The world is changing and becoming more connected every day and the Internet of Things ‘IoT’ is taking off like a rocket ship. What if you have an idea for a tiny embedded device and you wanted to control it through your browser or your smart phone? Here is an example of how to do just that. It uses a Raspberry Pi and a tiny program that simply reads the time. Then it shows how to make a web server that will connect to the program and retrieve the time for any browser to show. Its got to be one of the world’s simplest web servers.
In this example, I use a Raspberry Pi running on Linux, but in truth you can use any computer. The embedded program is written in Java and the web server programming is written with PHP, HTML and Javascript. A tiny bit of AJAX is introduced.
The Basic Idea
The graphic below shows how these objects are organized. Think about some device that you may want to use. Maybe you want to make a computerized sprinkler system for your yard or maybe you want to make a smart toaster. Those are what I mean when I say ‘device’. My simple device doesnt do anything fancy like like monitor a sprinkler system. It will only read the time from its hardware clock and report it to whoever requests it. I named this program TimeServer and since I am programming it in java, the full name is TimeServer.Jar.
Fig. 1- The Simple Connected Device |
The TimeServer actually does two things. As I already stated, it reads the time but it also needs a way to give to communicate to other things. The easiest and most generic way to communicate with devices is with Sockets. Think of it as like using a telephone line to call someone. The TimeServer just sits there waiting for somebody (or something) to call it and then ask for the time. The TimeServer responds with the time and then hangs up. This is why the graphic shows a TimeModel.java and a SocketServer.java inside of the TimeServer application.
With this approach, we can create any number of programs that can connect to the TimeServer and get the time. Not only that, the programs can be running locally on the same computer as the TimeServer or they can be running on any other external computer (as long as you can connect to the TimeServer across an ethernet connection).
In our example, we are going to have the Web Server create a SocketClient and use that to connect to the TimeServer. We will do this because we want any browser to display our time and browsers ultimately connect to web servers. To be perfectly honest, I am misusing the term Web Server a little bit. We are not actually writing a web server, as they are large complicated programs that are loaded with features. What we are doing is writing script to tell the web server what we want it to do. That is known as server side scripting and we are using PHP as the scripting language. Also included in our PHP scripts is some HTML and Javascript. Browsers speak the language of HTML and Javascript and the Web Server will send all of that over to any browser that initiates a connection.
The TimeServer App
My TimeServer consists of four classes.
- TimeModel.java - for reading and formatting the time
- SocketServer.java - for handling a socket connection
- TimeServer.java - the logic for reading and handling requests
- TimeServerEntry.java - The main program which launches TimeServer in its own thread
The Time Model
As you can see below, all TimeModel.java does is read the system time and format it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The Socket Server
The socket server is also quite simple. When it is created, it is given a socket object which it uses to read and write messages (ReadLine and PrintLn). The only other function is for closing the connection when it is done. Any errors will be output to the console that launched the app.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
The Time Server
The TimeServer is really the heart of the app. It has no window or user interface and I want it to run in the background so I made the TimeServer work on its own thread. You can see that the class extends the ‘Thread’ class which will allow me to do this. The TimeServer also creates instances of the TimeModel and SockServer classes that I have already introduced.
When your class exends the Thead class, you will need to implement the function run() as you see I have done in the source below. In my case, the run function is simply a loop that listens for incoming messages from the socket. When it receives a message, it looks for a “:” and then a “1”. This is my idea of a super simple command structure. “:1”, “:2”, “:3”, etc. could be three different commands, although only “:1” is implemented in this demo. When it does get a “:1”, then it will respond get the time from the TimeModel and write it out to the SockServer.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
The Entry Point (The Main)
The entry point is really just a way to start my app. It creates a ServerSocket on port number 444 and then enters a loop where it listens for connections. When it gets a connection, it accepts it and creates a new TimeServer object which will be launched on its own thread. The start() call is what kicks off the thread’s run() function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
The Web Server Script
Whenever a browser connects with a web server, the web server will (if on Linux) go to /var/www and look for index.htm to pass on to the browser. But in this case, I have placed a php file named index.php along with some other files into the /var/www directory. These files are:
- index.php - standard html and javascript for output to browsers
- getTime.php - script for creating a socket and communicating with the TimeServer
- header.php - standard header
- admin.css - some formatting
Fig 2. shows what the browser will initially dislplay
Fig. 2- Initial Output to Browser |
header.php
The header is pretty standard. It describes basic information for the browser such as the html version and some metadata. It also includes our admin.css file. The admin.css file (not shown) defines what colors and styles you want html objects like buttons and text fields to be. Our header.php is loaded by the index.php file.
1 2 3 4 5 |
|
index.php
If you look at the index.php file below, you can see that it is actually written with three different languages. The first three lines are written in php and load the header. The second section is Javascript which will be explained shortly. The bottom section is HTML and defines a table with buttons and text fields. The buttons onClick properties call the above Javascript functions. The text fields are written with the ‘div’ tag and have id’s so that the Javascript can search for them in the document and replace their displayed text.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
Look in the HTML section and find the first button. You can see that its onclick property will call the loadXMLDoc function and pass a 1 as a parameter. Now look up in the Javascript section and find the loadXMLDoc(state) function.
1 2 3 4 |
|
The function loadXMLDoc first creates a XMLHttpRequest object. This powerful Javascript object provides an easy way to retrieve data from a URL and update just a part of the page without having to do a full page refresh. This object is the basis for AJAX programming.
It then sets an inline function to the XMLHttpRequest’s onreadystatechange event. This event will be fired and the function will be invoked when the TimeServer response is ready to be processed. The function itself looks into the html document and finds the element by the id. In this example; it searches for the object with the id “myTime” and then replaces the objects text with the TimeServer’s response text.
Next, we want to use the XMLHttpRequest to send a request to the TimeServer to retrieve the time. To do this, we need to use the open method to specify the type of request, the URL and whether the request is syncronous or not. Then we need to call send like so:
1 2 |
|
getTime.php
Once the user presses the button, the GET is called on getTime.php and the parameter “1” is passsed in and stored in the property $s. Then the code switches on $s and runs case “1”. The codeblock of case 1 creates a client socket and connects to the localhost on port 444 which is the TimeServer App. If everything is successfull, we form the message to send “:1” and call socket_write. After we are sure that the entire message is written, we call socket_read and set the return value into $rdVal. We echo the result, shutdown the socket and then close it.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
The echoed result from getTime.php is captured by the XMLHttpRequest object’s GET function. This triggers the onReadyStateChange event to fire and run our defined function(). Remember, the function searches our document for the element with the id of “myTime” and copies the responseText (from the echo) into the element’s innerHTML thereby replacing the displayed text.
Get Continual Time Updates
In order to get the time to update automatically, we have to create a timer in Javascript. The second button’s onClick method calls the Javascript startStopTimer(). Here, we evaluate a flag called timerIsOn to decide whether to start or stop the timer. If the timer is on, then we toggle the flag to off, then call clearInterval to stop the timer and then search the document for the element with the id of “myTimeStream” and replace the text with “Halted”.
If the timer is off, then we toggle the flag to on and then start the timer with the call setInterval and pass in a function pointer and the desired interval (in milliseconds). This simply means that the function will be called at the desired interval while the timer is running. Finally, we search for the element with the id of “myTimeStream” and replace the text with “Running”.
In our case, we call loadXMLDoc(1) every second and as a result, you should see the time update every second.
Fig. 3- Output to Browser |
Putting it All Together
Compile the java project and export as a jar file. I compiled the project on my laptop and copied it to a projects folder on my raspberry pi. Then open a terminal and navigate to the folder where your jar file is located. Then launch the TimeServer with the following command.
1
|
|
You should see the output on your terminal. To test your project, you can open your browser on the raspberry pi and type localhost in the url. You should see the initial dislay. I could not get the browsers on the raspberry pi to actually work. I am guessing that these browsers are not fully capable since the raspberry pi si such a small computer. But at least you should be able to see the initial display of the buttons and text.
Now open a browser on an different computer on the same network as the raspberry pi and type the ip address into the URL. Again, you should see the initial screen. Press the Button labeled ‘Get Once’ and watch the time update. Then press the button labeled ‘Observe Time’. The description should toggle to ‘Running’ and the Time should update continuously. If you press the button again, then the updates should stop.
Summary
Congratulations, you have just made a super tiny and simple web server using very inexpensive hardware. You can now add more functionality to your java program and extend the web page and make anything you desire. Go ahead and make your sprinkler system or security camera or whatever. You will be able to interact with your device using the browser on your cell phone or desktop.
Go ahead and do cool things.