|
|
# 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.
|
|
|
|
|
|
The following points will be covered by this tutorial:
|
|
|
|
|
|
1. Installation of Copper Plugin for Mozilla Firefox
|
|
|
2. Introduction of jCoAP (based on Task 1)
|
|
|
1. Installation of Copper plugin for Mozilla Firefox
|
|
|
2. Introduction of jCoAP
|
|
|
3. Import of prepared project into Eclipse
|
|
|
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
|
|
|
* JAVA SE JDK 1.6+
|
|
|
* Eclipse IDE for JAVA development
|
|
|
* Prepared JAVA project files for Hands-on
|
|
|
* Java SE JDK 1.6+
|
|
|
* Eclipse IDE for Java development
|
|
|
* 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/
|
|
|
- Click on „add to Firefox“ & Confirm Installation
|
|
|
- [https://addons.mozilla.org/de/firefox/addon/copper-270430/](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 coap://host:port/resourcePath/?query=filter.
|
|
|
Copper will allow you to make any CoAP interaction interactively.
|
|
|
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
|
|
|
- [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)
|
|
|
|
|
|
### Task 1 – Sequence Diagram
|
|
|

|
|
|
|
|
|
#### Client Side
|
|
|

|
|
|
|
|
|
**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
|
|
|

|
|
|
#### Client Side
|
|
|

|
|
|
|
|
|
**CoapResource (interface):** describes interfaces that must be supported by each resource.
|
|
|
**BasicCoapResource:** already implemented resource with basic functionality, implements CoapResource (interface)
|
|
|
**TemperatureResource:** individual resource, inherits from BasicCoapResource
|
|
|
**CoapServer (interface):** describes interfaces that must be supported by a resource server
|
|
|
**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
|
|
|
**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)
|
|
|
|
|
|
* 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
|
|
|

|
|
|
|
|
|
* 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
|
|
|
**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
|
|
|
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
|
|
|

|
|
|
2. General > Existing Projects ...
|
|
|
3. Click ‚Next‘
|
|
|

|
|
|
4. Browse <Select Project Folder>
|
|
|
5. Click ‚Finish’
|
|
|

|
|
|
|
|
|
* the resulting GUI should look like this:
|
|
|

|
|
|
1. *[File » Import]*
|
|
|
2. *[General » Existing Projects into Workspace]*
|
|
|
3. Browse <Project Folder>
|
|
|
4. 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
|
|
|
* *[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
|
|
|
1. Create a new resource class TemperatureResource (already done in our example Server)
|
|
|
2. Instantiate a new ResourceServer
|
... | ... | @@ -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
|
|
|
5. Run the ResourceServer
|
|
|
|
|
|
|
|
|
#### 1. Create a new resource class TemperatureResource (TemperatureResource.java):
|
|
|
* 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
|
|
|
* 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[ ]`
|
|
|
* 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 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
|
|
|
* 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
|
|
|
* 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):
|
|
|
* Need a CoapResourceServer to maintain resources
|
|
|
`CoapResourceServer resourceServer = new CoapResourceServer();`
|
|
|
```java
|
|
|
CoapResourceServer resourceServer = new CoapResourceServer();
|
|
|
```
|
|
|
|
|
|
#### 3. Instantiate a new TemperatureResource (Server.java, FIXME 2):
|
|
|
* Resources are created like normal objects and added to the server
|
|
|
`CoapResource resource = new CoapResource();`
|
|
|
* Resources are created like normal objects and added to the server
|
|
|
```java
|
|
|
CoapResource resource = new CoapResource();
|
|
|
```
|
|
|
|
|
|
#### 4. Add the TemperatureResource to the ResourceServer (Server.java, FIXME 3):
|
|
|
* Resources are created like normal objects and added to the server
|
|
|
`resourceServer.createResource(resource);`
|
|
|
|
|
|
#### 5. Run the ResourceServer (Server.java):
|
|
|
`resourceServer.start();`
|
|
|
```java
|
|
|
resourceServer.createResource(resource);
|
|
|
```
|
|
|
|
|
|
#### 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 » 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
|
|
|
* Test it with Copper: `coap://127.0.0.1`
|
|
|
* Stretch goal:
|
|
|
* Create another resource type e.g.: humidity or current Time
|
|
|
* Tip: make a copy of „TemperatureResource.java“
|
|
|
* Create another resource type e.g.: humidity or current Time, use real sensor values if possible
|
|
|
* Tip: make a copy of `TemperatureResource.java`
|
|
|
|
|
|
### Client
|
|
|
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 |
|
|
4. Wait for CoapResponse
|
|
|
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
|
|
|
`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 6-8):
|
|
|
`clientChannel.sendMessage(request);`
|
|
|
```java
|
|
|
public class Client implements CoapClient {...}
|
|
|
```
|
|
|
* A CoapChannelManager is used to manage different connections and to establish a connection to a server
|
|
|
```java`
|
|
|
channelManager = BasicCoapChannelManager.getInstance();
|
|
|
clientChannel = channelManager.connect(CoapClient client,InetAddress serverIP, int serverPort);
|
|
|
```
|
|
|
|
|
|
#### 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
|
|
|
```java
|
|
|
Boolean reliable = false;
|
|
|
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
|
|
|
* 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`
|
|
|
* A client has some callbacks that are invoked, when the corresponding event occurs
|
|
|
```java
|
|
|
public void onConnectionFailed(...)
|
|
|
public void onResponse(...) // = Unicast
|
|
|
public void onMCResponse(...) // MC = Multicast
|
|
|
```
|
|
|
|
|
|
|
|
|
* 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
|
|
|
* 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:
|
|
|
* GET the “/.well-known/core” resource (it is generated automatically by the server)
|
|
|
* 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
|
|
|

|
|
|
1. Use the eventing mechanism CoAP-Observe
|
|
|
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”,
|
|
|
“medium”, “low” or “off”
|
|
|
3. Implement an Air Conditioner Resource with the path `/ACControl`, that can be set to `high`, `medium`, `low` or `off`
|
|
|
|
|
|
|
|
|
1. Use the eventing mechanism CoAP-Observe (Server.java, TODO 10):
|
|
|
* Mark the TemperatureResource as observable
|
|
|
`resource.setObservable(true);`
|
|
|
* Mark the TemperatureResource as observable
|
|
|
```java
|
|
|
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();`
|
|
|
`}`
|
|
|
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):
|
|
|
* indicate a change for resource every 5 seconds
|
|
|
```java
|
|
|
while (true) {
|
|
|
try {Thread.sleep(5000);}
|
|
|
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):
|
|
|
* 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);`
|
|
|
|
|
|
* Add the observe-option to your CoAP-GET request (Client.java, TODO 13)
|
|
|
```java
|
|
|
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)
|
|
|
```java
|
|
|
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 |
|
|
|
```java
|
|
|
request.setPayload(“medium”.getBytes());
|
|
|
clientChannel.sendMessage(request);
|
|
|
``` |
|
|
\ No newline at end of file |