formatting of eclipse import tutorial authored by Björn Butzin's avatar Björn Butzin
# Tutorial for jCoAP Hands-on # Tutorial for jCoAP Hands-on
In this tutorial we will describe how to develop a simple message exchange between devices using jCoAP. In this tutorial we will explain how to develop a simple message exchange between devices using jCoAP.
Furthermore, we will introduce the observe mechanism. Furthermore, we will introduce the observe mechanism.
The following points will be covered by this tutorial: The following points will be covered by this tutorial:
1. Installation of Copper Plugin for Mozilla Firefox 1. Installation of Copper plugin for Mozilla Firefox
2. Introduction of jCoAP (based on Task 1) 2. Introduction of jCoAP
3. Import of prepared project into Eclipse 3. Import of prepared project into Eclipse
4. Task 1: Implementation of client/server and enable simple message exchange 4. Task 1: Implementation of client/server and enable simple message exchange
5. Task 2: Implementation of an airconditioner control by using the CoAP-observe mechanism 5. Task 2: Implementation of an air conditioner control by using the CoAP-observe mechanism
## 1. Requirements for this tutorial ## 1. Requirements for this tutorial
* JAVA SE JDK 1.6+ * Java SE JDK 1.6+
* Eclipse IDE for JAVA development * Eclipse IDE for Java development
* Prepared JAVA project files for Hands-on * Prepared [Java project files for Hands-on](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/tree/master/ws4d-jcoap-handsOn)
## 2. Installation of Copper Plugin for Mozilla Firefox ## 2. Installation of the Copper Plugin for Mozilla Firefox
- https://addons.mozilla.org/de/firefox/addon/copper-270430/ - [https://addons.mozilla.org/de/firefox/addon/copper-270430/](https://addons.mozilla.org/de/firefox/addon/copper-270430/)
- Click on add to Firefox“ & Confirm Installation - Click on `add to Firefox` and Confirm Installation
- Restart Firefox - Restart Firefox
After the installation you can enter coap://host:port/resourcePath/?query=filter. 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 interactively. Copper will allow you to make any CoAP interaction.
![Copper Screenshot](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/CopperScreenshot.jpg) ![Copper Screenshot](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/CopperScreenshot.jpg)
## 3. Introduction of jCoAP ## 3. Introduction of jCoAP
- WS4D-jCoAP: Java implementation of CoAP - WS4D-jCoAP: Java implementation of CoAP
- http://ws4d.org/ - [http://ws4d.org/](http://ws4d.org/)
- https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap - [https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap)
### Task 1 – Sequence Diagram #### Client Side
![Task 1 – Sequence Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Task1Sequence.png) ![Client Side UML Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Client%20UML.jpg)
#### Client Side
![Client Side UML Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Client%20UML.jpg)
**CoapClient (interface):** describes interfaces that must be supported by a client
**Client:** individual implementation of a client application, implements CoapClient (interface)
**ChannelManager:** manages channels
**Channel:** one channel represents a connection to one client
#### Server Side
![Server Side UML Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/ServerUML.jpg)
**CoapResource (interface):** describes interfaces that must be supported by each resource. **CoapClient:** Interface that must be implemented by a client
**BasicCoapResource:** already implemented resource with basic functionality, implements CoapResource (interface) **Client:** Customized implementation of a client application, implements `CoapClient`
**TemperatureResource:** individual resource, inherits from BasicCoapResource **Channel:** A channel represents a connection between a Client and a Server
**CoapServer (interface):** describes interfaces that must be supported by a resource server **ChannelManager:** Manages `Channels` (Timeouts, Matching Requests and Responses)
**CoapResourceServer:** manages a list of resources, enables access of these resources from outside, implements CoapServer (interface)
**Server:** individual implementation of a server application, creates CoapResourceServer and resources
* ToDo on server side:
1. Create a new resource class TemperatureResource
2. Instantiate a new ResourceServer
3. Instantiate a new TemperatureResource
4. Add the TemperatureResource to the ResourceServer
5. Run the ResourceServer
#### Server Side
![Server Side UML Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/ServerUML.jpg)
* ToDo on client side: **CoapResource:** Interface that must be supported by each resource.
1. Establish a connection to the Server using the ChannelManager **BasicCoapResource:** Already implemented resource with basic functionality, implements `CoapResource`
2. Create a CoapRequest & add some Options **TemperatureResource:** Example of a customized resource, inherits from `BasicCoapResource`
3. Send the CoapRequest **CoapServer:** Interface that must be supported by a resource server
4. Wait for CoapResponse **CoapResourceServer:** Manages a list of resources, enables access of these resources from outside, implements `CoapServer`
5. Print the CoapResponse on the console **Server:** Example of a customized implementation of a server application, creates `CoapResourceServer` and `CoapResources`
## 4. Import of prepared project into Eclipse ## 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 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](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/tree/master/ws4d-jcoap-handsOn)
1. File > Import 1. *[File » Import]*
![Eclipse File Import](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/EclipseImport1.png) 2. *[General » Existing Projects into Workspace]*
2. General > Existing Projects ... 3. Browse <Project Folder>
3. Click ‚Next‘ 4. Finish
![Eclipse File Import](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/EclipseImport2.png)
4. Browse <Select Project Folder>
5. Click ‚Finish’
![Eclipse File Import](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/EclipseImport3.png)
* the resulting GUI should look like this:
![Eclipse GUI](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/GUI.png)
* We have prepared some FIXME and TODO annotations: * We have prepared some FIXME and TODO annotations:
* Just open the „Task“ view * Just open the „Task“ view
* FIXMEs are for the first task (message exchange) * FIXMEs are for the first task (message exchange)
* TODOs are for the second task (observe and AC control) * TODOs are for the second task (observe and AC control)
* If you do not have a „Task“ view: * If you do not have a „Task“ view:
* Window > Show View > Other * *[Window &raquo; Show View &raquo; Other]*
* Type task * Type `task`
* Select General > Task view * Select *[General &raquo; Task]* view
## 5. Task 1: Implementation of client/server and enable simple message exchange ## 5. Task 1: Implementation of client/server and enable simple message exchange
### Sequence Diagram
![Task 1 – Sequence Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Task1Sequence.png)
### Server ### Server
1. Create a new resource class TemperatureResource (already done in our example Server) 1. Create a new resource class TemperatureResource (already done in our example Server)
2. Instantiate a new ResourceServer 2. Instantiate a new ResourceServer
...@@ -101,46 +80,57 @@ You can find the required files in our repository at https://gitlab.amd.e-techni ...@@ -101,46 +80,57 @@ You can find the required files in our repository at https://gitlab.amd.e-techni
4. Add the TemperatureResource to the ResourceServer 4. Add the TemperatureResource to the ResourceServer
5. Run the ResourceServer 5. Run the ResourceServer
#### 1. Create a new resource class TemperatureResource (TemperatureResource.java): #### 1. Create a new resource class TemperatureResource (TemperatureResource.java):
* We could have used the predefined BasicCoapResource * We could have used the predefined BasicCoapResource
* BasicCoapResource is a resource that just keeps a static `byte[ ]` that is: * BasicCoapResource is a resource that just keeps a static `byte[]` which is:
* returned on GET requests * returned on GET requests
* replaced by the payload on PUT requests * replaced by the payload on PUT requests
* appended with the payload on POST requests * appended with the payload on POST requests
* deleted on DELETE requests * deleted on DELETE requests
* We do not want a static `byte[ ]` * We do not want a static `byte[]`
* Instead we want a random number to be returned on a GET * Instead we want a random number to be returned on a GET
* PUT, POST and DELETE are not used * PUT, POST and DELETE are not used
* ->So we implemented TemperatureResource wich extends BasicCoapResource with: * ->So we implemented TemperatureResource which extends BasicCoapResource with:
* A constructor to initialize the resource and disallow POST, PUT and DELETE requests * A constructor to initialize the resource and disallow POST, PUT and DELETE requests
* Two get() Methods: * Two get() Methods:
* Get a list of accepted media types [& query parameters] which returns a `byte[ ]` together with its media type * Get a list of accepted media types [& query parameters] which returns a `byte[]` together with its media type
```java
CoapData get(List<CoapMediaType> mediaTypesAccepted)
CoapData get(List<String> query, List<CoapMediaType> mediaTypesAccepted)
```
* And the `getResourceType()` method * And the `getResourceType()` method
* Wich returns a description string of the resource * Which returns a description string of the resource
#### 2. Instantiate a new ResourceServer (Server.java, FIXME 1): #### 2. Instantiate a new ResourceServer (Server.java, FIXME 1):
* Need a CoapResourceServer to maintain resources * Need a CoapResourceServer to maintain resources
`CoapResourceServer resourceServer = new CoapResourceServer();` ```java
CoapResourceServer resourceServer = new CoapResourceServer();
```
#### 3. Instantiate a new TemperatureResource (Server.java, FIXME 2): #### 3. Instantiate a new TemperatureResource (Server.java, FIXME 2):
* Resources are created like normal objects and added to the server * Resources are created like normal objects and added to the server
`CoapResource resource = new CoapResource();` ```java
CoapResource resource = new CoapResource();
```
#### 4. Add the TemperatureResource to the ResourceServer (Server.java, FIXME 3): #### 4. Add the TemperatureResource to the ResourceServer (Server.java, FIXME 3):
* Resources are created like normal objects and added to the server * Resources are created like normal objects and added to the server
`resourceServer.createResource(resource);` ```java
resourceServer.createResource(resource);
#### 5. Run the ResourceServer (Server.java): ```
`resourceServer.start();`
#### 5. Run the ResourceServer (Server.java FIXME 4):
```java
resourceServer.start(port);
resourceServer.start(); // equals port = CoapConstants.COAP_DEFAULT_PORT
```
* Run Server: Click on Run -> Run in the Menu bar * Run Server: Click on *[Run &raquo; Run]* in the Menu bar
* To stop the server, press the red terminate button in the console/task area * To stop the server, press the red terminate button in the console/task area
* Test it with Copper: coap://127.0.0.1 * Test it with Copper: `coap://127.0.0.1`
* Stretch goal: * Stretch goal:
* Create another resource type e.g.: humidity or current Time * Create another resource type e.g.: humidity or current Time, use real sensor values if possible
* Tip: make a copy of TemperatureResource.java * Tip: make a copy of `TemperatureResource.java`
### Client ### Client
1. Establish a connection to the Server using the ChannelManager 1. Establish a connection to the Server using the ChannelManager
...@@ -149,68 +139,95 @@ You can find the required files in our repository at https://gitlab.amd.e-techni ...@@ -149,68 +139,95 @@ You can find the required files in our repository at https://gitlab.amd.e-techni
4. Wait for CoapResponse 4. Wait for CoapResponse
5. Print the CoapResponse on the console (already done in our example) 5. Print the CoapResponse on the console (already done in our example)
#### 1. Establish a connection to the Server using the ChannelManager (Client.java, FIXME 4-5): #### 1. Establish a connection to the Server using the ChannelManager (Client.java, FIXME 5-6):
* A client must implement CoapClient interface * A client must implement CoapClient interface
`public class Client implements CoapClient {...}` ```java
* A CoapChannelManager is used to manage different connections and to establish a connection to a server public class Client implements CoapClient {...}
`channelManager = BasicCoapChannelManager.getInstance();` ```
`clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);` * A CoapChannelManager is used to manage different connections and to establish a connection to a server
```java`
#### 2. Create a CoapRequest & add some Options (Client.java, FIXME 6-8): channelManager = BasicCoapChannelManager.getInstance();
* A channel represents a single connection and is used to create and send requests clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);
`Boolean reliable = false;` ```
`CoapRequestCode reqCode = CoapRequestCode.GET;`
`CoapRequest request = clientChannel.createRequest(reliable,reqCode);` #### 2. Create a CoapRequest & add some Options (Client.java, FIXME 7-9):
`request.setUriPath("/temperature");` * A channel represents a single connection and is used to create and send requests
```java
#### 3. Send the CoapRequest (Client.java, FIXME 6-8): Boolean reliable = false;
`clientChannel.sendMessage(request);` CoapRequestCode reqCode = CoapRequestCode.GET;
CoapRequest request = clientChannel.createRequest(reliable,reqCode);
request.setUriPath("/temperature");
```
#### 3. Send the CoapRequest (Client.java, FIXME 7-9):
```java
clientChannel.sendMessage(request);
```
#### 4. Wait for CoapResponse & Print the CoapResponse on the console #### 4. Wait for CoapResponse & Print the CoapResponse on the console
* A client has some callbacks that are invoked, when the corresponding event occurs * A client has some callbacks that are invoked, when the corresponding event occurs
`public void onConnectionFailed(...)` ```java
`public void onResponse(...) // = Unicast` public void onConnectionFailed(...)
`public void onMCResponse(...) // MC = Multicast` public void onResponse(...) // = Unicast
public void onMCResponse(...) // MC = Multicast
```
* Run Server: select Server.java and click on Run -> Run in the Menu bar * Run Server: select Server.java and click on *[Run &raquo; Run]* in the Menu bar
* Run Client: select Client.java and click on Run -> Run in the Menu bar * Run Client: select Client.java and click on *[Run &raquo; Run]* in the Menu bar
* Stretch goal: * Stretch goal:
* GET the “/.well-known/core” resource (it is generated automatically by the server)
* If you have written your own resources before: GET them * 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 Adresses: `CoapConstants.COAP_ALL_NODES_IPV4_MC_ADDR`, `CoapConstants.COAP_ALL_NODES_IPV6_LL_MC_ADDR` and `CoapConstants.COAP_ALL_NODES_IPV6_SL_MC_ADDR`
```java
// add a (mandatory) token to match outgoing multicast message and incoming unicast messages
request.setToken("MCToken".getBytes());
```
## 6. Task 2: Implementation of a AC control by using the CoAP-observe mechanism ## 6. Task 2: Implementation of a AC control by using the CoAP-observe mechanism
![Task 2 - Sequence diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Task2Sequence.png) ![Task 2 - Sequence diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Task2Sequence.png)
1. Use the eventing mechanism CoAP-Observe 1. Use the eventing mechanism CoAP-Observe
2. Let the server notify clients every 5 seconds about a changed TemperatureResource 2. Let the server notify clients every 5 seconds about a changed TemperatureResource
3. Implement an Air Conditioner Resource with the path “/ACControl”, that can be set to “high”, 3. Implement an Air Conditioner Resource with the path `/ACControl`, that can be set to `high`, `medium`, `low` or `off`
“medium”, “low” or “off”
1. Use the eventing mechanism CoAP-Observe (Server.java, TODO 10): 1. Use the eventing mechanism CoAP-Observe (Server.java, TODO 10):
* Mark the TemperatureResource as observable * Mark the TemperatureResource as observable
`resource.setObservable(true);` ```java
resource.setObservable(true);
```
2. Let server notify clients every 5 s about changed TemperatureResource (Server.java, TODO 11): 2. Let server notify clients every 5 s about changed TemperatureResource (Server.java, TODO 11):
* indicate a change for resource every 5 seconds * indicate a change for resource every 5 seconds
`while (true) {` ```java
` try {Thread.sleep(5000);}` while (true) {
` catch (InterruptedException e) {/*do nothing*/}` try {Thread.sleep(5000);}
` resource.changed();` catch (InterruptedException e) {/*do nothing*/}
`}` resource.changed();
3. Implement an Air Conditioner Resource with the path “/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 `/ACControl`, that can be set to `high`, `medium`, `low` or `off` (Client.java & Server.java, TODO 12-15):
* Change exitAfterResponse to false (Client.java, TODO 12) * Change exitAfterResponse to false (Client.java, TODO 12)
* Add the observe-option to your CoAP-GET request (Client.java, TODO 13) * Add the observe-option to your CoAP-GET request (Client.java, TODO 13)
`request.setObserveOption(0);` ```java
* add a BasicCoapResource to the ResourceServer (Server.java, TODO 14) `resourceServer.createResource(newBasicCoapResource(“/ACControl”,”off”,CoapMediaType.text_plain));` request.setObserveOption(0);
* send PUT request (Client.java, TODO 15) ```
`CoapRequest request = clientChannel.createRequest(true, CoapRequestCode.PUT);` * add a BasicCoapResource to the ResourceServer (Server.java, TODO 14)
`request.setUriPath(“/ACControl”);` ```java
`request.setContentType(CoapMediaType.text_plain);` resourceServer.createResource(newBasicCoapResource(/ACControl,off,CoapMediaType.text_plain));
Depending on the received temperature, set the payload to high, medium, low or off ```
high -> 28 <= Temperature * send PUT request (Client.java, TODO 15)
medium -> 25 <= Temperature < 28 ```java
low -> 21 <= Temperature < 25 CoapRequest request = clientChannel.createRequest(true, CoapRequestCode.PUT);
off -> Temperature < 21 request.setUriPath(/ACControl);
`request.setPayload(“medium”.getBytes());` request.setContentType(CoapMediaType.text_plain);
`clientChannel.sendMessage(request);` ```
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 |
```java
request.setPayload(medium.getBytes());
clientChannel.sendMessage(request);
```
\ No newline at end of file