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 air conditioner 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
![Task 1 – Sequence Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/Task1Sequence.png)
#### Client Side #### 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) ![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 **CoapClient:** Interface that must be implemented by a client
**Client:** individual implementation of a client application, implements CoapClient (interface) **Client:** Customized implementation of a client application, implements `CoapClient`
**ChannelManager:** manages channels **Channel:** A channel represents a connection between a Client and a Server
**Channel:** one channel represents a connection to one client **ChannelManager:** Manages `Channels` (Timeouts, Matching Requests and Responses)
#### Server Side #### Server Side
![Server Side UML Diagram](https://gitlab.amd.e-technik.uni-rostock.de/ws4d/jcoap/raw/master/ws4d-jcoap-handsOn/img/ServerUML.jpg) ![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. **CoapResource:** Interface that must be supported by each resource.
**BasicCoapResource:** already implemented resource with basic functionality, implements CoapResource (interface) **BasicCoapResource:** Already implemented resource with basic functionality, implements `CoapResource`
**TemperatureResource:** individual resource, inherits from BasicCoapResource **TemperatureResource:** Example of a customized resource, inherits from `BasicCoapResource`
**CoapServer (interface):** describes interfaces that must be supported by a resource server **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 (interface) **CoapResourceServer:** Manages a list of resources, enables access of these resources from outside, implements `CoapServer`
**Server:** individual implementation of a server application, creates CoapResourceServer and resources **Server:** Example of a customized implementation of a server application, creates `CoapResourceServer` and `CoapResources`
* 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
* ToDo on client side:
1. Establish a connection to the Server using the ChannelManager
2. Create a CoapRequest & add some Options
3. Send the CoapRequest
4. Wait for CoapResponse
5. Print the CoapResponse on the console
## 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,10 +80,9 @@ You can find the required files in our repository at https://gitlab.amd.e-techni ...@@ -101,10 +80,9 @@ 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
...@@ -112,35 +90,47 @@ You can find the required files in our repository at https://gitlab.amd.e-techni ...@@ -112,35 +90,47 @@ You can find the required files in our repository at https://gitlab.amd.e-techni
* 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
public class Client implements CoapClient {...}
```
* A CoapChannelManager is used to manage different connections and to establish a connection to a server * A CoapChannelManager is used to manage different connections and to establish a connection to a server
`channelManager = BasicCoapChannelManager.getInstance();` ```java`
`clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);` channelManager = BasicCoapChannelManager.getInstance();
clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);
```
#### 2. Create a CoapRequest & add some Options (Client.java, FIXME 6-8): #### 2. Create a CoapRequest & add some Options (Client.java, FIXME 7-9):
* A channel represents a single connection and is used to create and send requests * A channel represents a single connection and is used to create and send requests
`Boolean reliable = false;` ```java
`CoapRequestCode reqCode = CoapRequestCode.GET;` Boolean reliable = false;
`CoapRequest request = clientChannel.createRequest(reliable,reqCode);` CoapRequestCode reqCode = CoapRequestCode.GET;
`request.setUriPath("/temperature");` CoapRequest request = clientChannel.createRequest(reliable,reqCode);
request.setUriPath("/temperature");
#### 3. Send the CoapRequest (Client.java, FIXME 6-8): ```
`clientChannel.sendMessage(request);`
#### 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);
```
* add a BasicCoapResource to the ResourceServer (Server.java, TODO 14)
```java
resourceServer.createResource(newBasicCoapResource(/ACControl,off,CoapMediaType.text_plain));
```
* send PUT request (Client.java, TODO 15) * send PUT request (Client.java, TODO 15)
`CoapRequest request = clientChannel.createRequest(true, CoapRequestCode.PUT);` ```java
`request.setUriPath(“/ACControl”);` CoapRequest request = clientChannel.createRequest(true, CoapRequestCode.PUT);
`request.setContentType(CoapMediaType.text_plain);` request.setUriPath(/ACControl);
request.setContentType(CoapMediaType.text_plain);
```
Depending on the received temperature, set the payload to high, medium, low or off Depending on the received temperature, set the payload to high, medium, low or off
high -> 28 <= Temperature | high | 28 <= Temperature |
medium -> 25 <= Temperature < 28 | medium | 25 <= Temperature < 28 |
low -> 21 <= Temperature < 25 | low | 21 <= Temperature < 25 |
off -> Temperature < 21 | off | Temperature < 21 |
`request.setPayload(“medium”.getBytes());` ```java
`clientChannel.sendMessage(request);` request.setPayload(medium.getBytes());
clientChannel.sendMessage(request);
```
\ No newline at end of file