• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Trying to send byte command to receiver over ethernet

 
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey all I am having an issue with trying to figure out why this code does not work. it never errors - it just doesn't do anything. I checked with my Onkyo iPhone app and it works and I'm using the same config as it is.

Here is the main code that sets up the command:

The output its sending looks like this:

ISCP������������������!1QSTN


And according to the documentation it looks right to me? enter image description here

And the rest of the System.out.printLn is this:


eISCP data size: 7(0x7) chars
eISCP msg size: 23(0x17) chars
Connected to 192.168.1.33 on port 60128
out_Init
inInit
sending 23 chars:
Ascii: ISCP???!1PWRQSTN
Hex: 0x49 0x53 0x43 0x50 0x00 0x00 0x00 0x10 0x00 0x00 0x00 0x07 0x01 0x00 0x00 0x00 0x21 0x31 0x51 0x53 0x54 0x4e 0x0d
sent!


Here is the full source code to the java app.

It would be great if someone who knows java sockets and byte code better than I jump in and help me out! Maybe there's just something I am missing or incorrectly inserting?
 
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmmm, this is weird.  At first I was rather put off by your using a StringBuffer to collect byte data - though it looks like you are then writing it with writeBytes(), which I guess will work as long as all the character data fits within 8 bits.  So maybe that's not actually a bug, but it certainly is confusing.

I think the one thing I see that still makes no sense to me is, why are you using an ObjectOutputStream for out_?  (I had to follow the link to see the complete code.). If you are doing object serialization as defined for Java, then this makes sense.  If you are doing anything else, then no, do not use an ObjectOutputStream; it makes no sense.  It will probably add additional header info and possible more.  I recommend replacing that with a DataOutputStream, which gives you very precise control of what you're writing.  Once you do that, you can probably drop all the StringBuilder stuff and write bytes directly.  Though then you might want an alternate way of displaying your hex output for debugging.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's something that could help you see the output in a human readable form:

Note that the output inside the parentheses will render a human-readable character, if a corresponding human-readable character exists.  If not, you get something cryptic and unreadable, depending on your system.

To attach to your code, try something like
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Here's something that could help you see the output in a human readable form:

Note that the output inside the parentheses will render a human-readable character, if a corresponding human-readable character exists.  If not, you get something cryptic and unreadable, depending on your system.

To attach to your code, try something like



I get the following:

eISCP data size: 10(0xa) chars
eISCP msg size: 26(0x1a) chars
Connected to 192.168.1.33 on port 60128
out_Init
inInit
sending 26 chars:
Ascii: ISCP??????
???!1PWRQSTN
Hex: 0x49 0x53 0x43 0x50 0x00 0x00 0x00 0x10 0x00 0x00 0x00 0x0a 0x01 0x00 0x00 0x00 0x21 0x31 0x50 0x57 0x52 0x51 0x53 0x54 0x4e 0x0d
writing byte   0: ffffffac (ᆲ)
writing byte   1: ffffffed (■)
writing byte   2:  0 (??)
writing byte   3:  5 ()
writing byte   4: 77 (w)
writing byte   5: 1a ()
writing byte   6: 49 (I)
writing byte   7: 53 (S)
writing byte   8: 43 (C)
writing byte   9: 50 (P)
writing byte  10:  0 (??)
writing byte  11:  0 (??)
writing byte  12:  0 (??)
writing byte  13: 10 ()
writing byte  14:  0 (??)
writing byte  15:  0 (??)
writing byte  16:  0 (??)
writing byte  17:  a (
)
writing byte  18:  1 ()
writing byte  19:  0 (??)
writing byte  20:  0 (??)
writing byte  21:  0 (??)
writing byte  22: 21 (!)
writing byte  23: 31 (1)
writing byte  24: 50 (P)
writing byte  25: 57 (W)
writing byte  26: 52 (R)
writing byte  27: 51 (Q)
writing byte  28: 53 (S)
writing byte  29: 54 (T)
writing byte  30: 4e (N)
writing byte  31:  d ()
sent!
received 32 bytes: "ISCP??????+???!1NJA2-http://19"
closed connections

 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And just sending the command without the query results in this:

