Tutorial for jCoAP Hands-on
In this tutorial we will explain how to develop a simple message exchange between devices using jCoAP.
Furthermore, we will introduce the observe mechanism.
The following points will be covered by this tutorial:
- Installation of Copper plugin for Mozilla Firefox
- Introduction of jCoAP
- Import of prepared project into Eclipse
- Task 1: Implementation of client/server and enable simple message exchange
- Task 2: Implementation of an air conditioner control by using the CoAP-observe mechanism
1. Requirements for this tutorial
- Java SE JDK 1.6+
- Eclipse IDE for Java development
- Prepared Java project files for Hands-on
2. Installation of the Copper Plugin for Mozilla Firefox
- https://addons.mozilla.org/de/firefox/addon/copper-270430/
- Click on
add to Firefox
and Confirm Installation - Restart Firefox
After the installation you can enter anything like coap://host:port/resourcePath/?query=filter
in the address bar.
Copper will allow you to make any CoAP interaction.
3. Introduction of jCoAP
- WS4D-jCoAP: Java implementation of CoAP
- http://ws4d.org/
- https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap
Client Side
CoapClient: Interface that must be implemented by a client
Client: Customized implementation of a client application, implements CoapClient
Channel: A channel represents a connection between a Client and a Server
ChannelManager: Manages Channels
(Timeouts, Matching Requests and Responses)
Server Side
CoapResource: Interface that must be supported by each resource.
BasicCoapResource: Already implemented resource with basic functionality, implements CoapResource
TemperatureResource: Example of a customized resource, inherits from BasicCoapResource
CoapServer: Interface that must be supported by a resource server
CoapResourceServer: Manages a list of resources, enables access of these resources from outside, implements CoapServer
Server: Example of a customized implementation of a server application, creates CoapResourceServer
and CoapResources
4. Import of prepared project into Eclipse
You can find the required files in our repository at https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/tree/master/ws4d-jcoap-handsOn
- [File » Import]
- [General » Existing Projects into Workspace]
- Browse
- Finish
- We have prepared some FIXME and TODO annotations:
- Just open the „Task“ view
- FIXMEs are for the first task (message exchange)
- TODOs are for the second task (observe and AC control)
- If you do not have a „Task“ view:
- [Window » Show View » Other]
- Type
task
- Select [General » Task] view
5. Task 1: Implementation of client/server and enable simple message exchange
Sequence Diagram
Server
- Create a new resource class TemperatureResource (already done in our example Server)
- Instantiate a new ResourceServer
- Instantiate a new TemperatureResource
- Add the TemperatureResource to the ResourceServer
- Start the ResourceServer
- Test
1. Create a new resource class TemperatureResource (TemperatureResource.java):
- We could have used the predefined
BasicCoapResource
-
BasicCoapResource
is a resource that just keeps a staticbyte[]
which is: - returned on GET requests
- replaced by the payload on PUT requests
- appended with the payload on POST requests
- deleted on DELETE requests
- We do not want a static
byte[]
- Instead we want a random number to be returned on a GET
- PUT, POST and DELETE are not used
- ->So we implemented
TemperatureResource
which extendsBasicCoapResource
with: - A constructor to initialize the resource and disallow POST, PUT and DELETE requests and
- Two get() methods:
CoapData get(List<CoapMediaType> mediaTypesAccepted);
CoapData get(List<String> query, List<CoapMediaType> mediaTypesAccepted);
2. Instantiate a new ResourceServer (Server.java, FIXME 0):
- Need a CoapResourceServer to maintain resources
CoapResourceServer resourceServer = new CoapResourceServer();
3. Instantiate a new TemperatureResource (Server.java, FIXME 1):
- Resources are created like normal objects
CoapResource resource = new CoapResource();
4. Add the TemperatureResource to the ResourceServer (Server.java, FIXME 2):
resourceServer.createResource(resource);
5. Start the ResourceServer (Server.java FIXME 3):
resourceServer.start(port);
resourceServer.start(); // equals port = CoapConstants.COAP_DEFAULT_PORT
6. Test:
- Run Server: Click on [Run » Run] in the Menu bar
- To stop the server, press the red terminate button in the console/task area
- Test it with Copper:
coap://127.0.0.1
- Stretch goal:
- Create another resource type e.g.: humidity or current time, use real sensor values if possible
- Tip: make a copy of
TemperatureResource.java
Client
- Establish a connection to the Server using the ChannelManager
- Create a CoapRequest & add some Options
- Send the CoapRequest
- Wait for CoapResponse & Print the CoapResponse on the console (already done in our example)
- Test
1. Establish a connection to the Server using the ChannelManager (Client.java, FIXME 4-5):
- A client must implement CoapClient interface
public class Client implements CoapClient {...}
- A CoapChannelManager is used to manage different connections and to establish a connection to a server
channelManager = BasicCoapChannelManager.getInstance();
clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);
2. Create a CoapRequest & add some Options (Client.java, FIXME 6-8):
- A channel represents a single connection and is used to create and send requests
Boolean reliable = false;
CoapRequestCode reqCode = CoapRequestCode.GET;
CoapRequest request = clientChannel.createRequest(reliable,reqCode);
request.setUriPath("/temperature");
3. Send the CoapRequest (Client.java, FIXME 9):
clientChannel.sendMessage(request);
4. Wait for CoapResponse & Print the CoapResponse on the console:
- A client has some callbacks that are invoked, when the corresponding event occurs
public void onConnectionFailed(...);
public void onResponse(...); // = Unicast
public void onMCResponse(...); // MC = Multicast
5. Test:
- Run Server: select Server.java and click on [Run » Run] in the Menu bar
- Run Client: select Client.java and click on [Run » Run] in the Menu bar
- Stretch goal:
- If you have written your own resources before: GET them
- GET the
/.well-known/core
resource (it is generated automatically by the server) - GET the
/.well-known/core
resource using multicast (aka. Multicast Discovery)
// Multicast addresses
// CoapConstants.COAP_ALL_NODES_IPV4_MC_ADDR
// CoapConstants.COAP_ALL_NODES_IPV6_LL_MC_ADDR
// CoapConstants.COAP_ALL_NODES_IPV6_SL_MC_ADDR
// On Multicast: add token to match multicast request and unicast responses
request.setToken("MCToken".getBytes());
6. Task 2: Implementation of a AC control by using the CoAP-observe mechanism
- Use the eventing mechanism CoAP-Observe
- Let the server notify clients every 5 seconds about a changed TemperatureResource
- Implement an Air Conditioner Resource with the path
/ACControl
, that can be set tohigh
,medium
,low
oroff
1. Use the eventing mechanism CoAP-Observe (Server.java, TODO 10):
- Mark the TemperatureResource as observable
resource.setObservable(true);
2. Let server notify clients every 5 s about changed TemperatureResource (Server.java, TODO 11):
- indicate a change for resource every 5 seconds
while (true) {
try {Thread.sleep(5000);}
catch (InterruptedException e) {/*do nothing*/}
resource.changed(); // Notify
}
/ACControl
, that can be set to high
, medium
, low
or off
(Client.java & Server.java, TODO 12-15):
3. Implement an Air Conditioner Resource with the path - Change exitAfterResponse to false (Client.java, TODO 12)
- Add the observe-option to your CoAP-GET request (Client.java, TODO 13)
request.setObserveOption(0);
- add a BasicCoapResource to the ResourceServer (Server.java, TODO 14)
resourceServer.createResource(newBasicCoapResource("/ACControl","off",CoapMediaType.text_plain));
- send PUT request (Client.java, TODO 15)
CoapRequest request = clientChannel.createRequest(true, CoapRequestCode.PUT);
request.setUriPath("/ACControl");
request.setContentType(CoapMediaType.text_plain);
Depending on the received temperature, set the payload to high, medium, low or off
high 28 <= Temperature
medium 25 <= Temperature < 28
low 21 <= Temperature < 25
off Temperature < 21
request.setPayload("medium".getBytes());
clientChannel.sendMessage(request);