create delay in UDP read

Hi,

I am trying to read the messages that TouchOSC is sending. I have an enc28j60 connected to my arduino uno 328.
My goal is to read out messages send by TouchOSC without having a computer in between. It is already working, but i still have 2 questions.

In TouchOSC I have a couple of push buttons that have an "pressed" and an "released" value.

This control sends the second value of its value range when pressed and the first value of its value range when released.

The "Pressed" value is 1 and the "released" value is 0.

for now my code gives me the following serial output if i press an push button one:

initialize: success
received: '/1/push1'
remote ip: 192.168.178.18
remote port: 62199
restart connection: success
 
received: '/1/push1'
remote ip: 192.168.178.18
remote port: 62199
restart connection: success

/1/ means on which page the object is on, push1 is the name of the push button their also should be a value but i can't get that value.

The first block of info is when i press the push button and the second block is when i release the push button.

So my question is:
1: is it possible to only get the first block of information(the message's are received about 50 milliseconds apart, so I was thinking about some kind of timeout?).

2: Is it possible to also get the value that ToucOSC is sending?

my code is based on the UDPserver example from the UIPEthernet library :

#include <UIPEthernet.h>

EthernetUDP udp;

void setup() {

  Serial.begin(9600);

  uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

  Ethernet.begin(mac,IPAddress(192,168,178,88));

  int success = udp.begin(5000);

  Serial.print("initialize: ");
  Serial.println(success ? "success" : "failed");

}

void loop() {

  //check for new udp-packet:
  int size = udp.parsePacket();
  if (size > 0) {
    do
      {
        char* msg = (char*)malloc(size+1);
        int len = udp.read(msg,size+1);
        msg[len]=0;
        Serial.print("received: '");
        Serial.print(msg);
        free(msg);
      }
    while ((size = udp.available())>0);
    //finish reading this packet:
    udp.flush();
    Serial.println("'");
    int success;
    do
      {
        Serial.print("remote ip: ");
        Serial.println(udp.remoteIP());
        Serial.print("remote port: ");
        Serial.println(udp.remotePort());
       
        //send new packet back to ip/port of client. This also
        //configures the current connection to ignore packets from
        //other clients!
        success = udp.beginPacket(udp.remoteIP(),udp.remotePort());
    //beginPacket fails if remote ethaddr is unknown. In this case an
    //arp-request is send out first and beginPacket succeeds as soon
    //the arp-response is received.
      }
    while (!success);

    udp.stop();
    //restart with new connection to receive packets from other clients
    Serial.print("restart connection: ");
    Serial.println (udp.begin(5000) ? "success" : "failed");
    Serial.println(" ");
    delay(200);
  }
}

So my question is:
1: is it possible to only get the first block of information(the message's are received about 50 milliseconds apart, so I was thinking about some kind of timeout?).

There is only one block of information. The block is sent twice - once for the press and once for the release.

You could keep track of whether the switch is pressed or released, by toggling a value every time the data for push1 arrives.

Or, you could go back to the code on the sender and figure out why it is not sending different data for press and release.

2: Is it possible to also get the value that ToucOSC is sending?

You are getting whatever the sender is putting in the UDP packet. Since that doesn't appear to be enough information, the problem appears to be on the sender end.

the blocks of info appear to be the same however they are not because the first block has the value of 1 and the second block has a value of 0. Those value's just aren't showen.

With wireshark i managed to get the raw hex data from the message that is being sent:
when pressed it sends: 2f312f7075736831000000002c6600003f8000000
converted to text: /1/push1,f??

when released it sends: 2f312f7075736831000000002c660000000000000
converted to text: /1/push1,f

so i think it does send the value with it, but how to get the value ?

Why are you stopping and starting the udp service?

    udp.stop();
    //restart with new connection to receive packets from other clients
    Serial.print("restart connection: ");
    Serial.println (udp.begin(5000) ? "success" : "failed");
    Serial.println(" ");
    delay(200);

Ah. So, the actual value is a non-printing character, and you want us to help you get that from what is printed. No. ain't gonna happen.

You do, though, know where in the data stream the value of interest is. And, now you know that it is a non-printing character (byte), so you should have some idea how to get the value.

@surfertim

If i don't call a udp.stop it keeps thinking it is receiving messages and will keep printing the "remote ip" and the "remote port".

The udp is restarted again after this stop.

@PaulS

So if i understand correctly, I can't decode the non-printing character but i could make some kind of function where if the non-printing character equals an other equal non-printing character and their by giving it a printable character?

So if i understand correctly, I can't decode the non-printing character

Sure you can. You just can't print the byte as a character. You can print the bytes in other formats, though, to see the whole message the same way that wireshark showed it to you. Make your decisions based on the binary value, not the printed representation of the binary value (when the printed representation isn't defined for that binary value).

Thank you very much PaulS i will start working on it.

I have one question left: because it sends a message when pressed and released, and i don't really need the second message. How can I program it so that it will ignore every second message ?

and i don't really need the second message. How can I program it so that it will ignore every second message ?

Think about this for a second. What you are asking is "How can I make the Arduino do nothing when the message is X".

Does rephrasing the question help?

Sorry for the stupid question. I should have thought about it a little more before asking.

I managed to receive the HEX message that TouchOSC is sending.

This is what I receive now:

From 192.168.178.18
2F312F7075736832320002C66000000
, port 57932
Contents:
/1/push22

Received packet of size 20
From 192.168.178.18
2F312F7075736832320002C66003FFFFFFF8000
, port 57932
Contents:
/1/push22

Their is just one thing left wich i can't seem to figure out.
I need to store that HEX value in a variable so i can compare it to the same HEX value but then in a string format.
I don't know how to store it.

What I want to achieve is something like:

if(IncomingHex == "2F312F7075736832320002C66000000 "){
digitalWrite(LedPin, HIGH);
}

My code:

#include <Dhcp.h>
#include <Dns.h>
#include <ethernet_comp.h>
#include <UIPClient.h>
#include <UIPEthernet.h>
#include <UIPServer.h>
#include <UIPUdp.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 178, 88);

unsigned int localPort = 5000;      // local port to listen on


// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back
char IncomingByte;

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  Serial.begin(9600);
}



    

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  //char packetcontents = Udp.parsePacket();
  if(packetSize)
  {
    //Serial.println(packetcontents, HEX);
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    
    Serial.println(" ");
    
 for (int i =0; i < 20; i++)
    {
      
      Serial.print(packetBuffer[i], HEX);
     
    }
    
 
 Serial.println(" ");
    
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);
    Serial.println(" ");
    Serial.println(" ");
    
    
    
  }
  delay(10);
}

I need to store that HEX value in a variable so i can compare it to the same HEX value but then in a string format.

Why do you need to compare the value AS A STRING? It isn't a string that you receive.

for (int i =0; i < 20; i++)
    {

      Serial.print(packetBuffer[i], HEX);

    }

This makes it hard to see where a value starts and ends. The blank lines do not help make the code more readable. Printing a space after each character would be helpful, as would printing each byte as both a character and a hex value.

I don't necessarily need to compare it to a string. What i want to do is, when i press a button i TouchOSC a LED will light up on my arduino. I thought the easiest way to do this is if the raw HEX data received by the arduino is the same as a previous stored value the light will go on.

I added the blank link lines in my code so that every thing is put underneath each other.

when i remove the ", HEX". This is the serial outcome:

From 192.168.178.18
/1/push22,f (some non-printing characters)
, port 57270
Contents:
/1/push22

Received packet of size 20
From 192.168.178.18
/1/push22,f??
, port 57270
Contents:
/1/push22

when i try to put a space after every character with this code:

 for (int i =0; i < 20; i++)
    {
      
      Serial.print(packetBuffer[i], HEX);
     if (i > 1)
      {
        Serial.print(" ");
      }
    }

I get:

Received packet of size 20
From 192.168.178.18
2F312F 70 75 73 68 32 32 0 0 0 2C 66 0 0 0 0 0 0
, port 57270
Contents:
/1/push22

Received packet of size 20
From 192.168.178.18
2F312F 70 75 73 68 32 32 0 0 0 2C 66 0 0 3F FFFFFF80 0 0
, port 57270
Contents:
/1/push22

when i try to put a space after every character with this code:

Let me ask this. Does it matter if you get
xxxxxx
vs.
xxxxxx?

To me, it doesn't. So, unconditionally print the space.

If it matters to you, the space that you don't want to print is the one when i is 19, not the ones when i is 0 and 1.

To me it doesn't really matter about the spaces.

However I can't get the spaces everywhere.
Now i am getting this: 2F312F70 75 73 68 32 32 0 0 0 2C 66 0 0 3F FFFFFF80 0 0

with this code:

 for (int i =0; i < packetSize; i++)
    {
      
      Serial.print(packetBuffer[i], HEX);
     if (i > 2)
      {
        Serial.print(" ");
      }
    }

How would I not print a space when i is 19 but do print when i is not 19?

Edit:

here is a link that explains the OSC packet protocol
http://opensoundcontrol.org/spec-1_0
http://opensoundcontrol.org/spec-1_0-examples#addressparts

I think the UDP message that TouchOSC sends consists of a HEX part and a FLOAT32 part?

     if (i > 2)

So, don't print a space when i is 0, 1, or 2. Why not?

How would I not print a space when i is 19 but do print when i is not 19?
if(i != 19)
   Serial.print(" ");
I think the UDP message that TouchOSC sends consists of a HEX part and a FLOAT32 part?

Well, we won't know that until you print a space after every byte.

I did as you told now i get:

Received packet of size 20
From 192.168.178.18
2F 31 2F 70 75 73 68 32 32 0 0 0 2C 66 0 0 0 0 0 0
, port 54253
Contents:
/1/push22

Received packet of size 20
From 192.168.178.18
2F 31 2F 70 75 73 68 32 32 0 0 0 2C 66 0 0 3F FFFFFF80 0 0
, port 54253
Contents:
/1/push22

2F 31 2F 70 75 73 68 32 32 0 0 0 2C 66 0 0 0 0 0 0

Look at the ASCII table. 2F = '/'. 31 = '1'. etc. So, what you have is "/1/push22" followed by some numeric values. Exactly what they mean, I don't know.

When you print the array as a string, the 0 is a NULL, so it terminates output.

Is push22 the name of a widget in your sending application?

Yes the name of the widget.

The OSC protocol sends the value of the widget in a int32 or a float32 format, if I understand the information on this website
http://opensoundcontrol.org/spec-1_0-examples#addressparts

The OSC Message with the OSC Address Pattern "/oscillator/4/frequency"
and the floating point number 440.0 as the single argument would be represented
by the following 32-byte message:

2f (/) 6f (o) 73 (s) 63 (c)
69 (i) 6c (l) 6c (l) 61 (a)
74 (t) 6f (o) 72 (r) 2f (/)
34 (4) 2f (/) 66 (f) 72 (r)
65 (e) 71 (q) 75 (u) 65 (e)
6e (n) 63 (c) 79 (y) 0 ()
2c (,) 66 (f) 0 () 0 ()
43 (C) dc (Ü) 0 () 0 ()
The next example shows the 40 bytes in the representation of the OSC Message
with OSC Address Pattern "/foo" and 5 arguments:

The int32 1000
The int32 -1
The string "hello"
The float32 1.234
The float32 5.678
2f (/) 66 (f) 6f (o) 6f (o)
0 () 0 () 0 () 0 ()
2c (,) 69 (i) 69 (i) 73 (s)
66 (f) 66 (f) 0 () 0 ()
0 () 0 () 3 () e8 (è)
ff (ÿ) ff (ÿ) ff (ÿ) ff (ÿ)
68 (h) 65 (e) 6c (l) 6c (l)
6f (o) 0 () 0 () 0 ()
3f (?) 9d () f3 (ó) b6 (¶)
40 (@) b5 (µ) b2 (”) 2d (-)

The OSC protocol sends the value of the widget in a int32 or a float32 format, if I understand the information on this website

Your example, with the push button widget then should be sending "/1/push22" followed by 4 bytes containing the value, for a total of 13 bytes. Why does it send 20? Perhaps, we are expected to ignore the last 7.

But, in both cases (pressed and released), the value bytes would be 0, 0, 0, and 2C. That doesn't make sense to me. So, apparently, those next 4 bytes are not the value. It would appear that the 2C in the message (a comma) is the separator between the ASCII name and the binary data portion of the message.

So, in your case, the information of interest is either 66 0 0 0 0 0 0 or 66 0 0 3F FFFFFF80 0 0. The 66 (f), apparently, means the the bit stream is a float, so the next 4 bytes (0 0 0 0 or 0 0 3F FFFFFF80) are the value of interest.

Now, I can't imagine why a digital push button sends a float value, but it's an Apple thing, I guess.

You could use a union to manipulate the 4 bytes as a float.

typedef union
{
  byte b[4];
  float f;
} 
crap;

crap c;

Set c.b[0], c.b[1], c.b[2], and c.b[3] to the 4 bytes that follow the byte after the 2C (,), if that byte is a 66 (f). Then, c.f will be the value of interest.