While I was serving as a lab assistant in advanced programming techniques course’s lab, the professor wanted to introduce an exercise where each student would get a Raspberry Pi (RPi) device in which he would develop a program and execute it.
But a non-trivial problem emerged while figuring out the exercise’s details. The lab is equipped with VGA monitors and PS/2 keyboards and mouses, hence connection of the essential peripherals to the RPi boards, in order to interact with them, was not straightforward (RPi’s only support HDMI and USB).
One possible solution to the problem was to operate the RPis headless (without dedicated monitor and input devices) but connected to university’s LAN and control them via RDP, VNC or even an SSH connection from a nearby PC. But in order to do that, each student must somehow acquire the IP address of his own RPi so he can connect to it. The university network’s administrator didn’t allow giving static IPs to our devices so I had to come up with an alternative solution:
RPi Identification System
The idea I came up with is this: each RPi, after booting and connecting to the local network (via Ethernet) would report its IP along with a unique ID to a dedicated server. The server would serve a web page in which every reported ID - IP pair would be listed. Each student, after connecting his RPi to Ethernet port and power, would wait a little and load this web page on a web browser to get the IP of his RPi. Problem solved!
Implementation
IP Reporter
Starting with the client part, which will run on every RPi, it was developed as a Java application. As each RPi has a unique id, the application makes use of a properties file for increased flexibility and easier deployment. During development of the application, it was noticed that usually, a host has lots of network interfaces and each interface may be bound to more than one IP address. As all the university’s network IPs are taken from the 150.140.xxx.xxx
address pool, a workaround was to accept only the reported IP that starts with the 150.140.
octets. This ip-starts-with string was implemented as another entry in the properties file so that the program can be used in other networks. Let’s have a look at the main method of the application:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) {
//get parameters from properties file
PropertiesHandler propertiesHandler = new PropertiesHandler();
System.out.println("id=" + propertiesHandler.getID());
try {
//get the correct own IP
InetAddress trueIP = IPManager.getTrueIP(propertiesHandler.getIpPrefix());
if (trueIP == null)throw new NullPointerException();
System.out.println("trueIP=" + trueIP.getHostAddress());
//send the request to server
HttpRequester.sendRequest(propertiesHandler.getServerUrl(),
propertiesHandler.getID(), trueIP.getHostAddress());
} catch (NullPointerException e) {
System.err.println("no matching IP found");
} catch (IOException e) {
System.err.println("connection error");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
What is going on here is rather simple.
Server side
The server side was implemented as a java servlet. It keeps internally a list of all the devices that have reported their ID-IP pair. An entry is added in the list (or updated) every time a compatible PUT request is received:
1
2
3
4
5
6
7
8
9
10
11
12
protected void doPut(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// PRINT CLIENT IP
String addr = request.getRemoteAddr();
System.out.println("got PUT request from " + addr);
// ---
DeviceEntry deviceEntry = new DeviceEntry(request.getParameter("id"),
request.getParameter("ip"));
devicesList.addOrUpdate(deviceEntry);
}
Whenever a GET request is received, it responds with an an HTML page containing a table with all the current entries:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// PRINT CLIENT IP
String addr = request.getRemoteAddr();
System.out.println("got GET request from " + addr);
PrintWriter out = response.getWriter();
out.print("<html><body>");
devicesList.printAsHtmlTable(out);
out.print("</body></html>");
}
Το complete the system, a unique ID should be given to each RPi and the IPReporter.properties
file on each RPi must be modified accordingly.
Finally, a “cron job” can be used to execute IPReporter.jar
every time the RPi is booted. This can be done by executing crontab -e
to edit crontab and adding one or more suitable lines, e.g.:
@reboot sudo java -jar IPReporter.jar
* * * * * sudo java -jar IPReporter.jar