Send String via UDP to Server

Hello,
I am new here and I have problems to finish my Programm. I have one Arduino which is connected via Network to a Apache Server.

On my Arduino Uno is a Ethernet Shield and a 3x4 Matrix Keypad connected. I can read in all of my Keys. The Arduino will work as a door unlocker. The user tipes in a password *1234# the arduino will send the Password via UDP to the Apache server, the server checks the number(which is a membernumber) if the person belongs to the company the server posts a HTTP page with a Y for Yes, the Arduino reads in the Y and opens the door.

Here is my code: I am not a programmer just a technican, so sorry If something isn't written write.

Sorry, I took out the code because of a workshop in my company, we don't want to make life to easy for our apprentice, I will publish the full and finished code on thursday this week, when the workshop is over.

Thanks for helping me out :slight_smile:

UDP is not the right protocol for this.

Connect to your server, and send a GET request, and pass the password as a parameter all in one TCP connection using Client. IE, if the password parsing page is password.html, say:

GET /password.html?pword=xxxx

You will save yourself a lot of trouble if you develop this in parts. You can verify that the server is working properly by using telnet.

If you type:
telnet 172.30.11.241 80

you'll connect to your server. Then you can type in commands like GET. You'll see exactly what the arduino would see.

Then program your arduino to send what you typed and read what the server sends back.

There's a good chance your server will require a HTTP 1.1 GET request. It's two lines:
GET /password.html?pword=xxx HTTP/1.1
HOST www.myhost.com

@berlin86
Interesting project, what me "worries" is that you want to sent the password over the network in plain text. If you want to make a secure system (remember it is a door unlocker!) the Arduino should encrypt the password and send the encrypted version to the server. The server stores only encrypted passwords, it doesn't need to know them in plain text. The server on his turn, should not send a plain text Yes or NO but also an encrypted message that the arduino can decipher.

A simple encryption XOR's the password with a "secret string" that is only known to the Arduino and the server. Relative easy to break but it's a starting point.

int i = 0, j = 0; 
while (i <= strlen(data) )
{
  data[i] ^= key[j];
  i++;
  j = (j+1) % strlen(key);
}

A more secure system are Question Answer systems (dont know their official name). The Arduino sends a string "1276534342654872635" and the Server answers with "73652493237592387429". The Server knows how to extract the password from the string sent by the Arduino and the Arduino knows how to extract the answer from the string from the Server.
example decoding the answer: the secret code can be: the first digit in the answer is the digit to test (so test 7th digit which is a 3). if its even it is a yes if it is odd the answer is no (3 is odd => NO). All other digits are noise. Another code could be be add up the digits and test if divisable by 5 etc. These QA tests are easy and fast but quite difficult to break, especially as there are so many ways to send yes/no.

DCContrarian is right that you should develop the system step by step. The encryption discussed above is certainly not the first one. You should first get the password collection right before try sending it to the server. just make a stub function in the Arduino to simulate the server
boolean checkOnServer(string password)
{
// if password is in some list return true else false;
// or just return true;
}

If that works its time for the next step.

sofar my 2 cents,
Rob

@DCContrarian
Thanks for the hind, i will try it this way, looks way easier then the UDP protocol.
Do you have a example for the get and send, password as parameter with using CLIENT?

@robtillaart
Thanks for your tip, this is just a internal project for our second year apprentice, to check there abillity to adapt to new tasks.
If we would use this we would use password encrypt and also the xbee wireless boad plus RFID chips to make our employees the entrace as easy as possible.
But it is a gret hind, thanks.

I have read the UDPsend and recive string, but when you compile it, it is not working because of UDP issues, I am just a apprentice 3 year and try to find the easiest way to make it work.

berlin86:
@DCContrarian
Thanks for the hind, i will try it this way, looks way easier then the UDP protocol.
Do you have a example for the get and send, password as parameter with using CLIENT?

Look at the example in the Arduino reference:
http://www.arduino.cc/en/Reference/ClientConstructor

From there, two directions to go in. Try replicating the example using telnet:
telnet 64.233.187.99 80
GET /search?q=arduino HTTP/1.0

Then try creating a page on your own server and replacing the IP address with your IP address and the page name with your page name.

How much of your project has been successful so far? I don't know about UDP and apache, but strings can be sent to apache using the GET request, which apache will set as the environmental variable "query_string" on a windows machine running apache. The query_string is the part of a URL that follows the "?". You will need some application running on the pc to process the supplied data and return the output to apache for return to the arduino client.

@zoomkat
PHP can create UDP sockets - PHP: socket_create - Manual - so it is makeable .. The advantage os using UDP is that it is faster than TCP as no handshake is done. The price is that sometimes packets are dropped if network is too busy. Normally in a network at home this won't happen. In protocols where minimization of network latency is important the use of UDP is prefered above TCP. e.g. NTP.

imho UDP is very interesting for Arduino as time not spent on networking can be used to do other things.

robtillaart:
A more secure system are Question Answer systems (dont know their official name).

That's called "challenge-response authentication".

I wonder whether you can actually get a response back if you send the request to the Apache server via UDP. Doesn't it require an IP connection? I could be wrong, though, since I've never tried it.

robtillaart:
imho UDP is very interesting for Arduino as time not spent on networking can be used to do other things.

Although the examples tend to spin waiting for the server's response to completely arrive, that's not essential. I've done applications where the Client and response buffer are declared globally. After sending the request, the response is accumulated into the buffer by checking client.available() on every pass through loop().

It's a little trickier than the examples, but it enables the Arduino to get on with other work while the Wiznet chip handles the low-level details.

That's called "challenge-response authentication".

Thanks, I recall the name again !

I wonder whether you can actually get a response back if you send the request to the Apache server via UDP. Doesn't it require an IP connection?

Just as TCP, UDP runs on top of IP. IP itself is a datagram protocol (quite like UDP) that doesn't use handshakes, just send that message. UDP datagrams contain the addressinfo of the sender to inform the receiver who to call back to response (if one want/need to). More tech see - User Datagram Protocol - Wikipedia

Hi to all,
I have finished it, is working well, you only have to use EEPROM clear as well in order to save memory! I will publish it by the end of the week, till then I have to remove the code, because of a company workshop for our apprentice, and we don't want to make life to easy for them.

Sorry for the delay, and thanks for the help, I will do a my final apprentice project in the next view month with Arduino. Xbee wireless and RFID solution, to make it work comfortable and usefull on a daily basis.

Take care

Hi to all, here is the code which I have developt for Arduino with Keypad and Database.

// Include libraries
#include <SPI.h>
#include <Ethernet.h>
#include <Keypad.h>
#include <EEPROM.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x34, 0x99 }; //Arduino MAC
byte ip[] = { 172,20,12,28 };        // Arduino IP
byte router[] = { 172,20,12,253 };   // Network Router IP 
byte server[] = { 172,20,12,145 };    // Server IP
Client client(server, 80);           // Serverinformation for client, were to send data


 //---------------------------------------

const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
int  i = 0;          // Counter for password
char passwort[] = {'0','0','0','0','0','0'}; // Password array of 6 signs

 //----------------------------------------------------------
 
char keys[ROWS][COLS] = // Keymap define

{
	{'1','2','3'},
	{'4','5','6'},
	{'7','8','9'},
	{'*','0','%'}  // # can't be used, it is a used variable of apache Server, replaced by %
};

byte rowPins[ROWS] = {3, 8, 7, 5}; // Connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 2, 6};    // Connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  // Define keypad variables from keypad.h and

 //----------------------------------------------------------

void setup() //Single Task
{
  
  pinMode(12, OUTPUT);  // Define Pin 12 as OUTPUT 13= not so strong for output current(used by system as check led)
  Serial.begin(9600);   // Boudrate at 9600 bits/s 
  
  //for (int i = 0; i < 512; i++) // Write a 0 to all 512 bytes of the EEPROM
  //EEPROM.write(i, 0);  
  //Serial.println("EEPROM empty" );  
}

 //----------------------------------------------------------
 
 
 void loop() //Repeat Task

{
         char pass = '1'; // While true check for key pressed
         while ( 1 )
        
          {
        
             pass = keypad.getKey(); // Read in key's
        
             if (pass != NO_KEY) break; // Break to stop loop
                
          }
          
            Serial.println(pass); // Print key
          
            passwort[i] = pass; // Write single key in char array passwort
            i++;
         
            if ( i == 6 ) // When password array of 6 charecters are full, go to functions
           { 
              sendpass(passwort);    // Take variable password to function sendpass
              char c = getdata();    // Start funktion getdata with c as get variable
              ckeckdata(c);          // Check server information about password 
              i = 0;                 // Reset password to zero
           }
}                         
                                   
 //----------------------------------------------------------
 

 void sendpass(char* passwortsend)    // Send password to Server
 
 {
       String p;                      // Counting password array together to be ready fpr TCP/IP
       for ( int j=0; j<6; j++)       // Convert password array to string password
       {
       p += passwortsend[j];
       }
       for (int i = 0; i < 512; i++) // Write a 0 to all 512 bytes of the EEPROM
       EEPROM.write(i, 0);  
       Serial.println("EEPROM empty" ); 
       Serial.println(p);
       Serial.println("ethernet...");
       Ethernet.begin(mac, ip, router); // Start the Ethernet connection MAC,IP,Router
       Serial.begin(9600);              // Start the serial library
       delay(3000);                     // Give the Ethernet shield 3 second to initialize
       Serial.println("connecting...");

 
  if (client.connect())          // If you get a connection, report back via serial
  { 
        String s = ("GET /cgi-bin/post.pl?I=2&W="); // Send password to URL with GET order /cgi-bin/=Apache Server   post.pl=perl script for database communication   ?=start parameter  &=link data
        s += p;                                     // Combine s=URL and p=password
        Serial.println("connected"); 
        Serial.println(s); // Show password string with URL
        client.println(s); // GET password send to server  
}
  
  else {
   
        Serial.println("connection failed");  // Didn't get a connection to the server
  }
  
 }
 
 //----------------------------------------------------------

 char getdata()        //Get Y or N from Server
 
 { 
 char data;
      
    while (1)
  {
        if (client.available()) 
  {
        Serial.println("Data Read"); // Waiting for answer from Apache
        data = client.read();
        Serial.print(data);
    break;
  }

  }                                        
      if (!client.connected())     // If server's disconnected, stop the client
  {
         Serial.println(data);
         Serial.println("disconnecting.");
         
    client.stop();   
  }
  return data;
}
 
 //----------------------------------------------------------
 
 void ckeckdata(char data)

 {                                     
       if (data == 'Y') // Y Password check  
      
       {   
          for (int i = 0; i < 512; i++) // Write 0 to all 512 bytes of the EEPROM
           EEPROM.write(i, 0);  
           Serial.println("EEPROM empty" );
           
           Serial.println("Accepted");        
           digitalWrite(12, HIGH);
           delay(1000);
           digitalWrite(12, LOW);
           delay(10);         
       }
       
       else            // Y Password check
       
       {
          Serial.println("Denied");  
          digitalWrite(12, HIGH);
          delay(100);
          digitalWrite(12, LOW);
          delay(10);
          
          for (int i = 0; i < 512; i++) // Write 0 to all 512 bytes of the EEPROM
          EEPROM.write(i, 0);  
          Serial.println("EEPROM empty" );
       }        
 }