Message Boards Message Boards

Streaming data from my robot to Mathematica over UDP

Posted 8 years ago

I have a robot from which I can send data to my C++ program over UDP on the LAN. Now I want to send those same data (live) to Mathematica to have a live Graphical Representation of my sensor values. Is it possible?

When I try to instantiate a Socket using the network loopback adapter (no matter what port I use) I get the below error:

In[6]:= socket = SocketConnect["127.0.0.1:8996"]
During evaluation of In[6]:= SocketConnect::connrefused: Connection refused by host 127.0.0.1, port 8996, during SocketConnect[127.0.0.1:8996]. >>
Out[6]= $Failed

or

In[8]:= socket = SocketConnect["192.168.1.77:8996"]
During evaluation of In[8]:= SocketConnect::connrefused: Connection refused by host 192.168.1.77, port 8996, during SocketConnect[192.168.1.77:8996]. >>
Out[8]= $Failed

UDP itself is a very simple networking protocol, but if I cannot even get a socket to read from then I am not sure what to do with the SocketConnect[] function. It seems to work fine to connect to website on port 80 so why can't I get a socket object locally? By the way I tried to turn off Norton just to make sure that was not interfering with the code but the result was exactly the same so my AV has nothing to do with the issue. Please help, some code samples would be nice as there is literally nothing in terms of Code Sample or Tutorial, not even in the form of a community contributed UDP Networking example. Thank you.

POSTED BY: LV VS
9 Replies
Posted 4 years ago

Thanks a lot for sharing, Ian.

The error occurs because the InetAddress class has not been loaded. Add this line after InstallJava[]:

LoadJavaClass["java.net.InetAddress"]
POSTED BY: Marcus M
Posted 6 years ago

Hi Ian, I'm getting the exact same error as Pedro. Using version 11.3

POSTED BY: Diego Zviovich

Hi,

When applying the above code, I get the following message after using the writeSocket:

writeSocket[udpSocket, "127.0.0.1", 5000, ToCharacterCode["hello from mathematica"]]

JavaNew::argx: Incorrect number or type of arguments to constructor for class java.net.DatagramPacket. The arguments, shown here in a list, were {{104,101,108,108,111,32,102,114,111,109,32,109,97,116,104,101,109,97,116,105,99,97},22,InetAddress`getByName[127.0.0.1],5000}.

Java::argx1: Method named send defined in class java.net.DatagramSocket was called with an incorrect number or type of arguments. The argument was $Failed.

$Failed

any idea why?

POSTED BY: Pedro Fonseca
Posted 6 years ago

Hi,

When applying the above code, I get the following message after using the writeSocket:

writeSocket[udpSocket, "127.0.0.1", 5000, ToCharacterCode["hello from mathematica"]]

JavaNew::argx: Incorrect number or type of arguments to constructor for class java.net.DatagramPacket. The arguments, shown here in a list, were {{104,101,108,108,111,32,102,114,111,109,32,109,97,116,104,101,109,97,116,105,99,97},22,InetAddress`getByName[127.0.0.1],5000}.

Java::argx1: Method named send defined in class java.net.DatagramSocket was called with an incorrect number or type of arguments. The argument was $Failed.

$Failed

any idea why?

POSTED BY: Updating Name

Ah. Copy/pasting the writeSocket function to the reply section here seems to have taken out some necessary formatting. When I added back in the underscores for the function arguments and matched those arguments to the variables in the function body, all is good.

Good to hear.

POSTED BY: Ian Johnson

Hi,

Unfortunately SocketConnect doesn't yet support UDP sockets like you are describing. However, you can use J/Link to create a DatagramSocket Java object to accomplish the same thing. I have some example code below.

Needs["JLink`"];
InstallJava[];
udpSocket = JavaNew["java.net.DatagramSocket", 5000];

This creates a socket object that you can send and receive with using the methods receive and send. Both of these methods take a DatagramPacket object as their arguments, which can be created with JavaNew as below in the Module.

readSocket[sock_, size_] := 
    JavaBlock@
       Block[
         {datagramPacket = JavaNew["java.net.DatagramPacket", Table[0, size], size]},
         sock@receive[datagramPacket];
         datagramPacket@getData[]
       ]

To write a byte array to the socket, you can use the following function, which will use the provided socket to send data over UDP :

writeSocket[sock_, dest_String, port_Integer, data_ /; AllTrue[data, IntegerQ[#] && # >= 0 && # <= 255 &]] := 
    JavaBlock@
        sock@send[
            JavaNew["java.net.DatagramPacket", data, Length[data], InetAddress`getByName[dest],port]
        ]

Here's an example of sending data to a socket and receiving it:

writeSocket[udpSocket, "127.0.0.1", 5000, ToCharacterCode["hello from mathematica"]]

Then read in the raw byte data:

readSocket[udpSocket, 40]

{104, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 109, 97, 116, 104, 101, 109, 97, 116, 105, 99, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

This can be turned back into the original string with FromCharacterCode:

DeleteCases[%, 0] // FromCharacterCode    

"hello from mathematica"

I hope this helps, and I'd be delighted to hear more about your robot.

Thanks, Ian

POSTED BY: Ian Johnson

Hi Ian, I'm having trouble getting this example to run as written (Mathematica version 11.0.1.0) -- seems to be something in the writeSocket function, possibly InetAddress, but I can't figure it out. Anyone else having trouble? Thanks, Chris

Hi Christopher,

What exactly is the error message you're seeing? It's possible that there were changes in 11.0.1 that broke the code I posted above.

Thanks,

Ian

POSTED BY: Ian Johnson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract