diff --git a/.classpath b/.classpath index 7bc01d9..5176974 100644 --- a/.classpath +++ b/.classpath @@ -1,9 +1,9 @@ - - + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0313e2c..223e3ad 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,27 +1,36 @@ + package="com.vanderbie.heart_rate_monitor" + android:versionCode="1" + android:versionName="1.0" > - + - - - - + + - - + + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/Processing/HeartRate_udp/HeartRate_udp.pde b/Processing/HeartRate_udp/HeartRate_udp.pde new file mode 100644 index 0000000..a946dfe --- /dev/null +++ b/Processing/HeartRate_udp/HeartRate_udp.pde @@ -0,0 +1,94 @@ +/** + * (./) udp.pde - how to use UDP library as unicast connection + * (cc) 2006, Cousot stephane for The Atelier Hypermedia + * (->) http://hypermedia.loeil.org/processing/ + http://ubaa.net/shared/processing/udp/ + * + * Extended by Joey van der Bie to display heart rate value send by Android phone + * https://github.com/joeyvanderbie/android-heart-rate-monitor + */ + +// import UDP library +import hypermedia.net.*; + + +UDP udp; // define the UDP object +int listenport = 6000;// this should be the same as the port in the Android app + +int textSize = 180; +/** + * init + */ +void setup() { + size(600,600); + // create a new datagram connection on port 6000 + // and wait for incomming message + udp = new UDP( this, listenport ); + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); + + + //Draw blank text + textSize(textSize); + background(255,0,0); + fill(255); + text("--", (width-textSize)/2, (height+textSize)/2); +} + +//process events +void draw() {; +} + +void displayHeartRate(int heart_rate){ + //display heart rate + background(255,0,0); + fill(255); + text(""+heart_rate, (width-textSize)/2, (height+textSize)/2); +} + +/** + * To perform any action on datagram reception, you need to implement this + * handler in your code. This method will be automatically called by the UDP + * object each time he receive a nonnull message. + * By default, this method have just one argument (the received message as + * byte[] array), but in addition, two arguments (representing in order the + * sender IP address and his port) can be set like below. + */ +// void receive( byte[] data ) { // <-- default handler +void receive( byte[] data, String ip, int port ) { // <-- extended handler + + + // get the "real" message = + // forget the ";\n" at the end <-- !!! only for a communication with Pd !!! + data = subset(data, 0, data.length-2); + String message = new String( data ); + + // print the result + println( "receive: \""+message+"\" from "+ip+" on port "+port ); + + + String heartrate[] = split(message, ","); + displayHeartRate(int(heartrate[0])); + +} + +/** + * on key pressed event: + * send the current key value over the network + */ +void keyPressed() { + + String message = str( key ); // the message to send + String ip = "localhost"; // the remote IP address + int port = 6100; // the destination port + + // formats the message for Pd + message = message+";\n"; + // send the message + udp.send( message, ip, port ); +} + + + + + diff --git a/Processing/HeartRate_udp/udp.pd b/Processing/HeartRate_udp/udp.pd new file mode 100644 index 0000000..43773de --- /dev/null +++ b/Processing/HeartRate_udp/udp.pd @@ -0,0 +1,30 @@ +#N canvas 103 333 764 337 10; +#X obj 36 28 cnv 15 690 190 empty empty empty 20 12 0 12 -237178 -212212 +0; +#X obj 36 221 cnv 15 690 70 empty empty empty 20 12 0 14 -146177 -66577 +0; +#X obj 45 256 print receive; +#X text 177 233 <-- Opens a socket for UDP network reception on port +6100 and prints the received message.; +#X obj 47 116 netsend 1; +#X msg 47 94 disconnect; +#X floatatom 47 164 5 0 0 0 - - -; +#X text 95 164 <-- Reports whether the connection is open or not (0=close +\, nonzero otherwise).; +#X obj 242 70 cnv 15 480 60 empty empty empty 20 12 0 14 -259904 -66577 +0; +#X msg 249 100 send \$1; +#X floatatom 249 82 5 0 0 0 - - -; +#X obj 45 234 netreceive 6100 1; +#X msg 47 72 connect localhost 6000; +#X text 314 81 [2] Send the current number to the remote machine (change +the value by dragging the number box or type directly the new value). +; +#X text 47 40 [1] Connect to 'localhost' on port 6000 for sending UDP +messages.; +#X connect 4 0 6 0; +#X connect 5 0 4 0; +#X connect 9 0 4 0; +#X connect 10 0 9 0; +#X connect 11 0 2 0; +#X connect 12 0 4 0; diff --git a/Processing/udp/examples/udp/udp.pd b/Processing/udp/examples/udp/udp.pd new file mode 100755 index 0000000..43773de --- /dev/null +++ b/Processing/udp/examples/udp/udp.pd @@ -0,0 +1,30 @@ +#N canvas 103 333 764 337 10; +#X obj 36 28 cnv 15 690 190 empty empty empty 20 12 0 12 -237178 -212212 +0; +#X obj 36 221 cnv 15 690 70 empty empty empty 20 12 0 14 -146177 -66577 +0; +#X obj 45 256 print receive; +#X text 177 233 <-- Opens a socket for UDP network reception on port +6100 and prints the received message.; +#X obj 47 116 netsend 1; +#X msg 47 94 disconnect; +#X floatatom 47 164 5 0 0 0 - - -; +#X text 95 164 <-- Reports whether the connection is open or not (0=close +\, nonzero otherwise).; +#X obj 242 70 cnv 15 480 60 empty empty empty 20 12 0 14 -259904 -66577 +0; +#X msg 249 100 send \$1; +#X floatatom 249 82 5 0 0 0 - - -; +#X obj 45 234 netreceive 6100 1; +#X msg 47 72 connect localhost 6000; +#X text 314 81 [2] Send the current number to the remote machine (change +the value by dragging the number box or type directly the new value). +; +#X text 47 40 [1] Connect to 'localhost' on port 6000 for sending UDP +messages.; +#X connect 4 0 6 0; +#X connect 5 0 4 0; +#X connect 9 0 4 0; +#X connect 10 0 9 0; +#X connect 11 0 2 0; +#X connect 12 0 4 0; diff --git a/Processing/udp/examples/udp/udp.pde b/Processing/udp/examples/udp/udp.pde new file mode 100644 index 0000000..c740f52 --- /dev/null +++ b/Processing/udp/examples/udp/udp.pde @@ -0,0 +1,73 @@ +/** + * (./) udp.pde - how to use UDP library as unicast connection + * (cc) 2006, Cousot stephane for The Atelier Hypermedia + * (->) http://hypermedia.loeil.org/processing/ + * + * Create a communication between Processing<->Pure Data @ http://puredata.info/ + * This program also requires to run a small program on Pd to exchange data + * (hum!!! for a complete experimentation), you can find the related Pd patch + * at http://hypermedia.loeil.org/processing/udp.pd + * + * -- note that all Pd input/output messages are completed with the characters + * ";\n". Don't refer to this notation for a normal use. -- + */ + +// import UDP library +import hypermedia.net.*; + + +UDP udp; // define the UDP object +int listenport = 6000;// this should be the same as the port in the Android app +/** + * init + */ +void setup() { + + // create a new datagram connection on port 6000 + // and wait for incomming message + udp = new UDP( this, listenport ); + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); +} + +//process events +void draw() {;} + +/** + * on key pressed event: + * send the current key value over the network + */ +void keyPressed() { + + String message = str( key ); // the message to send + String ip = "localhost"; // the remote IP address + int port = 6100; // the destination port + + // formats the message for Pd + message = message+";\n"; + // send the message + udp.send( message, ip, port ); + +} + +/** + * To perform any action on datagram reception, you need to implement this + * handler in your code. This method will be automatically called by the UDP + * object each time he receive a nonnull message. + * By default, this method have just one argument (the received message as + * byte[] array), but in addition, two arguments (representing in order the + * sender IP address and his port) can be set like below. + */ +// void receive( byte[] data ) { // <-- default handler +void receive( byte[] data, String ip, int port ) { // <-- extended handler + + + // get the "real" message = + // forget the ";\n" at the end <-- !!! only for a communication with Pd !!! + data = subset(data, 0, data.length-2); + String message = new String( data ); + + // print the result + println( "receive: \""+message+"\" from "+ip+" on port "+port ); +} + diff --git a/Processing/udp/examples/udp_multicast/udp_multicast.pde b/Processing/udp/examples/udp_multicast/udp_multicast.pde new file mode 100755 index 0000000..596f237 --- /dev/null +++ b/Processing/udp/examples/udp_multicast/udp_multicast.pde @@ -0,0 +1,100 @@ +/** + * (./) udp_multicast.pde - how to use UDP library as multicast connection + * (cc) 2006, Cousot stephane for The Atelier Hypermedia + * (->) http://hypermedia.loeil.org/processing/ + * + * Pass the mouse coordinates over the network to draw an "multi-user picture". + * + * -- + * + * about multicasting: + * The only difference between unicast/broadcast and multicast address is that + * all interfaces identified by that address receive the same data. Multicasting + * provide additional options in the UDP object (see the documentation for + * more informations), but the usage is commonly the same: simply add the + * multicast group address in his initialization to reflect a multicast + * connection. + * + * (note: currently applets are not allowed to use multicast sockets) + */ + +// import UDP library +import hypermedia.net.*; + + +UDP udp; // the UDP object + + +/** + * init the frame and the UDP object. + */ +void setup() { + + // to simplify the program, we use a byte[] array to pass the previous and + // the current mouse coordinates. The PApplet size must be defined with + // values <=255 + size( 255, 255 ); + background( 0 ); + + // create a multicast connection on port 6000 + // and join the group at the address "224.0.0.1" + udp = new UDP( this, 6000, "224.0.0.1" ); + // wait constantly for incomming data + udp.listen( true ); + // ... well, just verifies if it's really a multicast socket and blablabla + println( "init as multicast socket ... "+udp.isMulticast() ); + println( "joins a multicast group ... "+udp.isJoined() ); + +} + +// process events +void draw() { +} + + +/** + * on mouse move : + * send the mouse positions over the network + */ +void mouseMoved() { + + byte[] data = new byte[4]; // the data to be send + + // add the mouse positions + data[0] = byte(mouseX); + data[1] = byte(mouseY); + data[2] = byte(pmouseX); + data[3] = byte(pmouseY); + + // by default if the ip address and the port number are not specified, UDP + // send the message to the joined group address and the current socket port. + udp.send( data ); // = send( data, group_ip, port ); + + // note: by creating a multicast program, you can also send a message to a + // specific address (i.e. send( "the messsage", "192.168.0.2", 7010 ); ) +} + +/** + * This is the program receive handler. To perform any action on datagram + * reception, you need to implement this method in your code. She will be + * automatically called by the UDP object each time he receive a nonnull + * message. + */ +void receive( byte[] data ) { + + // retrieve the mouse coordonates + int x = int( data[0] ); + int y = int( data[1] ); + int px = int( data[2] ); + int py = int( data[3] ); + + // slowly, clears the previous lines + noStroke(); + fill( 0, 0, 0, 7 ); + rect( 0, 0, width, height); + + // and draw a single line with the given mouse positions + stroke( 255 ); + line( x, y, px, py ); + +} diff --git a/Processing/udp/library.properties b/Processing/udp/library.properties new file mode 100644 index 0000000..002506b --- /dev/null +++ b/Processing/udp/library.properties @@ -0,0 +1,9 @@ + +name = UDP +authorList = [Stephane Cousot](http://ubaa.net/) +url = http://ubaa.net/shared/processing/udp/ +category = Data +sentence = Enables simple UDP communication, as well as multicast support. +paragraph = +version = 1 +prettyVersion = 0.1 diff --git a/Processing/udp/library/udp.jar b/Processing/udp/library/udp.jar new file mode 100644 index 0000000..ef0e284 Binary files /dev/null and b/Processing/udp/library/udp.jar differ diff --git a/Processing/udp/reference/index.htm b/Processing/udp/reference/index.htm new file mode 100755 index 0000000..dc9e142 --- /dev/null +++ b/Processing/udp/reference/index.htm @@ -0,0 +1,23 @@ + + + + + + + + +
+ + + + + + + + + +
hypermedia.net
UDP