eISCP data size: 8(0x8) chars
eISCP msg size: 24(0x18) chars
Connected to 192.168.1.33 on port 60128
out_Init
inInit
sending 24 chars:
Ascii: ISCP?????????!1PWR01
Hex: 0x49 0x53 0x43 0x50 0x00 0x00 0x00 0x10 0x00 0x00 0x00 0x08 0x01 0x00 0x00 0x00 0x21 0x31 0x50 0x57 0x52 0x30 0x31 0x0d
writing byte   0: ffffffac (ᆲ)
writing byte   1: ffffffed (■)
writing byte   2:  0 (??)
writing byte   3:  5 ()
writing byte   4: 77 (w)
writing byte   5: 18 ()
writing byte   6: 49 (I)
writing byte   7: 53 (S)
writing byte   8: 43 (C)
writing byte   9: 50 (P)
writing byte  10:  0 (??)
writing byte  11:  0 (??)
writing byte  12:  0 (??)
writing byte  13: 10 ()
writing byte  14:  0 (??)
writing byte  15:  0 (??)
writing byte  16:  0 (??)
writing byte  17:  8 ()
writing byte  18:  1 ()
writing byte  19:  0 (??)
writing byte  20:  0 (??)
writing byte  21:  0 (??)
writing byte  22: 21 (!)
writing byte  23: 31 (1)
writing byte  24: 50 (P)
writing byte  25: 57 (W)
writing byte  26: 52 (R)
writing byte  27: 30 (0)
writing byte  28: 31 (1)
writing byte  29:  d ()
sent!
closed connections

 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This part:

David Go wrote:


That is the extra header info created by the Java object serialization protocol, generated by ObjectOutputStream.  I don't think you need that, and it is probably the source of your problems.  Again, I recommend replacing the ObjectOutputStream with a DataOutputStream, as I showed.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Looks a little bit better but still do not seem to be sending the correct commands. What am I missing or doing incorrectly?

 
Sheriff
Posts: 28329
97
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Go wrote:Looks a little bit better but still do not seem to be sending the correct commands. What am I missing or doing incorrectly?


You are expecting binary data to be comprehensible when displayed as characters. That column where you convert to characters is worse than useless, mostly.

Based on your specs, the first 4 bytes are supposed to be the characters "ISCP", which they are. The next 4 bytes are supposed to be a thing named "Header Size" which, being a number, would be four bytes representing a number. Which they are: you see 00, 00, 00, and 10 which put together make a four-byte integer representing 10. Carry on from there and check that what you're seeing is compatible with the specs.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I just don’t fully understand all this byte and stuff sadly…  
 
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I can't help but notice that you end your commands with a [CR], but the spec says you need to end it with an [EOF].

According to the spec, [EOF] is 0x1A.

See also: https://en.wikipedia.org/wiki/Substitute_character#End_of_file
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This doesn't appear to be related to your problem, but why are you not using DataOutputStream to its full potential? I don't really get the wisdom behind writing binary data to a StringBuilder and then converting it back to binary.


 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Newer version of the code using DataOutoputStream.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:This doesn't appear to be related to your problem, but why are you not using DataOutputStream to its full potential? I don't really get the wisdom behind writing binary data to a StringBuilder and then converting it back to binary.



I'm not able to get this to run.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:You are expecting binary data to be comprehensible when displayed as characters. That column where you convert to characters is worse than useless, mostly.


Well, that (when formatted in columns at least) came from my suggested code.  I find it useful because several parts of the required format do correspond to printable characters - so printing the printable char in parentheses makes it easy to validate what it means.  But sure, many parts of the format are not printable - which is why the more important part of the output is the hex representation of the char.  The intent is to be able to use both, when possible, or just the one when that's all you have.
 
Paul Clapham
Sheriff
Posts: 28329
97
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Well, that (when formatted in columns at least) came from my suggested code.  I find it useful because several parts of the required format do correspond to printable characters - so printing the printable char in parentheses makes it easy to validate what it means.  But sure, many parts of the format are not printable - which is why the more important part of the output is the hex representation of the char.  The intent is to be able to use both, when possible, or just the one when that's all you have.


Yeah, sorry, it's useful for someone who knows the difference between bytes and characters, which I notice the OP has said they don't. But not understanding that makes it impossible to even evaluate whether you have a correct solution. So that's what needs to be remedied first.

What Is A Byte?
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

David Go wrote:I'm not able to get this to run.


In what way?  Compilation errors?  Runtime errors?  Something else?

I see that Stephan is changing a lot of things at one time, organizing things in ways that make sense to him, and me... but maybe that's too much at once for you.  You can also try making smaller changes in your existing code, moving in the direction he suggests.  The biggest part of this is also what I meant earlier when I said:

Mike Simmons wrote:I recommend replacing that with a DataOutputStream, which gives you very precise control of what you're writing.  Once you do that, you can probably drop all the StringBuilder stuff and write bytes directly.


See how Stephan is using DataOutputMethods like writeByte(), writeInt() and others.  Your whole getEiscpMessage() method could be replaced by something like Stephan's writeHeader() and sendMessage() methods, which just use the DataOutputStream methods directly, rather than first constructing a StringBuilder and then getting bytes from it.  

Fundamentally it bothers us when you're putting binary data like 0x10 and 0x10000000 into a StringBuilder, which is used for character data.  I treated each byte as a printable character in my code, when I did ((char) b) and formatted it with (%s) - but that was an optional thing for debugging purposes, not the primary mechanism by which we send data to the socket.  If you see an unprintable character in a print statement, it's not so concerning... but if the data is somehow getting mangled during transmission, that's more of a concern.

Having said that, I think your use of StringBuilder with writeBytes() here does actually work, without mangling the data.  (That is, if there's still an error, it's probably elsewhere.) But it's the sort of thing that seems questionable at best.  Don't treat binary data as text if you can avoid it.  Or unless you're printing optional debugging info, as I was.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That was posted before I saw Paul's reply above.  Sounds like we're all on about the same page here.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:

David Go wrote:I'm not able to get this to run.


In what way?  Compilation errors?  Runtime errors?  Something else?

I see that Stephan is changing a lot of things at one time, organizing things in ways that make sense to him, and me... but maybe that's too much at once for you.  You can also try making smaller changes in your existing code, moving in the direction he suggests.  The biggest part of this is also what I meant earlier when I said:

Mike Simmons wrote:I recommend replacing that with a DataOutputStream, which gives you very precise control of what you're writing.  Once you do that, you can probably drop all the StringBuilder stuff and write bytes directly.


See how Stephan is using DataOutputMethods like writeByte(), writeInt() and others.  Your whole getEiscpMessage() method could be replaced by something like Stephan's writeHeader() and sendMessage() methods, which just use the DataOutputStream methods directly, rather than first constructing a StringBuilder and then getting bytes from it.  

Fundamentally it bothers us when you're putting binary data like 0x10 and 0x10000000 into a StringBuilder, which is used for character data.  I treated each byte as a printable character in my code, when I did ((char) b) and formatted it with (%s) - but that was an optional thing for debugging purposes, not the primary mechanism by which we send data to the socket.  If you see an unprintable character in a print statement, it's not so concerning... but if the data is somehow getting mangled during transmission, that's more of a concern.

Having said that, I think your use of StringBuilder with writeBytes() here does actually work, without mangling the data.  (That is, if there's still an error, it's probably elsewhere.) But it's the sort of thing that seems questionable at best.  Don't treat binary data as text if you can avoid it.  Or unless you're printing optional debugging info, as I was.



My question is more toward how to use the following in my current code:

What function should I call that as it looks like its taking whatever is in the out_ and in_ variables - right? And what should the ExecutorService be?

And the error I got was this:

C:\Users\AndroidStudioProjects\OnkyoRC\app\src\main\java\com\example\onkyorc\MainActivity.java:400: error: cannot find symbol
           var bytes = string.getBytes(US_ASCII);
           ^
 symbol:   class var
 location: class MainActivity.EiscpController


 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You don't need to quote the whole previous post in your reply - we often like to see just the part that you're immediately replying to.

David Go wrote:My question is more toward how to use the following in my current code:

What function should I call that as it looks like its taking whatever is in the out_ and in_ variables - right? And what should the ExecutorService be?


Hmmm, I hadn't noticed that.  The ExecutorService looks like an idea Stephan had that he didn't implement here - you should probably just delete it, since it's not being used:

I would probably do something like this instead:

And

The idea here is that when you're done with the controller, you close it.  But you don't want to close it before you're done.  Because that will close the input and output streams, and you may want to keep using those.  To be honest, there's a good chance you never want to close this class - just keep it open for the life of your program.  Unless you ever need to switch to reading and writing with a different socket.

There are probably other changes cascading from here.  You might want to make changes more slowly, rather than using Stephan's class directly, if you're not sure how it's to be used.  

One general design question to think about: do you want to open a socket each time you execute a command?  And then close it (or allow it to close eventually) sometime later?  Or just open the socket once, and use the controller to listen and respond?  Stephen's code is guiding you to the latter.  But your existing code is more like the former.  

David Go wrote:And the error I got was this:

C:\Users\AndroidStudioProjects\OnkyoRC\app\src\main\java\com\example\onkyorc\MainActivity.java:400: error: cannot find symbol
           var bytes = string.getBytes(US_ASCII);
           ^
 symbol:   class var
 location: class MainActivity.EiscpController



That looks like you're using an older version of Java.  What JDK are you using?  It should be version 11 or later.  (Technically, 10, but why would anyone still be using 10 now?)  If you're using an IDE, it may also have some settings for the java language level.  In IntelliJ this is under Project Settings ->Project -> Language Level, which should also be at least 11.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:You don't need to quote the whole previous post in your reply - we often like to see just the part that you're immediately replying to.



David Go wrote:
That looks like you're using an older version of Java.  What JDK are you using?  It should be version 11 or later.  (Technically, 10, but why would anyone still be using 10 now?)  If you're using an IDE, it may also have some settings for the java language level.  In IntelliJ this is under Project Settings ->Project -> Language Level, which should also be at least 11.


Looks like I have it set to version 17


Mike Simmons wrote:Hmmm, I hadn't noticed that.  The ExecutorService looks like an idea Stephan had that he didn't implement here - you should probably just delete it, since it's not being used:


So is this where i put all of that? Right after it has tried to send the command the old way?

Not understanding how else I would get the in_ and out_ to be able to send it to EiscpController?

out_ is populated in the sendCommand() function and in_ is populated the queryCommand function. So i would think I need to wait until it gathers all that data before I can send it to EiscpController?

Mike Simmons wrote:
One general design question to think about: do you want to open a socket each time you execute a command?  And then close it (or allow it to close eventually) sometime later?  Or just open the socket once, and use the controller to listen and respond?  Stephen's code is guiding you to the latter.  But your existing code is more like the former.  


Yes it can be opened for the duration of the app. It says to do just that in the document:

Note: The communication between server and client should hold one connection continuously. Unless it has connected continuously, the notice of status cannot be performed from a client.

 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It looks like there's probably a mismatch in your [ quote ] tags above, making the quote somewhat garbled, unfortunately.  It may be too late to edit it - maybe a moderator will fix it for you.

I'm not really an Android dev, so I'm not sure what are best practices to set this up... but as a guess, I might try having one instance variable in MainActivity:

When the app starts up, in whatever method is appropriate, initialize it something like this:

If you ever need to close everything, that can be done from the controller.  Closing the streams will also close the underlying socket.  You don't need to save the socket in another variable - simply saving the controller gives you access to whatever methods you need.
 
David Go
Ranch Hand
Posts: 54
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well i tried this:


No errors but it sadly did not turn the receiver on  

writing byte   0: 49 (I)
writing byte   1: 53 (S)
writing byte   2: 43 (C)
writing byte   3: 50 (P)
writing byte   4:  0 (??)
writing byte   5:  0 (??)
writing byte   6:  0 (??)
writing byte   7: 10 ()
writing byte   8:  0 (??)
writing byte   9:  0 (??)
writing byte  10:  0 (??)
writing byte  11:  8 ()
writing byte  12: 10 ()
writing byte  13:  0 (??)
writing byte  14:  0 (??)
writing byte  15:  0 (??)
writing byte  16: 21 (!)
writing byte  17: 31 (1)
writing byte  18: 50 (P)
writing byte  19: 57 (W)
writing byte  20: 52 (R)
writing byte  21: 30 (0)
writing byte  22: 31 (1)
writing byte  23: 1a ()



Do i need to put anything for these or are they fine as-is?
 
Seriously Rick? Seriously? You might as well just read this tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic