|
Post by pandawdy on Mar 15, 2020 14:57:42 GMT -5
Chris knows a LOT more about this than I do. But every explanation I read tells me that UDP is a connectionless protocol that simply pops a message out on the net. It is targeted at a specific IP and Port, fair enough. But because it is connectionless and because it should not expect a response I get confused. I would expect a programmed response from a connected device to be hard coded, one IP and one Port (or broadcast). So your device knows that it is talking (responding) to IP 9 Port 16000. That seems to be your setup. But it should be able to send a message at any time, not simply in immediate response to a received message. I have purchased a MKR1000 and I am in the throws of getting it onto my wifi network. Then I hope to properly explore UDP messaging. But it isn't turning out to be as simple a process as Arduino would have me believe. Where would we be without Chris's expertise, these youngsters! The message I'm sending to the device is just asking the device what it has programmed at a certain location. It's not an acknowledgement of a connection or anything like that. That's why it immediately responds. Normally this device doesn't transmit anything unless it's asked to. Funny you mentioned Arduino. This device uses an Atmel CPU like arduino.. but not the same software.
|
|
|
Post by Chris Iverson on Mar 15, 2020 15:03:24 GMT -5
It figures that someone stumbles across the one sockets scenario that I didn't account for in the DLL.
I know what's happening, now, and the simplest solution is, unfortunately, not currently available in my DLL: choose the port to send from.
This is something that's possible to do in normal sockets programming, it's just not usually done, because for the most part, it's usually not needed. You choose a destination port, the OS will handle randomly choose a sending port for you(specifically so you don't choose something that's already used, and wind up not being able to send), and the receiving side will simply send back to where the packet it received came from. 99% of the time, it doesn't matter what port you send from. Which is why I left the functionality out of my DLL.
It shouldn't take too long to add the functionality to the DLL, I just wasn't expecting to have to do so.
In the meantime, you might be able to get it to work by setting up a UDP listener on port 16000, sending the first packet using UDPConnect(), and then getting the response from the UDP listener.
Out of curiosity, is communication with this device only ever initiated from the PC? Or does the device send data to the PC on its own, as well?
UDP is a connectionless protocol, yes. That means you can just pick a destination IP and port, and transmit away. The destination will get your IP and port when they receive your message, and transmit back to that pair. Two-way communication over UDP is perfectly doable, but it's not reliable.
Unlike TCP, though, UDP does not guarantee message delivery, and it does not guarantee message order.
If you send messages 1, 2, and 3, the receiver may only receive messages 3,1, in that order.
That just means, if you're doing two-way communication using UDP, you need to do extra work to make sure you get everything in order. You need to be prepared for the scenario that you don't receive responses, and you need to be prepared for receiving responses out of order.
For some protocols, that won't matter. Many video and audio streaming protocols use UDP, because one dropped packet in the middle won't break the connection(although it may cause temporary audio/video quality drop or hiccups). VPN protocols often use UDP, both for speed, and because higher-level encapsulated layers already handle retransmission if something isn't received, and adding another layer doing so can actually have the opposite effect and wind up killing the connection.
|
|
|
Post by pandawdy on Mar 15, 2020 16:58:02 GMT -5
It figures that someone stumbles across the one sockets scenario that I didn't account for in the DLL. I know what's happening, now, and the simplest solution is, unfortunately, not currently available in my DLL: choose the port to send from. This is something that's possible to do in normal sockets programming, it's just not usually done, because for the most part, it's usually not needed. You choose a destination port, the OS will handle randomly choose a sending port for you(specifically so you don't choose something that's already used, and wind up not being able to send), and the receiving side will simply send back to where the packet it received came from. 99% of the time, it doesn't matter what port you send from. Which is why I left the functionality out of my DLL. It shouldn't take too long to add the functionality to the DLL, I just wasn't expecting to have to do so. In the meantime, you might be able to get it to work by setting up a UDP listener on port 16000, sending the first packet using UDPConnect(), and then getting the response from the UDP listener. Out of curiosity, is communication with this device only ever initiated from the PC? Or does the device send data to the PC on its own, as well? UDP is a connectionless protocol, yes. That means you can just pick a destination IP and port, and transmit away. The destination will get your IP and port when they receive your message, and transmit back to that pair. Two-way communication over UDP is perfectly doable, but it's not reliable. Unlike TCP, though, UDP does not guarantee message delivery, and it does not guarantee message order. If you send messages 1, 2, and 3, the receiver may only receive messages 3,1, in that order. That just means, if you're doing two-way communication using UDP, you need to do extra work to make sure you get everything in order. You need to be prepared for the scenario that you don't receive responses, and you need to be prepared for receiving responses out of order. For some protocols, that won't matter. Many video and audio streaming protocols use UDP, because one dropped packet in the middle won't break the connection(although it may cause temporary audio/video quality drop or hiccups). VPN protocols often use UDP, both for speed, and because higher-level encapsulated layers already handle retransmission if something isn't received, and adding another layer doing so can actually have the opposite effect and wind up killing the connection. In this case if a message fails, it wouldn't be a big deal. The only time this device tries to send a message to the PC is when the PC asks for it.
|
|
|
Post by Chris Iverson on Mar 15, 2020 22:22:23 GMT -5
New release of LBNet is up: github.com/iversc/lbnet/releases/tag/2.2.0-RC1New functions added UDPConnectFrom() and ConnectFrom(). They add a new parameter that lets you specify the local port used to send data. The new test file, test-udp-client-from.bas, uses UDPConnectFrom() to always connect using the local port 1600. If you run the test server, as well, you can see that the client will always connect from that port. You should be able to use that to get the data you need. EDIT: Oops, just realized that should've been port 16000 in the demo. Oh well, easy enough to change in the code itself, and it should still work for what you need once you correct it.
|
|
|
Post by Rod on Mar 16, 2020 4:43:48 GMT -5
I don't know enough about this yet. Is there a "listener" routine in the dll? one that sits and listens just like the device, the server? Anyways I can report success with the new poll and get response UDPConnectFrom() function.
I used port 16000 as a test. I stuck it in both sets of code. so the device was listening on 16000. Normally it was listening on 2390 but I was not sure which data item in UDPConnectFrom() was which. It should be possible to send to 2390 using port 16000 and get the response back on 16000 but I just set it all to 16000. Also if you fail you need to restart Liberty to clear the connection. I restarted the Arduino a couple of times as well but eventually it was up and stable. My virus checker kicked in at one point!
connectServer$ = "xxx.xxx.x.xxx" hSock = UDPConnectFrom(connectServer$, "16000", 0, "16000") if IsSocketInvalid(hSock) then print "Connect() failed. - ";GetError() goto [doEnd] end if
Firstly I sent a UDP packet using my UDP tool just to show the Arduino was up and running. Then I used our new dll to send a packet and get the response.
For any Arduino folks this was the Sketch, it is the plain vanilla UDP message and response example.
/* WiFi UDP Send and Receive String
This sketch wait an UDP packet on localPort using a WiFi shield. When a packet is received an Acknowledge packet is sent to the client on port remotePort
Circuit: * WiFi shield attached
created 30 December 2012 by dlf (Metodo2 srl)
*/
#include <SPI.h> #include <WiFi101.h> #include <WiFiUdp.h>
int status = WL_IDLE_STATUS; ///////please enter your sensitive data in the Secret tab/arduino_secrets.h char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP int keyIndex = 0; // your network key Index number (needed only for WEP)
unsigned int localPort = 16000; // local port to listen on
char packetBuffer[255]; //buffer to hold incoming packet char ReplyBuffer[] = "acknowledged"; // a string to send back
WiFiUDP Udp;
void setup() { //Initialize serial and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only }
// check for the presence of the shield: if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue: while (true); }
// attempt to connect to WiFi network: while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection: delay(10000); } Serial.println("Connected to wifi"); printWiFiStatus();
Serial.println("\nStarting connection to server..."); // if you get a connection, report back via serial: Udp.begin(localPort); }
void loop() {
// if there's data available, read a packet int packetSize = Udp.parsePacket(); if (packetSize) { Serial.print("Received packet of size "); Serial.println(packetSize); Serial.print("From "); IPAddress remoteIp = Udp.remoteIP(); Serial.print(remoteIp); Serial.print(", port "); Serial.println(Udp.remotePort());
// read the packet into packetBufffer int len = Udp.read(packetBuffer, 255); if (len > 0) packetBuffer[len] = 0; Serial.println("Contents:"); Serial.println(packetBuffer);
// send a reply, to the IP address and port that sent us the packet we received Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); } }
void printWiFiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID());
// print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip);
// print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }
|
|
|
Post by pandawdy on Mar 16, 2020 8:56:43 GMT -5
New release of LBNet is up: github.com/iversc/lbnet/releases/tag/2.2.0-RC1New functions added UDPConnectFrom() and ConnectFrom(). They add a new parameter that lets you specify the local port used to send data. The new test file, test-udp-client-from.bas, uses UDPConnectFrom() to always connect using the local port 1600. If you run the test server, as well, you can see that the client will always connect from that port. You should be able to use that to get the data you need. EDIT: Oops, just realized that should've been port 16000 in the demo. Oh well, easy enough to change in the code itself, and it should still work for what you need once you correct it. Chris, thanks a lot for your help. I haven't had a chance to test it out but I will let you know how it turns out as soon as I get a chance.
|
|
|
Post by pandawdy on Mar 16, 2020 9:26:28 GMT -5
Chris, I tested this and it seems to work well. You can see the results in the photo below. I added a line so I could see the data string going out to my device.. and the response is at the end. Really appreciate your help on this.
|
|
|
Post by pandawdy on Mar 16, 2020 9:51:39 GMT -5
Rod,
Was your test successful?
|
|
|
Post by Rod on Mar 16, 2020 11:02:13 GMT -5
@pandawady yes the poll and immediate response via UDPConnectFrom() worked well and I was able to get a response from the device within a second or so. I still think we should have "listening" capability on any designated port. Just need to find more time to play.
|
|
|
Post by Chris Iverson on Mar 16, 2020 11:22:36 GMT -5
Glad to hear it works!
Rod, take a look at the test-udp-server.bas file in the zip file for listening for UDP on ports. The function used to create the listener is UDPCreateListenSocket(srv$), where srv$ is a string indicating a service name("http") or port number("80") that you want to listen on.
|
|
|
Post by pandawdy on Mar 18, 2020 9:41:39 GMT -5
Chris, is there a help file or a readme that goes more in depth on all of the subs and functions in your DLL?
|
|
|
Post by Chris Iverson on Mar 18, 2020 11:42:54 GMT -5
Not yet. I've been planning to put a collective documentation together, but haven't had a chance to do so.
A good amount of the DLL is used in some way in the various test examples on the github site, but it's not always clear why yet.
If you do have any questions, I'd be glad to answer in the meantime.
|
|
|
Post by Rod on Mar 18, 2020 12:48:46 GMT -5
Any help file will be awesome. Just remember readers know nothing, absolutely nothing. Plug in the power, press reset, wait ten seconds all needs explained. Imagine your five year old nephew and write accordingly. Writing the code is just the first step. Look at what Alyce has provided.
|
|
|
Post by pandawdy on Mar 18, 2020 16:36:26 GMT -5
Not yet. I've been planning to put a collective documentation together, but haven't had a chance to do so. A good amount of the DLL is used in some way in the various test examples on the github site, but it's not always clear why yet. If you do have any questions, I'd be glad to answer in the meantime. Chris,
No problem. Just curious if you had something. Once you do have it I would like to download it.
|
|