UDP
BUFFER_SIZE
address ( )
broadcast ( )
close ( )
dispose ( )
getBuffer ( )
getTimeToLive ( )
isBroadcast ( )
isClosed ( )
isJoined ( )
isListening ( )
isLoopback ( )
isMulticast ( )
listen ( )
log ( )
loopback ( )
port ( )
run ( )
send ( )
setBuffer ( )
setReceiveHandler ( )
setTimeToLive ( )
setTimeoutHandler ( )
+
+ + diff --git a/Processing/udp/reference/stylesheet.css b/Processing/udp/reference/stylesheet.css new file mode 100755 index 0000000..1d677a5 --- /dev/null +++ b/Processing/udp/reference/stylesheet.css @@ -0,0 +1,100 @@ + + + + +body { + margin: 0; + color: black; + background-color: white; + font-family: verdana, arial, sans-serif; + font-size: 10px; +} +pre { + font-family: "Courier New", Courier, mono; + font-size: 11px; + line-height: normal; + color: black; + border: 1px solid silver; + padding: 17px; +} +a +{ + color: red; + text-decoration: none +} + +a:hover +{ + color: fuchsia; + text-decoration: none; +} + + +.mainText { + vertical-align: top; + text-align: right; + padding-right: 20px; +} +.linkList { + vertical-align: top; + font-style: normal; + color: #999999; + padding-left: 5px; +} +.descList { + vertical-align: top; + font-style: normal; + color: #000000; + padding-left: 20px; + padding-bottom: 30px; + width: 200px; +} +.libName { + font-size: 16px; + font-weight: bold; +} +.indexheader, +.header { + font-size: 12px; + color: gray; + text-align: right; + padding: 20px; + width: 126px; + font-weight: normal; +} +.methodName { + font-size: 24px; + vertical-align: top; + font-weight: bold; + color: red; + padding-left: 20px; + padding-bottom: 30px; +} +.mainTextName { + vertical-align: top; + padding-right: 20px; + text-align: right; + padding-top: 5px; +} +.colored { + color: #999999; +} +.indextext { + vertical-align: top; + text-align: left; + padding-right: 20px; + padding-left: 20px; +} +.indexheader { + font-weight: bold; + width: auto; + height: auto; +} +.code_style { + font-size: 8px; +} + +.hide +{ + display: none; +} diff --git a/Processing/udp/reference/udp_class_udp.htm b/Processing/udp/reference/udp_class_udp.htm new file mode 100755 index 0000000..7f4d784 --- /dev/null +++ b/Processing/udp/reference/udp_class_udp.htm @@ -0,0 +1,328 @@ + + + +hypermedia.net : : UDP + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ hypermedia.net + index
NameUDP
Examples
None available
DescriptionCreate and manage unicast, broadcast or multicast socket to send and receive + datagram packets over the network. +

+ The socket type is define at his initialyzation by the passed IP address. + To reach a host (interface) within a network, you need to specified the kind + of address: +

    +
  • An unicast address refer to a unique host within a subnet.
  • +
  • A broadcast address allow you to call every host within a subnet. +
  • +
  • A multicast address allows to call a specific group of hosts within + the subnet. A multicast group is specified by a IP address in the range + 224.0.0.0 (reserved, should not be used) to + 239.255.255.255 inclusive, and by a standard UDP port number. +
    + notes: the complete reference of special multicast addresses should be + found in the latest available version of the "Assigned Numbers RFC" +
  • +
+ A packet sent to a unicast or broadcast address is only delivered to the + host identified by that address. To the contrary, when packet is send to a + multicast address, all interfaces identified by that address receive the data + . +

+ To perform actions on receive and/or timeout events, you must implement + specific method(s) in your code. This method will be automatically called + when the socket receive incoming data or a timeout event. By default, the + "receive handler" is typically receive(byte[] data) but you can + retrieve more informations about the datagram packet, see + {@link UDP#setReceiveHandler(String name)} for more informations. In the same + logic, the default "timeout handler" is explicitly timeout(). +

+ + note: currently applets are not allowed to use multicast sockets +

Constructors
UDP(owner);
+UDP(owner, port);
+UDP(owner, port, ip);
+
Parameters + + + + + + + + + + + + + + + + + + + + +
owner the target object to be call by the receive handler
port local port to bind
ip host address or group address
+
Fields + + + + + + + + +
BUFFER_SIZE The default socket buffer length in bytes.

+
Methods + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
address ( ) Return the actual socket's local address, or null if the + address correspond to any local address.

broadcast ( ) Enables or disables the ability of the current process to send broadcast + messages.

close ( ) Close the actuel datagram socket and all associate resources.

dispose ( ) Close the socket. This method is automatically called by Processing when + the PApplet shuts down.

getBuffer ( ) Return the actual socket buffer length

getTimeToLive ( ) Return the "Time to Live" value or -1 if an error occurred (or if + the current socket is not a multicast socket).

isBroadcast ( ) Returns whether the opened socket send broadcast message socket or not.

isClosed ( ) Returns whether the current socket is closed or not.

isJoined ( ) Returns whether the multicast socket is joined to a group address.

isListening ( ) Returns whether the socket wait for incoming data or not.

isLoopback ( ) Returns whether the multicast socket loopback mode is enable or not.

isMulticast ( ) Returns whether the opened datagram socket is a multicast socket or not.

listen ( ) Wait for incoming data, and call the appropriate handlers each time a + message is received. If the owner's class own the appropriate target + handler, this method send it the receive message as byte[], the sender + IP address and port. +

+ This method force the current Thread to be ceased for a + temporary period. If you prefer listening without blocking the current + thread, use the {@link UDP#listen(int millis)} or + {@link UDP#listen(boolean on)} method instead.

log ( ) Enable or disable output process log.

loopback ( ) Enable or disable the multicast socket loopback mode. By default loopback + is enable. +
+ Setting loopback to false means this multicast socket does not want to + receive the data that it sends to the multicast group.

port ( ) Return the actual socket's local port, or -1 if the socket is closed.

run ( ) Wait for incoming datagram packets. This method is called automaticlly, + you do not need to call it.

send ( ) Send data to the requested IP address and port. +

+ A null IP address will assign the packet address to the + local host. Use this method to send data to another application by + passing null as the destination address.

setBuffer ( ) Set the maximum size of the packet that can be sent or receive on the + current socket. This value must be greater than 0, otherwise the buffer + size is set to the his default value. +

+ return true if the new buffer value have been correctly set, + false otherwise. +

+ note : this method has no effect if the socket is listening. To define + a new buffer size, call this method before implementing a new buffer in + memory. Explicitly before calling a receive methods.

setReceiveHandler ( ) Register the target's receive handler. +

+ By default, this method name is "receive" with one argument + representing the received data as byte[]. For more + flexibility, you can change this method with another useful method by + passing his name. You could get more informations by implementing two + additional arguments, a String representing the sender IP + address and a int representing the sender port : +

+ void myCustomReceiveHandler(byte[] message, String ip, int port) {
+	// do something here...
+ }
+ 


setTimeToLive ( ) Control the life-time of a datagram in the network for multicast packets + in order to indicates the scope of the multicasts (ie how far the packet + will travel). +

+ The TTL value must be in range of 0 to 255 inclusive. The larger the + number, the farther the multicast packets will travel (by convention): +

+ 0	-> restricted to the same host
+ 1	-> restricted to the same subnet (default)
+ <32	-> restricted to the same site
+ <64	-> restricted to the same region
+ <128	-> restricted to the same continent
+ <255	-> no restriction
+ 
+ The default value is 1, meaning that the datagram will not go beyond the + local subnet. +

+ return true if no error occured.

setTimeoutHandler ( ) Register the target's timeout handler. By default, this method name is + "timeout" with no argument.

+
UsageWeb & Application
Related
+
+ + \ No newline at end of file diff --git a/Processing/udp/reference/udp_field_buffer_size.htm b/Processing/udp/reference/udp_field_buffer_size.htm new file mode 100755 index 0000000..0a102aa --- /dev/null +++ b/Processing/udp/reference/udp_field_buffer_size.htm @@ -0,0 +1,51 @@ + + + +hypermedia.net : : UDP : : BUFFER_SIZE ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameBUFFER_SIZE ( )
ExamplesNone available
DescriptionThe default socket buffer length in bytes.
Syntax
BUFFER_SIZE;
+
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_address.htm b/Processing/udp/reference/udp_method_address.htm new file mode 100755 index 0000000..8f35dc4 --- /dev/null +++ b/Processing/udp/reference/udp_method_address.htm @@ -0,0 +1,57 @@ + + + +hypermedia.net : : UDP : : address ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Nameaddress ( )
ExamplesNone available
DescriptionReturn the actual socket's local address, or null if the + address correspond to any local address.
Syntax
address();
+
ReturnsString
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_broadcast.htm b/Processing/udp/reference/udp_method_broadcast.htm new file mode 100755 index 0000000..3f4f788 --- /dev/null +++ b/Processing/udp/reference/udp_method_broadcast.htm @@ -0,0 +1,57 @@ + + + +hypermedia.net : : UDP : : broadcast ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Namebroadcast ( )
ExamplesNone available
DescriptionEnables or disables the ability of the current process to send broadcast + messages.
Syntax
broadcast(on);
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_close.htm b/Processing/udp/reference/udp_method_close.htm new file mode 100755 index 0000000..76a4144 --- /dev/null +++ b/Processing/udp/reference/udp_method_close.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : close ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Nameclose ( )
ExamplesNone available
DescriptionClose the actuel datagram socket and all associate resources.
Syntax
close();
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_dispose.htm b/Processing/udp/reference/udp_method_dispose.htm new file mode 100755 index 0000000..2c09e9b --- /dev/null +++ b/Processing/udp/reference/udp_method_dispose.htm @@ -0,0 +1,57 @@ + + + +hypermedia.net : : UDP : : dispose ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Namedispose ( )
ExamplesNone available
DescriptionClose the socket. This method is automatically called by Processing when + the PApplet shuts down.
Syntax
dispose();
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_getbuffer.htm b/Processing/udp/reference/udp_method_getbuffer.htm new file mode 100755 index 0000000..0ab05d3 --- /dev/null +++ b/Processing/udp/reference/udp_method_getbuffer.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : getBuffer ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamegetBuffer ( )
ExamplesNone available
DescriptionReturn the actual socket buffer length
Syntax
getBuffer();
+
Returnsint
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_gettimetolive.htm b/Processing/udp/reference/udp_method_gettimetolive.htm new file mode 100755 index 0000000..d065e85 --- /dev/null +++ b/Processing/udp/reference/udp_method_gettimetolive.htm @@ -0,0 +1,57 @@ + + + +hypermedia.net : : UDP : : getTimeToLive ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamegetTimeToLive ( )
ExamplesNone available
DescriptionReturn the "Time to Live" value or -1 if an error occurred (or if + the current socket is not a multicast socket).
Syntax
getTimeToLive();
+
Returnsint
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_isbroadcast.htm b/Processing/udp/reference/udp_method_isbroadcast.htm new file mode 100755 index 0000000..519a76b --- /dev/null +++ b/Processing/udp/reference/udp_method_isbroadcast.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isBroadcast ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisBroadcast ( )
ExamplesNone available
DescriptionReturns whether the opened socket send broadcast message socket or not.
Syntax
isBroadcast();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_isclosed.htm b/Processing/udp/reference/udp_method_isclosed.htm new file mode 100755 index 0000000..563cba5 --- /dev/null +++ b/Processing/udp/reference/udp_method_isclosed.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isClosed ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisClosed ( )
ExamplesNone available
DescriptionReturns whether the current socket is closed or not.
Syntax
isClosed();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_isjoined.htm b/Processing/udp/reference/udp_method_isjoined.htm new file mode 100755 index 0000000..ba986e6 --- /dev/null +++ b/Processing/udp/reference/udp_method_isjoined.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isJoined ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisJoined ( )
ExamplesNone available
DescriptionReturns whether the multicast socket is joined to a group address.
Syntax
isJoined();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_islistening.htm b/Processing/udp/reference/udp_method_islistening.htm new file mode 100755 index 0000000..997838f --- /dev/null +++ b/Processing/udp/reference/udp_method_islistening.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isListening ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisListening ( )
ExamplesNone available
DescriptionReturns whether the socket wait for incoming data or not.
Syntax
isListening();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_isloopback.htm b/Processing/udp/reference/udp_method_isloopback.htm new file mode 100755 index 0000000..48fa2f7 --- /dev/null +++ b/Processing/udp/reference/udp_method_isloopback.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isLoopback ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisLoopback ( )
ExamplesNone available
DescriptionReturns whether the multicast socket loopback mode is enable or not.
Syntax
isLoopback();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_ismulticast.htm b/Processing/udp/reference/udp_method_ismulticast.htm new file mode 100755 index 0000000..69eb450 --- /dev/null +++ b/Processing/udp/reference/udp_method_ismulticast.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : isMulticast ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NameisMulticast ( )
ExamplesNone available
DescriptionReturns whether the opened datagram socket is a multicast socket or not.
Syntax
isMulticast();
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_listen.htm b/Processing/udp/reference/udp_method_listen.htm new file mode 100755 index 0000000..db5e752 --- /dev/null +++ b/Processing/udp/reference/udp_method_listen.htm @@ -0,0 +1,79 @@ + + + +hypermedia.net : : UDP : : listen ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Namelisten ( )
ExamplesNone available
DescriptionStart/stop waiting constantly for incoming data.
Syntax
listen(on);
+listen(millis);
+listen();
+
Parameters + + + + + + + + + + + + + + +
on the required listening status.
millis the required timeout value in milliseconds.
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_loopback.htm b/Processing/udp/reference/udp_method_loopback.htm new file mode 100755 index 0000000..024f4db --- /dev/null +++ b/Processing/udp/reference/udp_method_loopback.htm @@ -0,0 +1,75 @@ + + + +hypermedia.net : : UDP : : loopback ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Nameloopback ( )
ExamplesNone available
DescriptionEnable or disable the multicast socket loopback mode. By default loopback + is enable. +
+ Setting loopback to false means this multicast socket does not want to + receive the data that it sends to the multicast group.
Syntax
loopback(on);
+
Parameters + + + + + + + + +
on local loopback of multicast datagrams
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_port.htm b/Processing/udp/reference/udp_method_port.htm new file mode 100755 index 0000000..0f436b5 --- /dev/null +++ b/Processing/udp/reference/udp_method_port.htm @@ -0,0 +1,56 @@ + + + +hypermedia.net : : UDP : : port ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Nameport ( )
ExamplesNone available
DescriptionReturn the actual socket's local port, or -1 if the socket is closed.
Syntax
port();
+
Returnsint
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_run.htm b/Processing/udp/reference/udp_method_run.htm new file mode 100755 index 0000000..6352ffa --- /dev/null +++ b/Processing/udp/reference/udp_method_run.htm @@ -0,0 +1,57 @@ + + + +hypermedia.net : : UDP : : run ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Namerun ( )
ExamplesNone available
DescriptionWait for incoming datagram packets. This method is called automaticlly, + you do not need to call it.
Syntax
run();
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_send.htm b/Processing/udp/reference/udp_method_send.htm new file mode 100755 index 0000000..6314e65 --- /dev/null +++ b/Processing/udp/reference/udp_method_send.htm @@ -0,0 +1,95 @@ + + + +hypermedia.net : : UDP : : send ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
Namesend ( )
ExamplesNone available
DescriptionSend message to the current socket. Explicitly, send message to the + multicast group/port or to itself.
Syntax
send(message);
+send(buffer);
+send(message, ip);
+send(buffer, ip);
+send(message, ip, port);
+send(buffer, ip, port);
+
Parameters + + + + + + + + + + + + + + + + + + + + + + + + + + +
message the message to be send
buffer data to be send
ip the destination host's IP address
port the destination host's port
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_setbuffer.htm b/Processing/udp/reference/udp_method_setbuffer.htm new file mode 100755 index 0000000..c2c07c0 --- /dev/null +++ b/Processing/udp/reference/udp_method_setbuffer.htm @@ -0,0 +1,80 @@ + + + +hypermedia.net : : UDP : : setBuffer ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamesetBuffer ( )
ExamplesNone available
DescriptionSet the maximum size of the packet that can be sent or receive on the + current socket. This value must be greater than 0, otherwise the buffer + size is set to the his default value. +

+ return true if the new buffer value have been correctly set, + false otherwise. +

+ note : this method has no effect if the socket is listening. To define + a new buffer size, call this method before implementing a new buffer in + memory. Explicitly before calling a receive methods.

Syntax
setBuffer(size);
+
Parameters + + + + + + + + +
size the buffer size value in bytes or n<=0
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_setreceivehandler.htm b/Processing/udp/reference/udp_method_setreceivehandler.htm new file mode 100755 index 0000000..6e5dde7 --- /dev/null +++ b/Processing/udp/reference/udp_method_setreceivehandler.htm @@ -0,0 +1,83 @@ + + + +hypermedia.net : : UDP : : setReceiveHandler ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamesetReceiveHandler ( )
ExamplesNone available
DescriptionRegister the target's receive handler. +

+ By default, this method name is "receive" with one argument + representing the received data as byte[]. For more + flexibility, you can change this method with another useful method by + passing his name. You could get more informations by implementing two + additional arguments, a String representing the sender IP + address and a int representing the sender port : +

+ void myCustomReceiveHandler(byte[] message, String ip, int port) {
+	// do something here...
+ }
+ 
Syntax
setReceiveHandler(name);
+
Parameters + + + + + + + + +
name the receive handler name
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_settimeouthandler.htm b/Processing/udp/reference/udp_method_settimeouthandler.htm new file mode 100755 index 0000000..8d0228c --- /dev/null +++ b/Processing/udp/reference/udp_method_settimeouthandler.htm @@ -0,0 +1,72 @@ + + + +hypermedia.net : : UDP : : setTimeoutHandler ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamesetTimeoutHandler ( )
ExamplesNone available
DescriptionRegister the target's timeout handler. By default, this method name is + "timeout" with no argument.
Syntax
setTimeoutHandler(name);
+
Parameters + + + + + + + + +
name the timeout handler name
+
ReturnsNone
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/reference/udp_method_settimetolive.htm b/Processing/udp/reference/udp_method_settimetolive.htm new file mode 100755 index 0000000..e3b3fde --- /dev/null +++ b/Processing/udp/reference/udp_method_settimetolive.htm @@ -0,0 +1,88 @@ + + + +hypermedia.net : : UDP : : setTimeToLive ( ) + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
hypermedia.net
+ index
 
NamesetTimeToLive ( )
ExamplesNone available
DescriptionControl the life-time of a datagram in the network for multicast packets + in order to indicates the scope of the multicasts (ie how far the packet + will travel). +

+ The TTL value must be in range of 0 to 255 inclusive. The larger the + number, the farther the multicast packets will travel (by convention): +

+ 0	-> restricted to the same host
+ 1	-> restricted to the same subnet (default)
+ <32	-> restricted to the same site
+ <64	-> restricted to the same region
+ <128	-> restricted to the same continent
+ <255	-> no restriction
+ 
+ The default value is 1, meaning that the datagram will not go beyond the + local subnet. +

+ return true if no error occured.

Syntax
setTimeToLive(ttl);
+
Parameters + + + + + + + + +
ttl the "Time to Live" value
+
Returnsboolean
UsageWeb & Application
Related
 
+
+ + diff --git a/Processing/udp/src/UDP.java b/Processing/udp/src/UDP.java new file mode 100644 index 0000000..bc1337a --- /dev/null +++ b/Processing/udp/src/UDP.java @@ -0,0 +1,882 @@ +/** + * (./) UDP.java v0.2 06/01/26 + * (by) Douglas Edric Stanley & Cousot Stéphane + * (cc) some right reserved + * + * Part of the Processing Libraries project, for the Atelier Hypermedia, art + * school of Aix-en-Provence, and for the Processing community of course. + * - require Java version 1.4 or later - + * -> http://hypermedia.loeil.org/processing/ + * -> http://www.processing.org/ + * + * THIS LIBRARY IS RELEASED UNDER A CREATIVE COMMONS LICENSE BY. + * -> http://creativecommons.org/licenses/by/2.5/ + */ + + +package hypermedia.net; + +import java.net.*; +import java.io.*; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.Date; +import java.text.SimpleDateFormat; + +import processing.core.*; + +/** + * Create and manage unicast, broadcast or multicast socket to send and receive + * datagram packets over the network. + *

+ * The socket type is define at his initialyzation by the passed IP address. + * To reach a host (interface) within a network, you need to specified the kind + * of address: + *

+ * A packet sent to a unicast or broadcast address is only delivered to the + * host identified by that address. To the contrary, when packet is send to a + * multicast address, all interfaces identified by that address receive the data + * . + *

+ * To perform actions on receive and/or timeout events, you must implement + * specific method(s) in your code. This method will be automatically called + * when the socket receive incoming data or a timeout event. By default, the + * "receive handler" is typically receive(byte[] data) but you can + * retrieve more informations about the datagram packet, see + * {@link UDP#setReceiveHandler(String name)} for more informations. In the same + * logic, the default "timeout handler" is explicitly timeout(). + *

+ * + * note: currently applets are not allowed to use multicast sockets + * + * + * @version 0.1 + * @author Cousot Stéphane - stef@ubaa.net + * @author Douglas Edric Stanley - http://www.abstractmachine.net/ + */ +public class UDP implements Runnable { + + + // the current unicast/multicast datagram socket + DatagramSocket ucSocket = null; + MulticastSocket mcSocket = null; + + boolean log = false; // enable/disable output log + boolean listen = false; // true, if the socket waits for packets + int timeout = 0; // reception timeout > 0=infinite timeout + int size = 65507; // the socket buffer size in bytes + InetAddress group = null; // the multicast's group address to join + + // the reception Thread > wait automatically for incoming datagram packets + // without blocking the current Thread. + Thread thread = null; + + // the parent object (could be an application, a componant, etc...) + Object owner = null; + + // the default "receive handler" and "timeout handler" methods name. + // these methods must be implemented (by the owner) to be called + // automatically when the socket receive incoming datas or a timeout event + String receiveHandler = "receive"; + String timeoutHandler = "timeout"; + + // the log "header" to be set for debugging. Because log is disable by + // default, this value is automatically replaced by the principal socket + // settings when a new instance of UDP is created. + String header = ""; + + ///////////////////////////////// fields /////////////////////////////// + + /** + * The default socket buffer length in bytes. + */ + public static final int BUFFER_SIZE = 65507; + + + ///////////////////////////// constructors //////////////////////////// + + /** + * Create a new datagram socket and binds it to an available port and every + * address on the local host machine. + * + * @param owner the target object to be call by the receive handler + */ + public UDP( Object owner ) { + this( owner, 0 ); + } + + /** + * Create a new datagram socket and binds it to the specified port on the + * local host machine. + *

+ * Pass zero as port number, will let the system choose an + * available port. + * + * @param owner the target object to be call by the receive handler + * @param port local port to bind + */ + public UDP( Object owner, int port ) { + this( owner, port, null ); + } + + /** + * Create a new datagram socket and binds it to the specified port on the + * specified local address or multicast group address. + *

+ * Pass zero as port number, will let the system choose an + * available port. The absence of an address, explicitly null + * as IP address will assign the socket to the Unspecified Address (Also + * called anylocal or wildcard address). To set up the socket as multicast + * socket, pass the group address to be joined. If this address is not a + * valid multicast address, a broadcast socket will be created by default. + * + * @param owner the target object to be call by the receive handler + * @param port local port to bind + * @param ip host address or group address + */ + public UDP( Object owner, int port, String ip ) { + + this.owner = owner; + + // register this object to the PApplet, + // if it's used with Processing + try { + if ( owner instanceof PApplet ) ((PApplet)owner).registerMethod("dispose", this); + } + catch( NoClassDefFoundError e ) {;} + + // open a new socket to the specified port/address + // and join the group if the multicast socket is required + try { + + InetAddress addr = InetAddress.getByName(ip); + InetAddress host = (ip==null) ? (InetAddress)null: addr; + + if ( !addr.isMulticastAddress() ) { + ucSocket = new DatagramSocket( port, host ); // as broadcast + log( "bound socket to host:"+address()+", port: "+port() ); + } + else { + mcSocket = new MulticastSocket( port ); // as multicast + mcSocket.joinGroup( addr ); + this.group = addr; + log( "bound multicast socket to host:"+address()+ + ", port: "+port()+", group:"+group ); + } + } + catch( IOException e ) { + // caught SocketException & UnknownHostException + error( "opening socket failed!"+ + "\n\t> address:"+ip+", port:"+port+" [group:"+group+"]"+ + "\n\t> "+e.getMessage() + ); + } + catch( IllegalArgumentException e ) { + error( "opening socket failed!"+ + "\n\t> bad arguments: "+e.getMessage() + ); + } + catch( SecurityException e ) { + error( (isMulticast()?"could not joined the group":"warning")+ + "\n\t> "+e.getMessage() ); + } + + } + + /////////////////////////////// methods /////////////////////////////// + + /** + * Close the socket. This method is automatically called by Processing when + * the PApplet shuts down. + * + * @see UDP#close() + */ + public void dispose() { + close(); + } + + /** + * Close the actuel datagram socket and all associate resources. + */ + public void close() { + if ( isClosed() ) return; + + int port = port(); + String ip = address(); + + // stop listening if needed + //listen( false ); + + // close the socket + try { + if ( isMulticast() ) { + if ( group!=null ) { + mcSocket.leaveGroup( group ); + log( "leave group < address:"+group+" >" ); + } + mcSocket.close(); + mcSocket = null; + } + else { + ucSocket.close(); + ucSocket = null; + } + } + catch( IOException e ) { + error( "Error while closing the socket!\n\t> " + e.getMessage() ); + } + catch( SecurityException e ) {;} + finally { + log( "close socket < port:"+port+", address:"+ip+" >\n" ); + } + } + + /** + * Returns whether the current socket is closed or not. + * @return boolean + **/ + public boolean isClosed() { + if ( isMulticast() ) return mcSocket==null ? true : mcSocket.isClosed(); + return ucSocket==null ? true : ucSocket.isClosed(); + } + + /** + * Return the actual socket's local port, or -1 if the socket is closed. + * @return int + */ + public int port() { + if ( isClosed() ) return -1; + return isMulticast()? mcSocket.getLocalPort() : ucSocket.getLocalPort(); + } + + /** + * Return the actual socket's local address, or null if the + * address correspond to any local address. + * + * @return String + */ + public String address() { + if ( isClosed() ) return null; + + InetAddress laddr = isMulticast() ? mcSocket.getLocalAddress(): + ucSocket.getLocalAddress(); + return laddr.isAnyLocalAddress() ? null : laddr.getHostAddress(); + } + + /** + * Send message to the current socket. Explicitly, send message to the + * multicast group/port or to itself. + * + * @param message the message to be send + * + * @see UDP#send(String message, String ip) + * @see UDP#send(String message, String ip, int port) + * + * @return boolean + */ + public boolean send( String message ) { + return send( message.getBytes() ); + } + + /** + * Send data to the current socket. Explicitly, send data to the multicast + * group/port or to itself. + * + * @param buffer data to be send + * + * @see UDP#send(byte[] data, String ip) + * @see UDP#send(byte[] data, String ip, int port) + * + * @return boolean + */ + public boolean send( byte[] buffer ) { + // probably if the group could not be joined for a security reason + if ( isMulticast() && group==null ) return false; + + String ip = isMulticast() ? group.getHostAddress() : address(); + return send( buffer, ip, port() ); + } + + /** + * Send message to the requested IP address, to the current socket port. + * + * @param message the message to be send + * @param ip the destination host's IP address + * + * @see UDP#send(String message) + * @see UDP#send(String message, String ip, int port) + * + * @return boolean + */ + public boolean send( String message, String ip ) { + return send( message.getBytes(), ip ); + } + + /** + * Send data to the requested IP address, to the current socket port. + * + * @param buffer data to be send + * @param ip the destination host's IP address + * + * @see UDP#send(byte[] buffer) + * @see UDP#send(byte[] buffer, String ip, int port) + * + * @return boolean + */ + public boolean send( byte[] buffer, String ip ) { + return send( buffer, ip, port() ); + } + + /** + * Send message to the requested IP address and port. + *

+ * A null IP address will assign the packet address to the + * local host. Use this method to send message to another application by + * passing null as the destination address. + * + * @param message the message to be send + * @param ip the destination host's IP address + * @param port the destination host's port + * + * @see UDP#send(String message) + * @see UDP#send(String message, String ip) + * + * @return boolean + */ + public boolean send( String message, String ip, int port ) { + return send( message.getBytes(), ip, port ); + } + + /** + * Send data to the requested IP address and port. + *

+ * A null IP address will assign the packet address to the + * local host. Use this method to send data to another application by + * passing null as the destination address. + * + * @param buffer data to be send + * @param ip the destination host's IP address + * @param port the destination host's port + * + * @see UDP#send(byte[] buffer, String ip) + * @see UDP#send(byte[] buffer, String ip, int port) + * + * @return boolean + */ + public boolean send( byte[] buffer, String ip, int port ) { + + boolean success = false; + DatagramPacket pa = null; + + try { + + pa = new DatagramPacket( buffer, buffer.length, InetAddress.getByName(ip), port ); + + // send + if ( isMulticast() ) mcSocket.send( pa ); + else ucSocket.send( pa ); + + success = true; + log( "send packet -> address:"+pa.getAddress()+ + ", port:"+ pa.getPort() + + ", length: "+ pa.getLength() + ); + } + catch( IOException e ) { + error( "could not send message!"+ + "\t\n> port:"+port+ + ", ip:"+ip+ + ", buffer size: "+size+ + ", packet length: "+pa.getLength()+ + "\t\n> "+e.getMessage() + ); + } + finally{ return success; } + } + + /** + * Set the maximum size of the packet that can be sent or receive on the + * current socket. This value must be greater than 0, otherwise the buffer + * size is set to the his default value. + *

+ * return true if the new buffer value have been correctly set, + * false otherwise. + *

+ * note : this method has no effect if the socket is listening. To define + * a new buffer size, call this method before implementing a new buffer in + * memory. Explicitly before calling a receive methods. + * + * @param size the buffer size value in bytes or n<=0 + * @return boolean + * @see UDP#getBuffer() + */ + public boolean setBuffer( int size ) { + boolean done = false; + + // do nothing if listening (block the thread otherwise) + if ( isListening() ) return done; + + try { + // set the SO_SNDBUF and SO_RCVBUF value + if ( isMulticast() ) { + mcSocket.setSendBufferSize( size>0 ? size : BUFFER_SIZE ); + mcSocket.setReceiveBufferSize( size>0 ? size : BUFFER_SIZE ); + } + else { + ucSocket.setSendBufferSize( size>0 ? size : BUFFER_SIZE ); + ucSocket.setReceiveBufferSize( size>0 ? size : BUFFER_SIZE ); + } + // set the current buffer size + this.size = size>0 ? size : BUFFER_SIZE; + done = true; + } + catch( SocketException e ) { + error( "could not set the buffer!"+ + "\n> "+e.getMessage() + ); + } + finally{ return done; } + } + + /** + * Return the actual socket buffer length + * @return int + * @see UDP#setBuffer(int size) + */ + public int getBuffer() { + return size; + } + + /** + * Returns whether the socket wait for incoming data or not. + * @return boolean + */ + public boolean isListening() { + return listen; + } + + + /** + * Start/stop waiting constantly for incoming data. + * + * @param on the required listening status. + * + * @see UDP#listen() + * @see UDP#listen(int millis) + * @see UDP#setReceiveHandler(String name) + */ + public void listen( boolean on ) { + + listen = on; + timeout = 0; + + // start + if ( on && thread==null && !isClosed() ) { + thread = new Thread( this ); + thread.start(); + } + // stop + if ( !on && thread!=null ) { + send( new byte[0] ); // unblock the thread with a dummy message + thread.interrupt(); + thread = null; + } + } + + /** + * Set the socket reception timeout and wait one time for incoming data. + * If the timeout period occured, the owner timeout() method is + * automatically called. + * + * @param millis the required timeout value in milliseconds. + * + * @see UDP#listen() + * @see UDP#listen(boolean on) + */ + public void listen( int millis ) { + if ( isClosed() ) return; + + listen = true; + timeout = millis; + + // unblock the thread with a dummy message, if already listening + if ( thread!=null ) send( new byte[0] ); + if ( thread==null ) { + thread = new Thread( this ); + thread.start(); + } + } + + /** + * Wait for incoming data, and call the appropriate handlers each time a + * message is received. If the owner's class own the appropriate target + * handler, this method send it the receive message as byte[], the sender + * IP address and port. + *

+ * This method force the current Thread to be ceased for a + * temporary period. If you prefer listening without blocking the current + * thread, use the {@link UDP#listen(int millis)} or + * {@link UDP#listen(boolean on)} method instead. + * + * @see UDP#listen() + * @see UDP#listen(boolean on) + * @see UDP#setReceiveHandler(String name) + */ + public void listen() { + try { + + byte[] buffer = new byte[ size ]; + DatagramPacket pa = new DatagramPacket(buffer,buffer.length); + + // wait + if ( isMulticast() ) { + mcSocket.setSoTimeout( timeout ); + mcSocket.receive( pa ); // <-- block the Thread + } + else { + ucSocket.setSoTimeout( timeout ); + ucSocket.receive( pa ); // <-- block + } + + + log( "receive packet <- from "+pa.getAddress()+ + ", port:"+ pa.getPort() + + ", length: "+ pa.getLength() + ); + + + // get the required data only (not all the buffer) + // and send it to the appropriate target handler, if needed + if ( pa.getLength()!=0 ) { + + byte[] data = new byte[ pa.getLength() ]; + System.arraycopy( pa.getData(), 0, data, 0, data.length ); + + try { + // try with one argument first > byte[] + callReceiveHandler( data ); + } + catch( NoSuchMethodException e ) { + // try with many argument > byte[], String, int + callReceiveHandler( data, + pa.getAddress().getHostAddress(), + pa.getPort() + ); + } + } + } + catch( NullPointerException e ) { + // *socket=null from the close() method; + listen = false; + thread = null; + } + catch( IOException e ) { + + listen = false; + thread = null; + + if ( e instanceof SocketTimeoutException ) callTimeoutHandler(); + else { + // do not print "Socket closed" error + // if the method close() has been called + if ( ucSocket!=null && mcSocket!=null ) + error( "listen failed!\n\t> "+e.getMessage() ); + } + } + } + + /** + * Wait for incoming datagram packets. This method is called automaticlly, + * you do not need to call it. + */ + public void run() { + while ( listen ) listen(); + } + + /** + * Register the target's receive handler. + *

+ * By default, this method name is "receive" with one argument + * representing the received data as byte[]. For more + * flexibility, you can change this method with another useful method by + * passing his name. You could get more informations by implementing two + * additional arguments, a String representing the sender IP + * address and a int representing the sender port : + *

+	 * void myCustomReceiveHandler(byte[] message, String ip, int port) {
+	 *	// do something here...
+	 * }
+	 * 
+ * + * @param name the receive handler name + * @see UDP#setTimeoutHandler(String name) + */ + public void setReceiveHandler( String name ) { + this.receiveHandler = name; + } + + /** + * Call the default receive target handler method. + * + * @param data the data to be passed + * @throws NoSuchMethodException + */ + private void callReceiveHandler( byte[] data ) + throws NoSuchMethodException { + + Class[] types; // arguments class types + Object[] values; // arguments values + Method method; + + try { + types = new Class[]{ data.getClass() }; + values = new Object[]{ data }; + method = owner.getClass().getMethod(receiveHandler, types); + method.invoke( owner, values ); + } + catch( IllegalAccessException e ) { error(e.getMessage()); } + catch( InvocationTargetException e ) { e.printStackTrace(); } + } + + /** + * Call the receive target handler implemented with the optional arguments. + * + * @param data the data to be passed + * @param ip the IP adress to be passed + * @param port the port number to be passed + */ + private void callReceiveHandler( byte[] data, String ip, int port ) { + + Class[] types; // arguments class types + Object[] values; // arguments values + Method method; + + try { + types = new Class[]{ data.getClass(), + ip.getClass(), + Integer.TYPE + }; + values = new Object[]{ data, + ip, + new Integer(port) + }; + method = owner.getClass().getMethod(receiveHandler, types); + method.invoke( owner, values ); + } + catch( NoSuchMethodException e ) {;} + catch( IllegalAccessException e ) { error(e.getMessage()); } + catch( InvocationTargetException e ) { e.printStackTrace(); } + } + + /** + * Register the target's timeout handler. By default, this method name is + * "timeout" with no argument. + * + * @param name the timeout handler name + * @see UDP#setReceiveHandler(String name) + */ + public void setTimeoutHandler( String name ) { + this.timeoutHandler = name; + } + + /** + * Call the timeout target method when the socket received a timeout event. + * The method name to be implemented in your code is timeout(). + */ + private void callTimeoutHandler() { + try { + Method m = owner.getClass().getDeclaredMethod(timeoutHandler, null); + m.invoke( owner, null ); + } + catch( NoSuchMethodException e ) {;} + catch( IllegalAccessException e ) { error(e.getMessage()); } + catch( InvocationTargetException e ) { e.printStackTrace(); } + } + + /** + * Returns whether the opened datagram socket is a multicast socket or not. + * @return boolean + */ + public boolean isMulticast() { + return ( mcSocket!=null ); + } + + /** + * Returns whether the multicast socket is joined to a group address. + * @return boolean + */ + public boolean isJoined() { + return ( group!=null ); + } + + /** + * Returns whether the opened socket send broadcast message socket or not. + * @return boolean + */ + public boolean isBroadcast() { + boolean result = false; + try { + result = (ucSocket==null) ? false : ucSocket.getBroadcast(); + } + catch( SocketException e ) { error( e.getMessage() ); } + finally { return result; } + } + + /** + * Enables or disables the ability of the current process to send broadcast + * messages. + * @return boolean + */ + public boolean broadcast( boolean on ) { + boolean done = false; + try { + if ( ucSocket!=null ) { + ucSocket.setBroadcast( on ); + done = isBroadcast(); + } + } + catch( SocketException e ) { error( e.getMessage() ); } + finally { return done; } + } + + /** + * Enable or disable the multicast socket loopback mode. By default loopback + * is enable. + *
+ * Setting loopback to false means this multicast socket does not want to + * receive the data that it sends to the multicast group. + * + * @param on local loopback of multicast datagrams + */ + public void loopback( boolean on ) { + try { + if ( isMulticast() ) mcSocket.setLoopbackMode( !on ); + } + catch( SocketException e ) { + error( "could not set the loopback mode!\n\t>"+e.getMessage() ); + } + } + + /** + * Returns whether the multicast socket loopback mode is enable or not. + * @return boolean + */ + public boolean isLoopback() { + try { + if ( isMulticast() && !isClosed() ) + return !mcSocket.getLoopbackMode(); + } + catch( SocketException e ) { + error( "could not get the loopback mode!\n\t> "+e.getMessage() ); + } + return false; + } + + /** + * Control the life-time of a datagram in the network for multicast packets + * in order to indicates the scope of the multicasts (ie how far the packet + * will travel). + *

+ * The TTL value must be in range of 0 to 255 inclusive. The larger the + * number, the farther the multicast packets will travel (by convention): + *

+	 * 0	-> restricted to the same host
+	 * 1	-> restricted to the same subnet (default)
+	 * <32	-> restricted to the same site
+	 * <64	-> restricted to the same region
+	 * <128	-> restricted to the same continent
+	 * <255	-> no restriction
+	 * 
+ * The default value is 1, meaning that the datagram will not go beyond the + * local subnet. + *

+ * return true if no error occured. + * + * @param ttl the "Time to Live" value + * @return boolean + * @see UDP#getTimeToLive() + */ + public boolean setTimeToLive( int ttl ) { + try { + if ( isMulticast() && !isClosed() ) mcSocket.setTimeToLive( ttl ); + return true; + } + catch( IOException e ) { + error( "setting the default \"Time to Live\" value failed!"+ + "\n\t> "+e.getMessage() ); + } + catch( IllegalArgumentException e ) { + error( "\"Time to Live\" value must be in the range of 0-255" ); + } + return false; + } + + /** + * Return the "Time to Live" value or -1 if an error occurred (or if + * the current socket is not a multicast socket). + * + * @return int + * @see UDP#setTimeToLive(int ttl) + */ + public int getTimeToLive() { + try { + if ( isMulticast() && !isClosed() ) + return mcSocket.getTimeToLive(); + } + catch( IOException e ) { + error( "could not retrieve the current time-to-live value!"+ + "\n\t> "+ e.getMessage() ); + } + return -1; + } + + /** + * Enable or disable output process log. + */ + public void log( boolean on ) { + log = on; + } + + /** + * Output message to the standard output stream. + * @param out the output message + */ + private void log( String out ) { + + Date date = new Date(); + + // define the "header" to retrieve at least the principal socket + // informations : the host/port where the socket is bound. + if ( !log && header.equals("") ) + header = "-- UDP session started at "+date+" --\n-- "+out+" --\n"; + + // print out + if ( log ) { + + String pattern = "yy-MM-dd HH:mm:ss.S Z"; + String sdf = new SimpleDateFormat(pattern).format( date ); + System.out.println( header+"["+sdf+"] "+out ); + header = ""; // forget header + } + } + + /** + * Output error messages to the standard error stream. + * @param err the error string + */ + private void error( String err ) { + System.err.println( err ); + } +} diff --git a/README.md b/README.md index 311afeb..87fb7e1 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ android-heart-rate-monitor ========================== +![heart rate](https://raw.githubusercontent.com/joeyvanderbie/android-heart-rate-monitor/master/screenshots/heartrate_small.png "Heart rate") -Android heart rate monitor +Android heart rate monitor and Processing heart rate receiver ## Introduction -Android based heart rate monitor which uses the camera and its flash to determine the users heart rate in beats per minute. +Android based heart rate monitor which uses the camera and its flash to determine the users heart rate in beats per minute and send via UDP. +A Processing patch is provided to receive the data send. +* Created by Joey van der Bie +* Github: http://github.com/joeyvanderbie/android-heart-rate-monitor + +The original android-heart-rate-monitor info: * Created by Justin Wetherell -* Google: http://code.google.com/p/android-heart-rate-monitor * Github: http://github.com/phishman3579/android-heart-rate-monitor -* LinkedIn: http://www.linkedin.com/in/phishman3579 -* E-mail: phishman3579@gmail.com -* Twitter: http://twitter.com/phishman3579 ## Details The App uses the PreviewCallback mechanism to grab the latest image from the preview frame. It then processes the YUV420SP data and pulls out all the red pixel values. @@ -21,9 +23,23 @@ It uses data smoothing in a Integer array to figure out the average red pixel va The App will collect data in ten second chunks and add the beets per minute to another Integer array which is used to smooth the beats per minute data. +If you provide an ip adres and port the app will send your heart beat to the provided Processing patch. + ## How To -All you have to do is open the HeartRateMonitor App and then hold the tip of your index finger over the camera lens of your phone. The entire camera preview image should be red with a lighter area where the tip of your finger is touching. Do not press too hard or you will cut off circulation which will result in an inaccurate reading. +Open the HeartRateMonitor App and hold the tip of your index finger over the camera lens of your phone. The entire camera preview image should be red with a lighter area where the tip of your finger is touching. Do not press too hard or you will cut off circulation which will result in an inaccurate reading. + +After ten seconds it will compute your heart rate. It'll take between ten and thirty seconds to get an accurate heart rate. + +If you provide an IP adres and port the app will send your heart beat to the provided Processing patch (default port is 6000) -After a second or two, you should see the Android icon on the top of the screen start to flash red when it senses a heart beat. After ten seconds it will compute your heart rate and update the number next to the Android icon. It'll take between ten and thirty seconds to get an accurate heart rate. +To use the Processing patch: +- download Processing 2.0 from processing.org +- copy the udp folder to the library folder of Processing +- open de HeartRate_udp.pd patch in Processing +Screenshots +----------------------------------------- +![start](https://raw.githubusercontent.com/joeyvanderbie/android-heart-rate-monitor/master/screenshots/blank_small.png "Start") +![heart rate](https://raw.githubusercontent.com/joeyvanderbie/android-heart-rate-monitor/master/screenshots/heartrate_small.png "Heart rate") +![udp](https://raw.githubusercontent.com/joeyvanderbie/android-heart-rate-monitor/master/screenshots/udp_small.png "UDP") diff --git a/ic_launcher-web.png b/ic_launcher-web.png new file mode 100644 index 0000000..0f58431 Binary files /dev/null and b/ic_launcher-web.png differ diff --git a/libs/GraphView-3.1.1.jar b/libs/GraphView-3.1.1.jar deleted file mode 100644 index 94333ec..0000000 Binary files a/libs/GraphView-3.1.1.jar and /dev/null differ diff --git a/libs/graphview-3.1.jar b/libs/graphview-3.1.jar new file mode 100644 index 0000000..d03f1de Binary files /dev/null and b/libs/graphview-3.1.jar differ diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..9870684 Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..642184f Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..f3d8f71 Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/drawable-xxhdpi/ic_launcher.png b/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..df1ee33 Binary files /dev/null and b/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/res/layout/main.xml b/res/layout/main.xml index 985fc99..627519e 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -1,46 +1,98 @@ - + +