|
Intro to Physical Computing Syllabus code, circuits, & construction
|
Siteplayer and UDP |
|||||||||||||||
| Although the siteplayer is designed primarily as a passive network device (it only responds to HTTP requests, it does not initiate them), it can send limited messages using the universal datagram protocol (UDP). By combining the siteplayer with a microprocessor such as a PIC or BX-24, you can arrange for many siteplayers to exchange messages using UDP. | ||||||||||||||||
| What's UDP?
If you're not familiar with the lower levels of networking protocols, then understanding UDP could take some time, and might bore you to tears if you're not interested in the technical details. It'll suffice to say that UDP is a very simple way to send bytes from one device to another over the internet. There's no need to establish a connection between the devices. The sender just picks an address and starts blasting bytes to the net, not knowing if the sender gets them, and not caring. Whee! There are a few details we need to send a UDP message. We need the IP address of who we're going to send it to. This will be a four-byte number, usually written in decimal notation like this: 128.122.151.62. Every device attached to the internet should have a unique IP address, assigned to it by the router through which it addresses the rest of the internet. We'll also need the Media Access Control address, or MAC address. Sometimes you'll hear this colloquially referred to as the ethernet address or the hardware address, or the physical address. Every device connected to the net via an ethernet network will have a unique MAC address, assigned by the manufacturer. It's a six-byte number, and usually is written in hexadecimal notation, like this: 00-40-0E-37-54-32. Once we have these details, we can send away merrily. |
If you are interested in the technical details, there are some available at this site. | |||||||||||||||
| Siteplayer SendUDP Command
Siteplayer has a number of special function registers in memory into which we put the IP address and MAC address that we want to send a message. We can set these registers initially when we make our .spd file, and we can change the values in them either by filling in the variables from a web page, or by writing to them through the siteplayer's serial port. Once the IP address and MAC address are set, we also have to set how many bytes we're going to send, and what memory address we want to send from. When all these details are covered, we give the siteplayer a sendUDP command, and the message is sent. Following are three examples of setting the UDP registers. The first sets the UDP registers from the .spd file. The second sets them from a web page on the siteplayer. The third sets them from a PIC using the siteplayer's serial port. Here's an example of how we'd set the UDP special function registers in our .spd file: org 0h recVar1 dB 0 ;a byte variable with the initial value 0 recVar2 dB 0 ; another byte ; we're going to send the following seven bytes whenever ; a UDP packet is sent. See how the UDP registers ; are set up below. org 04h numBytes db 01 byteComplement db FEh sendAddr1 db 19h sendAddr2 db FFh dataByte1 db 41h tailByte1 db 00 tailByte2 db 00 ; move to address 02D0h, ; the beginning of the UDP registers: org 02D0h ; set the six bytes of the MAC address ; (using the sample values given above. Make sure to ; use the correct one for the device you want to reach: udpmac1 db 00h udpmac2 db 40h udpmac3 db 0Eh udpmac4 db 37h udpmac5 db 54h udpmac6 db 32h ; set the IP address. Note that we're using decimal ; notation here, because it's convenient (because most ; IP addresses are given in decimal notation): udpip1 db 128 udpip2 db 122 udpip3 db 151 udpip4 db 62 ; set the port that the receiver will listen on ; (note that siteplayers will only listen ; on port 26482) udpport dw 26482 ; set the address in siteplayer memory ; to start sending from (this will start with the ; variable numbytes, above, and send it and ; the six bytes follwing (total seven bytes) udpaddr dw 04h udpcount dw 7 If we want to change the UDP registers in response to web-based input, we could use a form on a page, and have the user fill in the details. Here's how we'd do that: <form method="get" action="counter.spi"> UDP Send<br> MAC Address <input type="text" name="udpmac" size="2" value="^udpmac1">- <input type="text" name="udpmac2" size="2" value="^udpmac2">- <input type="text" name="udpmac3" size="2" value="^udpmac3">- <input type="text" name="udpmac4" size="2" value="^udpmac4">- <input type="text" name="udpmac5" size="2" value="^udpmac5">- <input type="text" name="udpmac6" size="2" value="^udpmac6"> <br> IP Address <input type="text" name="udpip" size="3" value="^udpip1">. <input type="text" name="udpip2" size="3" value="^udpip2">. <input type="text" name="udpip3" size="3" value="^udpip3">. <input type="text" name="udpip4" size="3" value="^udpip4"> : Port <input type="text" name="udpport" size="5" value="^udpport"> <br> Internal Siteplayer Address (decimal) <input type="text" name="udpaddr" size="5" value="^udpaddr"><br> Length <input type="text" name="udpcount" size="4" value="^udpcount"><br> Value to send <input type="text" name="dataByte1" size="4" value="^dataByte1"><br> <input type="hidden" name="udpsend" value="1"> <!-- the hidden field udpsend makes the siteplayer send out out on submit--> <input type="submit" name="Submit" value="Submit"> </form> Alternately, we may want to fill the siteplayer's UDP registers through the serial port. Here's how we could do that using a PIC in PicBasic Pro: addressLow var byte addressHigh var byte udpmac var byte(6) udpip var byte(4) '.... main code goes here, calls setAddress subroutine setAddress: ' set address to write to siteplayer ' at the beginning of the UDP registers (02D0h): addressLow = $D0 addressHigh = $02 ' set the UDP register values (using two byte arrays in the pic): udpmac[0] = $00 udpmac[1] = $03 udpmac[2] = $75 udpmac[3] = $0A udpmac[4] = $44 udpmac[5] = $43 udpip[0] = 128 udpip[1] = 122 udpip[2] = 151 udpip[3] = 62 ' note we are sending 10 bytes, ' so our command is $99 (writeX, 10 bytes) Serout2 PORTC.6, 84, [$99, addressLow, addressHigh,udpmac[0], udpmac[1],udpmac[2],udpmac[3], udpmac[4],udpmac[5],udpip[0], udpip[1],udpip[2],udpip[3]] return If we chose to set the other UDP variables, we would add them on to the serout, and modify the writeX command to include the appropriate number of bytes. |
||||||||||||||||
| So we set the registers, what next?
Once we've set the address of the device we're sending to, we set what information to send. The UDPAddr register tells the siteplayer what memory address to begin sending from, and the UDPcount register tells it how many bytes to send. For example, if we set UDPaddr to 3, and UDPcount to 3, it will send three bytes, from addresses 03, 04, and 05. The .spd file example above makes the siteplayer send the variables numBytes, byteComplement, sendAddr1, sendAddr2, dataByte1, tailByte1, and tailByte2. It starts at address 04h (numBytes) and sends seven bytes from there. From this, you can see that the .spd file is valuable when programming, so you know at what addresses your variables are stored when you want to retrieve or send them. Once the destination is set, and we've told the siteplayer what to send, we tell it to initiate a UDP send. To initiate the send there are two methods. From a web page, we can just set the UDPsend register (address 0FF1Eh) to 1, and the siteplayer will send a message. Or we can send the serial command UDPSend (hex value $50), and the siteplayer will send a message. Here's an HTML command to do it: <a href="myspi.spi?udpsend=1"> Send whatever's in the UDP registers out.</a> and here's a PICBasic Pro command to do it: Serout2 PORTC.6, 84, [$50] Note that the siteplayer may not send a message for every single send command you issue. It takes several milliseconds to send a UDP message. If the siteplayer is already sending a message, or if it's responding to an HTTP request, it will take note of any UDPsend messages, and send one message when it's done with all other requests. So sending several UDPsend commands in the space of a millisecond or two is not recommended. Broadcast vs. Directed Messages In some cases you want to send a UDP message without knowing the receiver. In these cases, the message will reach every device that's listening on the same subnet as your device. In other words, if your siteplayer has the IP address 128.122.151.34, then the subnet is 128.122.151.xx. To broadcast to this subnet, you use the IP address 128.122.151.255, and the MAC address FF-FF-FF-FF-FF-FF. This MAC address tells the router to send this particular message to every device it controls. |
||||||||||||||||
| Receiving UDP messages
In addition to sending UDP messages, the siteplayer can also receive UDP messages and store them in memory. It can also send them directly out the serial port, if instructed by the message to do so. In order to receive UDP packets, the UDPrcvr register must be set to 1. UDP receive is disabled on startup (in the pcadef.inc file), but you can enable it in HTML or via serial as follows: in HTML: <a href="myspi.spi?udprcvr=1">enable UDP</A><br> <a href="myspi.spi?udprcvr=0">disable UDP</A> Serial command (in picBasic Pro): serout2 PORTC.6, 84, [$90, $20, $FF, $01] The siteplayer expects incoming UDP messages to be formatted as follows:
Each UDP packet must end with two bytes of value 00 as wells . So let's say we wanted to tell the siteplayer to send the value 65 (ASCII "A") out the serial port. We know that the COM send object is address 0FF19h, and that we're only sending one byte. So our UDP packet would look like this:
Final packet: 01h FEh 19h FFh 41h 00h 00h |
||||||||||||||||
|
Here's a java example that sends this packet to a siteplayer: import java.net.*;
import java.util.*;
import java.io.*;
import java.text.*;
public class Send_udp {
// set port to send to (Siteplayer only listens on 26482)
static final int PORT = 26482;
DatagramSocket ds = null;
public static void main(String[] args) {
Send_udp mysender = new Send_udp();
mysender.sendstuff();
}
public Send_udp() {
try {
ds = new DatagramSocket(PORT);
} catch (SocketException exp) {}
}
public void sendstuff() {
InetAddress address = null;
try {
// fill in your IP address here
address = InetAddress.getByName("128.122.151.62");
} catch (UnknownHostException uhe) {}
byte[] dataBuffer1 = new byte[7];
DatagramPacket dpsend =
new DatagramPacket(dataBuffer1,
dataBuffer1.length, address, PORT);
// this is where we construct the UDP message byte by byte:
// number of bytes to send:
dataBuffer1[0] = 0x01;
// complement of number of bytes to send:
dataBuffer1[1] = (byte) 0xFE;
// low byte of address of COM:
dataBuffer1[2] = 0x19;
// high byte of address of COM:
dataBuffer1[3] = (byte) 0xFF;
// ASCII "A":
dataBuffer1[4] = 0x41;
// udp must end with two zero bytes:
dataBuffer1[5] = 0x00;
dataBuffer1[6] = 0x00;
try {
ds.send(dpsend);
System.out.println("Sent it\n")
} catch (IOException expe) {}
}
}
|
See Sonny's Java servers for siteplayer, a few useful examples for communicating to a siteplayer from a server. This example is derived from Sonny's example. | |||||||||||||||
| By now, you may have picked up on the fact that the .spd file example above enables a siteplayer send a UDP packet formatted for another siteplayer. It sends ASCII "A". | ||||||||||||||||
| One Final Note:
When your siteplayer is broadcasting or receiving UDP messages, it can't respond to web hits or accept downloads of new .spb files. So make sure when you construct a UDP application that there is time in between its listening and sending activities for these other crucial functions to take place. |