How to get string feedback with UDP?
Kari
Posts: 13
I am trying to control a device via UDP and for some reason I can not watch strings to and from my device. I am creating a client connection and sending strings which are controlling the device - it is switching and blinking - but I can not view the strings with device notifications like I normally would. I am trying to view device 0:4:2. I do have the latest firmware.
I have tried adding send_string 0,"'Hey I'm online'" and send_string 0,"'I just got this text: ',data.text" in my DATA_EVENT online and string sections respectively. Neither seems get triggered (I can see other send_string 0 comments in the code). So I'm concerned that maybe I haven't made my connection correctly - although...I am controlling it...so something has to be right...? No?
My real problem is that the device only switches SOMETIMES and I can't figure out why. I would like to send a switch string until the device indicates it has executed the command. But I appear to be programming blind here.
Has anyone else had this problem and gotten around it? Is there some "'RXON'" for TCP/IP and/or UDP that I should be using? Do I need to view a different port:device:system? Can someone include a code snippet where they controlled something via this method and successfully received feedback?
Any help appreciated.
If it helps at all I am using an Analog Way Triplix which is connected to a Lantronix 2 port RS232 to UDP converter. The Triplix is connected to a switch along with a user PC, a control system, and 2 Analog Way DiVentiX image processors. I did try making a 3 headed RS232 "Medusa" cable, but this didn't work at all - the Triplix gets knocked off. UDP does seem to be the way to go, but this whole lack of string watching is driving me crazy.
I have tried adding send_string 0,"'Hey I'm online'" and send_string 0,"'I just got this text: ',data.text" in my DATA_EVENT online and string sections respectively. Neither seems get triggered (I can see other send_string 0 comments in the code). So I'm concerned that maybe I haven't made my connection correctly - although...I am controlling it...so something has to be right...? No?
My real problem is that the device only switches SOMETIMES and I can't figure out why. I would like to send a switch string until the device indicates it has executed the command. But I appear to be programming blind here.
Has anyone else had this problem and gotten around it? Is there some "'RXON'" for TCP/IP and/or UDP that I should be using? Do I need to view a different port:device:system? Can someone include a code snippet where they controlled something via this method and successfully received feedback?
Any help appreciated.
If it helps at all I am using an Analog Way Triplix which is connected to a Lantronix 2 port RS232 to UDP converter. The Triplix is connected to a switch along with a user PC, a control system, and 2 Analog Way DiVentiX image processors. I did try making a 3 headed RS232 "Medusa" cable, but this didn't work at all - the Triplix gets knocked off. UDP does seem to be the way to go, but this whole lack of string watching is driving me crazy.
0
Comments
Also try creating a buffer to handle returned strings so you can watch it in debug. I personally prefer created buffers over the data.text string handlers.
BTW it's not possible to switch the Analog Way (DiVentix) to an input, when there is actually no video source present. After selecting an input, you have to ask the device, which input is currently selected. I think it's definitely impossible to control this device without feedback processing!
Device notifications don?t work for IP so the best you can do is a SEND_STRING 0 under the STRING: handler inside the DATA_EVENT.
I don?t believe you will ever see data returned with an IP_CLIENT_OPEN device when you use UDP. A socket connection is not made like it is for TCP. UDP simply broadcasts the message. If you want to hear anything back from your device you will also have to do an IP_SERVER_OPEN and listen on the port.
Here is some sample code that does a loopback test for both TCP and UDP. This demonstrates what I?m talking about. You?ll see that the TCP Client and Server can both talk and listen to each other. And you?ll see that with UDP, the Server will hear what the Client has to say but the Client can?t hear anything back from the Server.
Throw the 4 variables in the debugger, open the diagnostics window, and push button 1.
Output:
Hope this helps.
slReturn = IP_Client_Open (nLocalPort, strIpAddress, nServerPort, 3)
I've used the Lantronix boxes like this with no problems.
--D
Yes, I saw the IP_UDP_2WAY flag with the IP_CLIENT_OPEN but I couldn?t get it to work in my loopback test. Any idea what I?m doing wrong? Could you possibility post a simple UDP loopback test?
What I tried before was to replace:
IP_SERVER_OPEN(dvUDPServer.Port,nUDPPort,IP_UDP)
IP_CLIENT_OPEN(dvUDPClient.Port,sNetlinx.IPAddress,nUDPPort,IP_UDP)
With just this:
IP_CLIENT_OPEN(dvUDPClient.Port,sNetlinx.IPAddress,nUDPPort,IP_UDP_2WAY)
But I still couldn?t see any UDP strings when I pushed button 1. If the IP_CLIENT_OPEN with IP_UDP_2WAY also opens up a listening port like an IP_SERVER_OPEN does, shouldn?t anything I send out be echoed back? Or is lack of sleep catching up with me.
Thanks for the insight.
Note: I?m testing with an NI-700 with the latest DUET firmware.
I've used this Lantronix box with 2-way UDP:
http://www.lantronix.com/device-networking/external-device-servers/xpress-dr-plus.html
Here's the line of code that I use to open the port:
I've had no problems with this. It sends and recieves as I would expect it to.
--D
You should try it with a spare master if you have one.
Thank you so much for your replies! I haven't dealt much with client/server stuff - eager to learn. Here is my code snippet which doesn't work. I'll try out your suggestions soon!
DEFINE_DEVICE
dvMaster = 0:1:2
dvAnalog1 = 0:3:2
dvAnalog2 = 0:4:2
DEFINE_EVENT
DATA_EVENT[dvMaster]
{
ONLINE:
{
IP_CLIENT_OPEN(3,'192.168.10.10',10800,3)
IP_CLIENT_OPEN(4,'192.168.10.11',10800,3)
}
}
DATA_EVENT[dvAnalog1]
{
ONLINE:
{
SEND_STRING 0,"'Analog Way #1 Online'"
}
OFFLINE:
{
WAIT 1 IP_CLIENT_OPEN(3,'192.168.10.10',10800,3)
}
STRING:
{
SEND_STRING 0,"'Analog Way #2 says: ',data.text"
}
}
DATA_EVENT[dvAnalog2]
{
ONLINE:
{
SEND_STRING 0,"'Analog Way #2 Online'"
}
OFFLINE:
{
WAIT 1 IP_CLIENT_OPEN(4,'192.168.10.11',10800,3)
}
STRING:
{
SEND_STRING 0,"'Analog Way #2 says: ',data.text"
}
}
You're not getting an online send_string 0 or your not getting the string send_string 0, or both
If you getting the online and not the send_string your device probably won't send anything until you give it a valid query or command.
Again, I would make a variable and create a buffer for each device and watch it in debug to see what comes in. Also try putting a send_string "device" with a valid command or query in the online event to initiate a response and then hopefully you'll get the send_string 0 from the string event.
Netlinx can connect to itself if I do an IP_CLIENT_OPEN along with an IP_SERVER_OPEN. The loopback works fine except as I noted originally, it’s only a 1 way conversation where the SERVER can hear the CLIENT (which is what I would expect) but the data does indeed get looped back.
One thing I noticed is I get the following runtime errors when I try to send data if I do an IP_CLIENT_OPEN with UDP 2WAY and use the broadcast IP. In my case 192.168.1.255
Line 1 :: SendString to socket-unknown sendto error 0x0 - 23:37:43
Line 2 :: CIpEvent::OnError 0:4:10 - 23:37:43
If I do an IP_CLEINT_OPEN with IP_UDP sans the 2WAY, then the broadcast IP works perfectly. I can send one message with Netlinx and every IP device I have on the network listening on that port receives the message. (The one to many paradigm that UDP offers is a real strength vs. the one to one with TCP)
At this point, I have no idea why I can’t get the 2WAY to work with my NI-700.
In my best Vinnie Barbarino voice – ‘I’m so confused!’
I don’t know about that. I do know the TCP loopback works fine
Do you mean send UDP to a spare master? I can’t do that at the moment but I have tried the 2WAY to talk with PCs on my network that have UDP broadcast and UDP listen apps running on them.
Put a WAIT 300 in front of the ONLINE: SEND_STRING 0s that you posted. That will give you enough time to open the diag window after a reboot. The ONLINE events are triggering. There just triggering before you can get in to see them.
As far as the rest, I’m clueless. I can’t get the 2WAY to work like dchristo has.
Joe Wrote: Do you have to use the boradcast to get loopback to work? That make mores sense than using the same IP but will the same IP work like 192.168.1.104 or what ever your master is?
Yes, by spare I meant another master but if the loopback works why bother
Netlinx can talk to itself via its own IP or with the broadcast IP but only if I do an IP_CLIENT_OPEN along with an IP_SERVER_OPEN. There is no scenario where the IP_CLIENT_OPEN with IP_UDP_2WAY works for me. I?m not going to lose any sleep over it since I can always do an IP_CLIENT_OPEN and an IP_SERVER_OPEN but I would like to know why I can?t get the 2WAY to work when others can. I don?t know if it?s just an NI-700 DUET thing or just a me stupid thing.
The reason you are not getting a loopback to work is because the IP_UDP_2WAY behaves differently than you expect. The 2WAY mode was designed to work with devices that interract in a specific way. Lets take a device that listens UDP on a specific port (say 10000) and when it responds, it responds to the IP and UDP Port that sent it the message. Many UDP devices work this way.
Let me walk you through the behavior.
IP_CLIENT_OPEN(dvUDPPort,'192.168.1.10',10000,IP_UDP_2WAY)
creates a socket on the NI and assignes the socket UDP port x (arbitrary and unique port number). The destination for SEND_STRINGs sent to local port dvPort is 192.168.1.10:10000. When the device responds to the NI, it send a message to our IP address UDP port x. The NI receives the message on UDP port x and sends it to the DATA_EVENT:STRING handler for local port dvPort.
Now your expected behavior was that the IP_CLIENT_OPEN to receive on the same UDP port number it sent to, in this case 10000. This could work for one device. But what if you wanted to control multiple devices? You would have multiple IP_CLIENT_OPENs, using different destinations, but all listening on the same UDP port. Any device that responded would send to the same UDP port, and we could not distinguish who originated the message in NetLinx code. Depending how the firmware was implemented, all messages would arrive on only one local port, or on every local port using that UDP port.
Instead the behavior implemented is multiple IP_CLIENT_OPENs using IP_UDP_2WAY use multiple and unique UDP port numbers to receive on, send messages to the destination IP and UDP port used in the IP_CLIENT_OPEN calls, and deliver the received messages from each device to their respective local port DATA handlers.
Sorry for the confusion. In reality this mode is made to work the way most UDP devices operate. Unfortunately is does not behave in a method that is similar to TCP which is what it appears what you expected.
Thanks for taking the time to post such a detailed response. Now I get it. I changed my PC app to send a message back on the remote port that the message came in on (UDP port x ).instead of sending back a message on the same local port and sure enough Netlinx is right on target and the IP_UDP_2WAY works perfectly. A couple of questions:
1) Is there any property I can inspect to see what arbitrary and unique port (UDP port x) that the NI assigns when doing a IP_CLIENT_OPEN with IP_UDP_2WAY?
2) If I want to use Netlinx to broadcast UDP on x.x.x.255 am I correct in assuming I have to do an IP_CLIENT_OPEN sans 2WAY?
Thanks again for your response. It?s always good to hear from an AMX guru.
In case I haven?t mentioned it before, AMX Rocks!
You MAY be able to use the 'UDPSENDTO' command to change the setting on the fly. The UDPSENDTO command allows you to change the destination IP and/or UDP port of a UDP local port on the fly.
SEND_COMMAND localPort, 'UDPSENDTO-<IP or URL>:<Port>'
SEND_COMMAND dvLocalPort,'UDPSENDTO-192.168.1.255:10000'
SEND_STRING dvLocalPort,"'Broadcasting this...'"
SEND_COMMAND dvLocalPort,'UDPSENDTO-someurl.com:10001'
SEND_STRING dvLocalPort,"'Unicasting this...'"
Off the top of my head, I'm not sure if it would work or whether the broadcast would give you an error without testing it under UDP_2WAY.
Chuck
Finally I got some time to sit down with this. I tried Joe's code out and I see what he's talking about. I got a UDP send message, but no response. But I want the response!
Joe, you mention a "PC app" that you send messages with - can you share? I'm not sure how to test this now that my devices have been hauled to the site.
Chuck, you lost me a bit.
I have Lantronix port1:
IP 192.168.10.10
Remote port 10800
Local port 10500
and Lantronix port 2:
IP 192.168.10.11
Remote port 10800
Local port 10600
I have this in code:
IP_CLIENT_OPEN(3,'192.168.10.10',10800,3)
IP_CLIENT_OPEN(4,'192.168.10.11',10800,3)
I thought I had the remote and local port switched, but I seem to get an error message whenI try to insert 10500 or 10600 instead of the 10800. It can't establish a connection. With 10800 I do not get an error message.
Is my problem that both remote ports are 10800? I would think even in this case I would get all devices communcations back, but I get nothing at all - not even the strings to the device.
Joe, do you have an updated code sample you could post or did you just change the way your PC app was communicating with your original code:
IP_CLIENT_OPEN(dvUDPClient.Port,sNetlinx.IPAddress,nUDPPort,IP_UDP_2WAY)
I appreciate your patience - I'm not really swift at networking.
Thanks so much!
Do you have code you can post?
I don't know how to do the cool insert code thing, but this is what I have. The local ports 10500 and 10600 are what I set inside the analog way switchers. I set both of them for remote port 10800. I don't know what the 10500 and the 10600 mean to me really.
dvMaster = 0:1:2
dvTP = 10001:1:2
//TCP/IP Devices
dvAnalog1 = 0:3:2 //Analog Way DiVenti-X #1
dvAnalog2 = 0:4:2 //Analog Way DiVenti-X #2
(***********************************************************)
(* VARIABLE DEFINITIONS GO BELOW *)
(***********************************************************)
DEFINE_VARIABLE
VOLATILE INTEGER nAWEffBtn[] = {91,92,93,94,95,96,97,98}
(***********************************************************)
(* STARTUP CODE GOES BELOW *)
(***********************************************************)
DEFINE_START
(***********************************************************)
(* THE EVENTS GO BELOW *)
(***********************************************************)
DEFINE_EVENT
DATA_EVENT[dvMaster]
{
ONLINE:
{
IP_CLIENT_OPEN(3,'192.168.10.10',10800,3)
IP_CLIENT_OPEN(4,'192.168.10.11',10800,3)
}
}
DATA_EVENT[dvAnalog1]
{
ONLINE:
{
SEND_STRING 0,"'Analog Way #1 Online'"
}
OFFLINE:
{
WAIT 1 IP_CLIENT_OPEN(3,'192.168.10.10',10800,3)
}
STRING:
{
SEND_STRING dvMaster,"'Analog Way #2 says: ',data.text"
}
}
DATA_EVENT[dvAnalog2]
{
ONLINE:
{
SEND_STRING 0,"'Analog Way #2 Online'"
}
OFFLINE:
{
WAIT 1 IP_CLIENT_OPEN(4,'192.168.10.11',10800,3)
}
STRING:
{
SEND_STRING dvMaster,"'Analog Way #2 says: ',data.text"
}
}
BUTTON_EVENT[dvTP,nAWEffBtn] //Analog Way Effects
{
PUSH:
{
SWITCH(GET_LAST(nAWEffBtn))
{
CASE 1: SEND_STRING dvAnalog1,"'0E'"
CASE 2: SEND_STRING dvAnalog1,"'1E'"
CASE 3: SEND_STRING dvAnalog1,"'6E'"
CASE 4: SEND_STRING dvAnalog1,"'7E'"
CASE 5: SEND_STRING dvAnalog1,"'8E'"
CASE 6: SEND_STRING dvAnalog1,"'9E'"
CASE 7: SEND_STRING dvAnalog1,"'10E'"
CASE 8: SEND_STRING dvAnalog1,"'11E'"
}
}
}
Since I no longer have the devices I'm still looking for a UDP type Hyperterminal program. I downloaded something called Hercules, but it appears to be for their products only?
Thanks for your responses.
FYI
http://amxforums.com/misc.php?do=bbcode has info on the special codes.
For code snippets use:
[noparse] [/noparse]
First I wanted to thank Chuck for his extremely detailed responses and everyone who helped generate ideas to help solve this problem.
The solution was to use an IP_Client to send stuff to the Analog Way devices and an IP_Server to parse stuff from the Analog Way just as Chuck had indicated. After adding in lots of send_string 0 statements I was bathing in device feedback - it was beautiful.
Because the Analog Way isn't always ready to accept commands and the time delays are variable - I really needed the feedback for reliable processing. If anyone ever finds themselves dealing with coding a DiVentiX - give me a call - I have all sorts of handy 'lessons learned'.
I never did locate a "hyperterminal" type program to emulate ethernet communications, so if anyone has advice on that - it would be lovely for the future.
Thanks again all!
Kari
Hello!
Sometimes I get a response from the equipment on UDP / IP, sometimes I do not get a response. When I test through the Hercules program, the answer always comes.
Help me please.
case 'STOP_4':
{
ip_server_open(16, 5000, IP_UDP)
ip_client_open(12,BsHO4_IP,5000,3)
wait(5){
send_string dv_Bs_Delivery1014_UDP, "'StopCL'"
wait(5){
send_string 0,"'Reply BS4:',BufferBs2,13,10"
if (find_string(BufferBs2, 'Stop_Ok',1)=0){
wait(5){
send_string dv_Bs_Delivery1014_UDP, "'StopCL'"
wait(5){
send_string 0,"'Reply BS4:',BufferBs2,13,10"
if (find_string(BufferBs2, 'Stop_Ok',1)=0){
wait(5){
send_string dv_Bs_Delivery1014_UDP, "'StopCL'"
wait(5){
send_string 0,"'Reply BS4:',BufferBs2,13,10"
if (find_string(BufferBs2, 'Stop_Ok',1)=0){
send_command 0:1:2, "'LOG, 2, Brightsign_Delivery4_1014 StopCL error'"
}
}
}
}
}
}
}
ip_client_close(16)
ip_server_close(12)
clear_buffer BufferBs2
}
}
}
Move your find_string(BufferBs2) evaluations to data_event[0:12:0]{string:{}}.
I'd also keep the server open
HARMAN_icraigie, thank you!
I changed it and it worked: