Difference between revisions of "Tutorial: Raspberry Pi communication with Processing"
(Created page with "--~~~~ ---- <bluebox> This recipe simply replaces the client.c program of the client-server example in this series of Raspberr...") |
(→Client code) |
||
Line 146: | Line 146: | ||
==Client code== | ==Client code== | ||
<br /> | <br /> | ||
− | The client code is written in [ | + | The client code is written in [https://processing.org Processing 2] and uses its [http://processing.org/reference/libraries/net/Client.html client] class to create a client that can communicate with our server over a socket. |
<br /> | <br /> | ||
<source lang="java"> | <source lang="java"> |
Revision as of 16:57, 26 July 2013
--D. Thiebaut (talk) 17:26, 26 July 2013 (EDT)
This recipe simply replaces the client.c program of the client-server example in this series of Raspberry Pi tutorials and replaces it by a client written in Processing 2
Hardware Setup
- The setup is that proposed in the excellent blog page at http://pihw.wordpress.com/guides/direct-network-connection/ from which the image above is taken.
- No need to try to copy what they already did very well, so simply follow their recommendations and connect your laptop to the Raspberry Pi using an ethernet cable.
Server/Client setup
- Here we take the server part of the example from User Moorthy at RPI and adapt it slightly for our use.
Server code
/* A simple server in the internet domain using TCP.
myServer.c
D. Thiebaut
Adapted from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
The port number used in 51717.
This code is compiled and run on the Raspberry as follows:
g++ -o myServer myServer.c
./myServer
The server waits for a connection request from a client.
The server assumes the client will send positive integers, which it sends back multiplied by 2.
If the server receives -1 it closes the socket with the client.
If the server receives -2, it exits.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
void error( char *msg ) {
perror( msg );
exit(1);
}
int func( int a ) {
return 2 * a;
}
void sendData( int sockfd, int x ) {
int n;
char buffer[32];
sprintf( buffer, "%d\n", x );
if ( (n = write( sockfd, buffer, strlen(buffer) ) ) < 0 )
error( const_cast<char *>( "ERROR writing to socket") );
buffer[n] = '\0';
}
int getData( int sockfd ) {
char buffer[32];
int n;
if ( (n = read(sockfd,buffer,31) ) < 0 )
error( const_cast<char *>( "ERROR reading from socket") );
buffer[n] = '\0';
return atoi( buffer );
}
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno = 51717, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
int data;
printf( "using port #%d\n", portno );
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error( const_cast<char *>("ERROR opening socket") );
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons( portno );
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error( const_cast<char *>( "ERROR on binding" ) );
listen(sockfd,5);
clilen = sizeof(cli_addr);
//--- infinite wait on a connection ---
while ( 1 ) {
printf( "waiting for new client...\n" );
if ( ( newsockfd = accept( sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen) ) < 0 )
error( const_cast<char *>("ERROR on accept") );
printf( "opened new communication with client\n" );
while ( 1 ) {
//---- wait for a number from client ---
data = getData( newsockfd );
printf( "got %d\n", data );
if ( data < 0 )
break;
data = func( data );
//--- send new data back ---
printf( "sending back %d\n", data );
sendData( newsockfd, data );
}
close( newsockfd );
//--- if -2 sent by client, we can quit ---
if ( data == -2 )
break;
}
return 0;
}
Client code
The client code is written in Processing 2 and uses its client class to create a client that can communicate with our server over a socket.
/*
PiMain.java
D. Thiebaut
Processing class extending Processing's PApplet and creating a socket with our raspberry Pi server
that is running a C/C++ server.
This class is developped and built inside Eclipse. To use the Processing IDE, simply remove the import
statements as well as the enclosing class.
*/
import processing.core.PApplet;
import processing.core.PFont;
import processing.net.*;
public class PiMain extends PApplet {
Client myClient;
String dataIn;
String raspberryPi = "169.254.0.2"; // change to the iP assigned to your Raspberry Pi
int portNo = 51717; // change this to the port used by the server.
int count = 0x2; // some integer sent to the server
boolean firstTime = true; // used to make sure setup initializes the connection only once.
public void setup() {
size(600, 500);
smooth();
if ( firstTime ) {
// setup communication with server
myClient = new Client(this, raspberryPi, portNo );
// send the server an integer
myClient.write( count++ );
firstTime = false;
}
frameRate( 30 ); // 30 frames/sec
}
public void draw() {
// clear background
background( 0 );
// read the string sent by the server every second...
if ( myClient.available() > 0 && frameCount % 30 == 0 ) {
// get string and remove white space chars
dataIn = myClient.readString().trim();
// transform it into an int
int x = Integer.parseInt( dataIn.trim() );
// send back a new value
myClient.write( String.format("%d",++count ) );
}
// display last exchange of data on applet
text( "Received: " + dataIn, 20, 20 );
text( "Sent back: " + count, 20, 40 );
}
}
Typical Output
The console outputs of the Server is shown below:
pi@raspberrypi ~ $ ./myServer4
using port #51717
waiting for new client...
opened new communication with client
got 0
sending back 0
got 4
sending back 8
got 5
sending back 10
got 6
sending back 12
got 7
sending back 14
got 8
sending back 16
got 9
...