| <?xml version="1.0" encoding="UTF-8"?> |
| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> |
| <channel> |
| <title>Eclipse Ditto Blog</title> |
| <description>Announcements, tutorials and examples around Eclipse Ditto and Digital Twins</description> |
| <link>https://www.eclipse.org/ditto/</link> |
| <atom:link href="https://www.eclipse.org/ditto/feed.xml" rel="self" type="application/rss+xml"/> |
| <pubDate>Fri, 23 Oct 2020 13:54:45 +0000</pubDate> |
| <lastBuildDate>Fri, 23 Oct 2020 13:54:45 +0000</lastBuildDate> |
| <generator>Jekyll v3.6.2</generator> |
| |
| <item> |
| <title>E2E acknowledgment</title> |
| <description><h2 id="e2e-acknowledgement-using-eclipse-ditto">E2E acknowledgement using Eclipse Ditto</h2> |
| |
| <p>By adding the new <a href="basic-acknowledgements.html">acknowledgements feature</a> to Ditto, it is now possible to provide an end to end QoS (quality of service) with level 1. |
| Previously the <a href="architecture-services-connectivity.html">connectivity service</a> of Ditto did accept all incoming messages immediately as soon as it received the message.</p> |
| |
| <p>This behaviour can now be controlled by a Ditto header called <a href="basic-acknowledgements.html#requesting-acks"><code class="highlighter-rouge">requested-acks</code></a>.</p> |
| |
| <p>In this blog post I will provide a few examples for how to use this new feature in the following scenarios:</p> |
| |
| <ol> |
| <li>Device publishes a change of its state and doesn’t care about whether the event regarding this change will be received by any subscriber or not.<br /> |
| This is the <a href="#scenario-1---fire-and-forget">fire and forget</a> scenario.</li> |
| <li>Device publishes a change of its state and wants to be sure it is persisted in Ditto.<br /> |
| This is the <a href="#scenario-2---processed-in-ditto">processed in Ditto</a> scenario.</li> |
| <li>Device publishes a change of its state and wants to be sure an application connected to Eclipse Ditto will receive the event regarding this change of the state.<br /> |
| This is the <a href="#scenario-3---notification-scenario">notification</a> scenario.</li> |
| <li>Device publishes a change of its state and wants to be notified when a subscriber was not able to receive the event regarding this change.<br /> |
| This is the <a href="#scenario-4---tracked-notification-scenario">tracked notification</a> scenario.</li> |
| <li>Device sends a live message and wants to be sure that it will eventually receive a response.<br /> |
| This is the <a href="#scenario-5---long-running-live-message-scenario">long running live message</a> scenario.</li> |
| <li>Device sends a live message and wants to either receive the response within a given timeout or never.<br /> |
| This is the <a href="#scenario-6---asking-for-required-information-scenario">asking for required information</a> scenario.</li> |
| </ol> |
| |
| <h2 id="scenarios">Scenarios</h2> |
| |
| <p>The following scenarios all share the same context:</p> |
| <ul> |
| <li>a device sends data/messages via a device connectivity layer (e.g. <a href="https://eclipse.org/hono/">Eclipse Hono</a> or an MQTT broker) to Ditto</li> |
| <li>Ditto’s <a href="architecture-services-connectivity.html">connectivity service</a> |
| <ul> |
| <li>consumes the <a href="protocol-specification.html">Ditto Protocol</a> message</li> |
| <li>forwards the message into the Ditto cluster to be processed</li> |
| <li>is responsible for technically acknowledging/settling the consumed message at the device connectivity layer / broker |
| <ul> |
| <li>the strategy of when this is done and with which outcome is handled by the Ditto headers mentioned in the scenarios</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p>Although all scenarios are based on the device sending something (e.g. telemetry data or a message), the |
| E2E acknowledgement can also be used the other way around when e.g. a backend application sends something to a device.</p> |
| |
| <h3 id="scenario-1---fire-and-forget">Scenario 1 - Fire and Forget</h3> |
| |
| <p>This is the simplest scenario of all, since the change can be published in a fire and forget semantics.</p> |
| |
| <p>In this scenario the device will send the modification command containing the headers:</p> |
| <ul> |
| <li><code class="highlighter-rouge">response-required=false</code></li> |
| <li><code class="highlighter-rouge">requested-acks=[]</code></li> |
| </ul> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/twin/commands/modify"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/features/lightSwitch/properties/status"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"on"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>For this case the connectivity service will immediately acknowledge the incoming message at the messaging system and then continues to process the command.</p> |
| |
| <p>It doesn’t matter if the command could be processed successfully or if any subscriber received an event for this change.</p> |
| |
| <h3 id="scenario-2---processed-in-ditto">Scenario 2 - Processed in Ditto</h3> |
| |
| <p>For this scenario the device wants to be sure its change will be properly persisted in Ditto.</p> |
| |
| <p>The command needs to define the following headers:</p> |
| <ul> |
| <li><code class="highlighter-rouge">response-required=false</code></li> |
| <li><code class="highlighter-rouge">requested-acks=["twin-persisted"]</code></li> |
| </ul> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/twin/commands/modify"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"twin-persisted"</span><span class="p">]</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/features/lightSwitch/properties/status"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"on"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>For this case the connectivity service will wait until the modification will be properly persisted in Ditto before acknowledging the incoming message at the messaging system.</p> |
| |
| <p>If the device published this command for example via an AMQP broker (with a QoS 1 “at least once” semantic), |
| this will cause the broker to redeliver the command to Ditto if the acknowledgment fails.<br /> |
| Please be aware that a redelivery will only be requested for the following error status codes:</p> |
| <ul> |
| <li><code class="highlighter-rouge">408</code> (Request timed out)</li> |
| <li><code class="highlighter-rouge">424</code> (Dependency Failure)</li> |
| <li>All kinds of <code class="highlighter-rouge">5xx</code> status codes</li> |
| </ul> |
| |
| <p>In this scenario it does matter if the command could be processed successfully, but it’s still not relevant if any subscriber received an event for this change.</p> |
| |
| <h3 id="scenario-3---notification-scenario">Scenario 3 - Notification scenario</h3> |
| |
| <p>For this scenario the device wants to be sure another system will be notified about the change of its state.</p> |
| |
| <p>This could be for example an alarming system which wants to be sure a backend application receives the information that the alarm was triggered.</p> |
| |
| <p>A prerequisite for this is that any kind of connection exists that publishes the event to the backend application and declares a user defined acknowledgement label. |
| This can be a <a href="httpapi-protocol-bindings-websocket.html">WebSocket session</a> or any kind of Ditto Connection types which can be found <a href="connectivity-overview.html">here</a>.</p> |
| |
| <p>For this example we expect the event to be forwarded by an <a href="connectivity-protocol-bindings-http.html">HTTP connection</a> |
| which declared the following acknowledgement label as |
| <a href="basic-connections.html#target-issued-acknowledgement-label">issued acknowledgement of the target</a>: <code class="highlighter-rouge">d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed</code>.</p> |
| |
| <p>The UUID prefix in this case is the ID of the HTTP connection and the<code class="highlighter-rouge">backend-process</code> part is a custom label, defined by the user.</p> |
| |
| <p>The command needs to define the following headers:</p> |
| <ul> |
| <li><code class="highlighter-rouge">response-required=false</code></li> |
| <li><code class="highlighter-rouge">requested-acks=["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"]</code></li> |
| <li><code class="highlighter-rouge">timeout=30s</code> (optional. Default is 10s.)</li> |
| </ul> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/twin/commands/modify"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"</span><span class="p">],</span><span class="w"> |
| </span><span class="s2">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"30s"</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/features/alarm/properties/status"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"on"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>For this case the connectivity service will wait until the HTTP request, which forwards the event regarding the thing change, |
| will be finished before acknowledging the incoming message at the messaging system.</p> |
| |
| <p>The status code of the HTTP response will in this case determine if the message will be acknowledged successfully or not and if a redelivery will be requested or not.<br /> |
| All kinds of <code class="highlighter-rouge">2xx</code> status codes will lead to a successful acknowledgement at the messaging system.<br /> |
| All other status codes will lead to a failed acknowledgement at the messaging system and for the following status codes a redelivery will be requested:</p> |
| <ul> |
| <li><code class="highlighter-rouge">408</code> (Request timed out)</li> |
| <li><code class="highlighter-rouge">424</code> (Dependency Failure)</li> |
| <li>All kinds of <code class="highlighter-rouge">5xx</code> status codes</li> |
| </ul> |
| |
| <p>In this scenario it is ensured a specified subscriber will receive an event for this change.</p> |
| |
| <h3 id="scenario-4---tracked-notification-scenario">Scenario 4 - Tracked notification scenario</h3> |
| |
| <p>For this scenario the device wants to know when a system could not be notified about the change of its state.</p> |
| |
| <p>This could be for example an alarming system which wants to be sure a backend application receives the information, |
| or if not: tries to send an SMS as notification.</p> |
| |
| <p>This scenario is mostly like scenario 3, but needs to set the <code class="highlighter-rouge">response-required</code> header to <code class="highlighter-rouge">true</code> and it’s required |
| to <a href="basic-connections.html#source-reply-target">configure the reply-target of the source</a> to also expect “nack” responses.</p> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/twin/commands/modify"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"</span><span class="p">]</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/features/alarm/properties/status"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"on"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>In this case the device will receive an acknowledgement response containing the status code and payload of the response of the backend application.<br /> |
| Based on this the device can decide how to handle the situation.<br /> |
| It is suggested to publish the modification command with QoS 0 (“at most once” semantics) in this case because the |
| device handles the result of the E2E acknowledgement. With QoS 1 (“at least once” semantics) brokers would usually redeliver the message to Ditto.</p> |
| |
| <p>If the HTTP endpoint of the backend application responds with the following response:</p> |
| |
| <p>headers:</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"content-type": "application/json" |
| </code></pre></div></div> |
| |
| <p>body:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"errorCode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notification.smartphone.failed"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Could not notify smartphone."</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>status code: <code class="highlighter-rouge">424</code></p> |
| |
| <p>The response received at the device would look like this:</p> |
| |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/twin/acks/d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"</span><span class="p">],</span><span class="w"> |
| </span><span class="s2">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"30s"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/json"</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"errorCode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notification.smartphone.failed"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Could not notify smartphone."</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">424</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <h3 id="scenario-5---long-running-live-message-scenario">Scenario 5 - Long running live message scenario</h3> |
| |
| <p>For this scenario the device is going to ask for an information which it needs eventually.</p> |
| |
| <p>Let’s say the device asks for the endpoint where it should download the new firmware from.<br /> |
| It’s not required that this response arrives within a given time. It’s just required to eventually arrive at the device |
| and after it was received the device can signal the user, that it is ready to download the firmware.</p> |
| |
| <p>The headers of the live message should have the following values:</p> |
| <ul> |
| <li><code class="highlighter-rouge">response-required=true</code></li> |
| <li><code class="highlighter-rouge">requested-acks=["live-response"]</code></li> |
| </ul> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/live/messages/firmware"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"live-response"</span><span class="p">],</span><span class="w"> |
| </span><span class="s2">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"text/plain"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5s"</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/outbox/messages/firmware"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"firmware.url.query"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>By requesting the acknowledgement <code class="highlighter-rouge">live-response</code> the connectivity service will wait until the response for the live message arrived |
| for 5s before acknowledging the incoming message at the broker and will request a redelivery if the response did not arrive within this timeout.</p> |
| |
| <p>This will repeat until either the broker discards the message or the response arrives in the specified timeout. |
| That way it is guaranteed that the device will eventually receive the response.</p> |
| |
| <h3 id="scenario-6---asking-for-required-information-scenario">Scenario 6 - Asking for required information scenario</h3> |
| |
| <p>For this scenario the device is going to ask for an information which it needs right now to proceed with its current task.</p> |
| |
| <p>Let’s say the device asks if it should allow a car with a license plate it detected to drive on the property by opening the barrier. |
| It could be possible to ask for that information, so the barrier opens automatically, but providing a fallback mechanism |
| like entering a code directly at the device if this response does not arrive within time.</p> |
| |
| <p>The headers of the live message should have the following values:</p> |
| <ul> |
| <li><code class="highlighter-rouge">response-required=true</code></li> |
| <li><code class="highlighter-rouge">requested-acks=[]</code></li> |
| </ul> |
| |
| <p>Example <a href="protocol-specification.html">Ditto Protocol</a> message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/my-thing/things/live/messages/car-enter"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"headers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"response-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"requested-acks"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w"> |
| </span><span class="s2">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"text/plain"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5s"</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/outbox/messages/car-enter"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="s2">"FN IB 1337"</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>By requesting explicitly not requesting any acknowledgement but still requiring a response, the connectivity service will |
| immediately acknowledge the incoming message at the broker. The device will then either receive the response within the specified timeout or never. |
| So the device can provide its alternative options to open the barrier after 5 seconds.</p> |
| |
| <h2 id="we-embrace-your-feedback">We embrace your feedback</h2> |
| |
| <p>I hope I could demonstrate the power of the new acknowledgement feature properly and could make it clear how it can be used. |
| Maybe you did recognize some of your use cases in the given examples or maybe you have another use case which can or cannot be solved by this feature.</p> |
| |
| <p>We would love to get your feedback.</p> |
| |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Fri, 23 Oct 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-10-23-end-2-end-acknowledgment.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-10-23-end-2-end-acknowledgment.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Asynchronous Client Creation in Ditto Java Client 1.3.0</title> |
| <description><p>Before <a href="https://github.com/eclipse/ditto-clients/tree/master/java">Ditto Java Client</a> 1.3.0, |
| a client object connects to a configured Ditto back-end during its creation.</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// create a client object and block until it connects to the Ditto back-end.</span> |
| <span class="kd">final</span> <span class="n">DittoClient</span> <span class="n">client</span> <span class="o">=</span> <span class="n">DittoClients</span><span class="o">.</span><span class="na">newInstance</span><span class="o">(</span><span class="n">messagingProvider</span><span class="o">);</span> |
| </code></pre></div></div> |
| |
| <p>There are several problems with the approach.</p> |
| <ol> |
| <li>The calling thread blocks waiting for IO, namely the authentication process |
| and establishment of a websocket.</li> |
| <li>If the client is configured to reconnect, then an incorrect end-ponit configuration |
| makes the factory method block forever.</li> |
| <li>If the client is not configured to reconnect, then the factory method will throw |
| an exception. But it is not possible to give the client reference to the exception |
| handler, since the client creation did not complete. Consequently the exception handler |
| has no simple way to free all resources allocated for the client.</li> |
| </ol> |
| |
| <p>1.3.0 addresses these problems by introducing an asynchronous client creation interface.</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">DittoClients</span> <span class="o">{</span> |
| |
| <span class="kd">public</span> <span class="kd">static</span> <span class="n">DisconnectedDittoClient</span> <span class="nf">newDisconnectedInstance</span><span class="o">(</span><span class="n">MessagingProvider</span> <span class="n">mp</span><span class="o">);</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="kd">interface</span> <span class="nc">DisconnectedDittoClient</span> <span class="o">{</span> |
| |
| <span class="n">CompletionStage</span><span class="o">&lt;</span><span class="n">DittoClient</span><span class="o">&gt;</span> <span class="nf">connect</span><span class="o">();</span> |
| |
| <span class="kt">void</span> <span class="nf">destroy</span><span class="o">();</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>The method <code class="highlighter-rouge">DittoClients.newDisconnectedInstance(MessagingProvider)</code> creates a <code class="highlighter-rouge">DisconnectedDittoClient</code> |
| object. The <code class="highlighter-rouge">DisconnectedDittoClient</code> has references to all resources allocated for the client and |
| can free them via the <code class="highlighter-rouge">destroy()</code> method. The <code class="highlighter-rouge">DisconnectedDittoClient</code> object offers no method to |
| interact with the Ditto API. By calling <code class="highlighter-rouge">connect()</code>, one obtains a future that yields a familiar |
| <code class="highlighter-rouge">DittoClient</code> object upon completion. One might use the asynchronous client creation interface thus:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">final</span> <span class="n">DisconnectedDittoClient</span> <span class="n">disconnectedClient</span> <span class="o">=</span> |
| <span class="n">DittoClients</span><span class="o">.</span><span class="na">newDisconnectedInstance</span><span class="o">(</span><span class="n">messagingProvider</span><span class="o">);</span> |
| |
| <span class="n">disconnectedClient</span><span class="o">.</span><span class="na">connect</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">thenAccept</span><span class="o">(</span><span class="k">this</span><span class="o">::</span><span class="n">startUsingDittoClient</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">exceptionally</span><span class="o">(</span><span class="n">exception</span> <span class="o">-&gt;</span> <span class="o">{</span> |
| <span class="k">this</span><span class="o">.</span><span class="na">handleConnectionFailure</span><span class="o">(</span><span class="n">exception</span><span class="o">);</span> |
| <span class="n">disconnectedClient</span><span class="o">.</span><span class="na">destroy</span><span class="o">();</span> |
| <span class="k">return</span> <span class="kc">null</span><span class="o">;</span> |
| <span class="o">});</span> |
| </code></pre></div></div> |
| |
| <p>The asynchronous client creation interface has the following advantages.</p> |
| |
| <ol> |
| <li> |
| <p>The calling thread does not block.</p> |
| </li> |
| <li> |
| <p>Even if configured to reconnect, the user can receive connection errors via |
| the connection error handler in <code class="highlighter-rouge">MessagingConfiguration</code> and shut down the client |
| at will.</p> |
| </li> |
| <li> |
| <p>When initial reconnection is disabled, the method <code class="highlighter-rouge">DisconnectedDittoClient.connect()</code> |
| returns a failed future on connection error. It is possible to reference the |
| <code class="highlighter-rouge">DittoDisconnectedClient</code> object in the future’s error handler, where the client can |
| be destroyed.</p> |
| </li> |
| </ol> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Thu, 08 Oct 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-10-08-asynchronous-client-creation.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-10-08-asynchronous-client-creation.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Eclipse Ditto Release 1.3.0</title> |
| <description><p>Today, the Ditto team is happy to announce the next feature update of Ditto <code class="highlighter-rouge">1.x</code>: <strong>Eclipse Ditto 1.3.0</strong></p> |
| |
| <p>1.3.0 focuses on the following areas:</p> |
| |
| <ul> |
| <li>Implicit/automatic creation of digital twins (things)</li> |
| <li>Use response of HTTP push connections as live message response</li> |
| <li>“Raw” payload mapper for “pass-through” connectivity scenarios not affecting the twin</li> |
| </ul> |
| |
| <p>Please have a look at the <a href="release_notes_130.html">1.3.0 release notes</a> for a more detailed information on the release.</p> |
| |
| <p>Also, some bugs were fixed which are not backported to Ditto 1.2.x - it is recommended to update to Ditto 1.3.0 right |
| away and skip 1.2.x.</p> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>Also the <a href="client-sdk-java.html">Ditto Java client</a>’s artifacts were published to Maven central.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <h2 id="kubernetes-ready-helm-chart">Kubernetes ready: Helm chart</h2> |
| |
| <p>In order to run Eclipse Ditto in a Kubernetes environment, best rely on the official |
| <a href="https://hub.helm.sh/charts/eclipse-iot/ditto">Helm chart</a> and deploy Ditto via the Helm package manager.</p> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-09-30-release-announcement-130.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-09-30-release-announcement-130.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Eclipse Ditto Release 1.2.0</title> |
| <description><p>Today, the Ditto team is happy to announce the second minor (feature) update of Ditto <code class="highlighter-rouge">1.x</code>:<br /> |
| <strong>Eclipse Ditto 1.2.0</strong></p> |
| |
| <p>1.2.0 focuses on the following areas:</p> |
| |
| <ul> |
| <li>“At least once” (QoS 1) processing of messages consumed/sent via Ditto’s managed <a href="basic-connections.html">connections</a> |
| (via <a href="basic-acknowledgements.html">acknowledgements</a>)</li> |
| <li>Addition of a <code class="highlighter-rouge">"_created"</code> timestamp for newly created digital twins (things)</li> |
| <li>Possibility to inject arbitrary <code class="highlighter-rouge">"_metadata"</code> when modifying digital twins (things)</li> |
| <li>Authenticate HTTP push connections with client certificates</li> |
| </ul> |
| |
| <p>Please have a look at the <a href="release_notes_120.html">1.2.0 release notes</a> for a more detailed information on the release.</p> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>Also the <a href="client-sdk-java.html">Ditto Java client</a>’s artifacts were published to Maven central.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <h2 id="kubernetes-ready-helm-chart">Kubernetes ready: Helm chart</h2> |
| |
| <p>In order to run Eclipse Ditto in a Kubernetes environment, best rely on the official |
| <a href="https://hub.helm.sh/charts/eclipse-iot/ditto">Helm chart</a> and deploy Ditto via the Helm package manager.</p> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Mon, 31 Aug 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-08-31-release-announcement-120.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-08-31-release-announcement-120.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Eclipse Ditto Release 1.1.0</title> |
| <description><p>Today, approximately 4 months after Eclipse Ditto’s <a href="2019-12-12-release-announcement-100.html">1.0.0</a> release, |
| the team is happy to announce the first minor (feature) update of Ditto <code class="highlighter-rouge">1.0</code>:<br /> |
| <strong>Eclipse Ditto 1.1.0</strong></p> |
| |
| <p>The Ditto team was quite busy, 1.1.0 focuses on the following areas:</p> |
| |
| <ul> |
| <li>Management of <a href="basic-policy.html">Policies</a> via <a href="protocol-specification-policies.html">Ditto Protocol</a> |
| <ul> |
| <li>Addition of policy APIs in Ditto <a href="client-sdk-java.html">Java client</a></li> |
| </ul> |
| </li> |
| <li>Possibility to <a href="basic-search.html">search</a> via <a href="protocol-specification-things-search.html">Ditto Protocol</a> |
| <ul> |
| <li>Addition of search APIs in Ditto <a href="client-sdk-java.html">Java client</a></li> |
| </ul> |
| </li> |
| <li>Enrich published Ditto events/message via additional <a href="basic-enrichment.html">custom fields</a> of the affected thing |
| <ul> |
| <li>Addition of enrichment APIs in Ditto <a href="client-sdk-java.html">Java client</a></li> |
| </ul> |
| </li> |
| <li>Support for establishing managed <a href="basic-connections.html">connections</a> via <a href="connectivity-protocol-bindings-mqtt5.html">MQTT 5</a></li> |
| <li>End-2-end <a href="basic-acknowledgements.html">acknowledgements</a> preparing Ditto to enable “at least once” processing |
| <ul> |
| <li>Addition of acknowledgement APIs in Ditto <a href="client-sdk-java.html">Java client</a></li> |
| </ul> |
| </li> |
| <li>Officially documented <a href="installation-operating.html#pre-authentication">pre-authenticated</a> authentication mechanism</li> |
| <li>Use of Java 11 for running Ditto containers</li> |
| <li>Deprecation of API version 1 (authorization via <a href="basic-acl.html">ACL</a> mechanism)</li> |
| <li>Use of CBOR as cluster internal replacement for JSON serialization</li> |
| <li>Further improvements on increasing throughput</li> |
| </ul> |
| |
| <p>Please have a look at the <a href="release_notes_110.html">1.1.0 release notes</a> for a more detailed information on the release.</p> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>Also the <a href="client-sdk-java.html">Ditto Java client</a>’s artifacts were published to Maven central.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <h2 id="kubernetes-ready-helm-chart">Kubernetes ready: Helm chart</h2> |
| |
| <p>In order to run Eclipse Ditto in a Kubernetes environment, best rely on the official |
| <a href="https://hub.helm.sh/charts/eclipse-iot/ditto">Helm chart</a> and deploy Ditto via the Helm package manager.</p> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Wed, 29 Apr 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-04-29-release-announcement-110.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-04-29-release-announcement-110.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Digital twins of devices connected via LoRaWAN to TTN</title> |
| <description><figure><img class="docimage" src="images/2020-04-16-Logo_TTVC_color.png" alt="TTVC logo" style="max-width:300px;padding-left:1em;float:right" /></figure> |
| |
| <p><br /></p> |
| |
| <p>A workshop of the <a href="https://www.thethingsnetwork.org/article/the-things-virtual-conference">2020 The Things Virtual Conference</a> |
| on April 16th 2020 is/was about how to connect Eclipse Ditto to “The Things Network” via TTN’s MQTT broker in order to |
| automatically update digital twins of devices connected via LoRaWAN to the TTN backend.</p> |
| |
| <p>You can find the slides <a href="slides/2020_04_16-ttn-virtual-conference/index.html">here</a>.</p> |
| |
| <p>This blogpost helps setting up this kind of connection and shall also be used as a step-by-step tutorial during |
| the workshop.</p> |
| |
| <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/D33JrN2RWiI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> |
| |
| <h2 id="requirements">Requirements</h2> |
| |
| <p>You’ll need:</p> |
| <ul> |
| <li>an operating system capable of running Docker (best use a Linux distribution)</li> |
| <li>4 CPU cores and 4GB of RAM are advised (less can work, but the Ditto cluster startup is more fragile then)</li> |
| <li>to have installed: <code class="highlighter-rouge">curl</code> and <code class="highlighter-rouge">git</code></li> |
| </ul> |
| |
| <p>Also, you’ll need a TTN account and an existing application with at least one device if you want to follow the hands-on |
| part and want to create digital twins of your devices connected to TTN.</p> |
| |
| <h2 id="preparation">Preparation</h2> |
| |
| <p>Please follow these initial preparation steps (if you don’t already have Docker and Docker Compose installed).</p> |
| |
| <p>When you have access to a Kubernetes cluster and already have worked with <a href="https://helm.sh">Helm</a> (the package manager |
| for Kubernetes), you can alternatively install Ditto via its official |
| <a href="https://hub.helm.sh/charts/eclipse-iot/ditto">Helm chart</a>.</p> |
| |
| <h3 id="install-docker">Install Docker</h3> |
| |
| <p>Assumption: You’re running a Debian or Ubuntu based Linux distribution containing the <code class="highlighter-rouge">apt</code> package manager.</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt install docker.io |
| <span class="nb">sudo </span>service docker start |
| <span class="nb">sudo </span>usermod <span class="nt">-a</span> <span class="nt">-G</span> docker &lt;your-username&gt; |
| </code></pre></div></div> |
| |
| <p>Logout and login again so that your user gets the “docker” group.</p> |
| |
| <h3 id="install-docker-compose">Install Docker Compose</h3> |
| |
| <p><a href="https://docs.docker.com/compose/install/">Follow the installation guide here</a>, in short:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>curl <span class="nt">-L</span> <span class="s2">"https://github.com/docker/compose/releases/download/1.25.4/docker-compose-</span><span class="k">$(</span>uname <span class="nt">-s</span><span class="k">)</span><span class="s2">-</span><span class="k">$(</span>uname <span class="nt">-m</span><span class="k">)</span><span class="s2">"</span> <span class="nt">-o</span> /usr/local/bin/docker-compose |
| <span class="nb">sudo </span>chmod +x /usr/local/bin/docker-compose |
| </code></pre></div></div> |
| |
| <h3 id="clone-ditto-codebase">Clone Ditto codebase</h3> |
| |
| <p>That is required to get the <code class="highlighter-rouge">docker-compose.yaml</code> file and other resources required to run Ditto with Docker Compose.</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone <span class="nt">--depth</span> 1 https://github.com/eclipse/ditto.git |
| </code></pre></div></div> |
| |
| <h2 id="startup-ditto-cluster">Startup Ditto cluster</h2> |
| |
| <p>Change directory into the just cloned git repository - optionally adjust the <code class="highlighter-rouge">DITTO_EXTERNAL_PORT</code> variable to where |
| Ditto is reachable after the start:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>ditto/deployment/docker/ |
| <span class="nb">export </span><span class="nv">DITTO_EXTERNAL_PORT</span><span class="o">=</span>80 |
| docker-compose up <span class="nt">-d</span> |
| </code></pre></div></div> |
| |
| <p>Verify that Ditto is running:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose ps |
| </code></pre></div></div> |
| |
| <p>The output should look similar like this:</p> |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Name Command State Ports |
| ---------------------------------------------------------------------------------------- |
| docker_concierge_1 /sbin/tini -- java -jar st ... Up 8080/tcp |
| docker_connectivity_1 /sbin/tini -- java -jar st ... Up 8080/tcp |
| docker_gateway_1 /sbin/tini -- java -Dditto ... Up 0.0.0.0:8081-&gt;8080/tcp |
| docker_mongodb_1 docker-entrypoint.sh mongo ... Up 27017/tcp |
| docker_nginx_1 nginx -g daemon off; Up 0.0.0.0:80-&gt;80/tcp |
| docker_policies_1 /sbin/tini -- java -jar st ... Up 8080/tcp |
| docker_swagger-ui_1 nginx -g daemon off; Up 80/tcp, 8080/tcp |
| docker_things-search_1 /sbin/tini -- java -jar st ... Up 8080/tcp |
| docker_things_1 /sbin/tini -- java -jar st ... Up 8080/tcp |
| </code></pre></div></div> |
| |
| <p>Verify that your Ditto cluster is healthy. Please give it ~1 minute in order to properly start up.</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-u</span> devops:foobar http://localhost:<span class="k">${</span><span class="nv">DITTO_EXTERNAL_PORT</span><span class="k">}</span>/status/health |
| </code></pre></div></div> |
| |
| <p>The returned output should start with:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="s2">"label"</span><span class="p">:</span><span class="s2">"roles"</span><span class="p">,</span><span class="s2">"status"</span><span class="p">:</span><span class="s2">"UP"</span><span class="p">,</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>If your Ditto cluster has trouble starting up (e.g. because you only have less CPU cores than advised), try the following |
| startup command instead:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose start mongodb<span class="p">;</span> sleep 30<span class="p">;</span> docker-compose start policies things<span class="p">;</span> sleep 60<span class="p">;</span> docker-compose start concierge<span class="p">;</span> sleep 60<span class="p">;</span> docker-compose start things-search<span class="p">;</span> sleep 60<span class="p">;</span> docker-compose start connectivity<span class="p">;</span> sleep 60<span class="p">;</span> docker-compose up <span class="nt">-d</span> |
| </code></pre></div></div> |
| |
| <h2 id="configure-connection-to-ttn-mqtt-broker">Configure connection to TTN MQTT broker</h2> |
| |
| <p>The Things Network provides a built in MQTT broker which you can connect to using your TTN application credentials. |
| For a more detailed description on that topic, please refer to the |
| <a href="https://www.thethingsnetwork.org/docs/applications/mqtt/quick-start.html">TTN MQTT Quick Start</a>.</p> |
| |
| <p>Eclipse Ditto can establish connections to MQTT brokers. This is a schematic picture of what we now will do:</p> |
| |
| <figure><img class="docimage" src="images/../slides/images/ttn-ditto-via-mqtt.png" alt="TTN to Ditto via MQTT" style="max-width:600px;padding-left:1em" /></figure> |
| |
| <p>In order to connect to your own TTN application, perform the following steps.</p> |
| |
| <p>You can find the <code class="highlighter-rouge">&lt;AppId&gt;</code> (application ID) and <code class="highlighter-rouge">&lt;AppKey&gt;</code> (access key) in your TTN console of your application. |
| For <code class="highlighter-rouge">&lt;Region&gt;</code>, e.g. choose <code class="highlighter-rouge">'eu'</code> when your application is in handled by the Handler ‘ttn-handler-eu’.</p> |
| |
| <p>Please export your application’s credentials locally to environment variables:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">TTN_REGION</span><span class="o">=</span><span class="s1">'&lt;Region&gt;'</span> |
| <span class="nb">export </span><span class="nv">TTN_APP_ID</span><span class="o">=</span><span class="s1">'&lt;AppID&gt;'</span> |
| <span class="nb">export </span><span class="nv">TTN_APP_KEY</span><span class="o">=</span><span class="s1">'&lt;AppKey&gt;'</span> |
| </code></pre></div></div> |
| |
| <p>After having done that, you can already create the connection of Ditto to the TTN MQTT broker:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> POST <span class="nt">-u</span> devops:foobar <span class="nt">-H</span> <span class="s1">'Content-Type: application/json'</span> <span class="nt">-d</span> <span class="s1">'{ |
| "targetActorSelection": "/system/sharding/connection", |
| "headers": { |
| "aggregate": false |
| }, |
| "piggybackCommand": { |
| "type": "connectivity.commands:createConnection", |
| "connection": { |
| "id": "ttn-connection-via-mqtt", |
| "name": "TTN-MQTT", |
| "connectionType": "mqtt", |
| "connectionStatus": "open", |
| "uri": "tcp://'</span><span class="s2">"</span><span class="k">${</span><span class="nv">TTN_APP_ID</span><span class="k">}</span><span class="s2">"</span><span class="s1">':'</span><span class="s2">"</span><span class="k">${</span><span class="nv">TTN_APP_KEY</span><span class="k">}</span><span class="s2">"</span><span class="s1">'@'</span><span class="s2">"</span><span class="k">${</span><span class="nv">TTN_REGION</span><span class="k">}</span><span class="s2">"</span><span class="s1">'.thethings.network:1883", |
| "failoverEnabled": true, |
| "clientCount": 1, |
| "validateCertificates": false, |
| "sources": [{ |
| "addresses": [ |
| "'</span><span class="s2">"</span><span class="k">${</span><span class="nv">TTN_APP_ID</span><span class="k">}</span><span class="s2">"</span><span class="s1">'/devices/+/up" |
| ], |
| "consumerCount": 1, |
| "qos": 0, |
| "authorizationContext": [ |
| "pre-authenticated:ttn-connection" |
| ], |
| "enforcement": { |
| "input": "{{ source:address }}", |
| "filters": [ |
| "'</span><span class="s2">"</span><span class="k">${</span><span class="nv">TTN_APP_ID</span><span class="k">}</span><span class="s2">"</span><span class="s1">'/devices/{{ thing:name }}/up" |
| ] |
| }, |
| "replyTarget": { |
| "enabled": false |
| }, |
| "payloadMapping": [ |
| "ttn-demo-mapping" |
| ] |
| }], |
| "mappingDefinitions": { |
| "ttn-demo-mapping": { |
| "mappingEngine": "JavaScript", |
| "options": { |
| "incomingScript": "function mapToDittoProtocolMsg(\n headers,\n textPayload,\n bytePayload,\n contentType\n) {\n\n let ttnJson = JSON.parse(textPayload);\n let deviceId = ttnJson['</span><span class="s2">"'"</span><span class="s1">'dev_id'</span><span class="s2">"'"</span><span class="s1">'];\n let payloadFields = ttnJson['</span><span class="s2">"'"</span><span class="s1">'payload_fields'</span><span class="s2">"'"</span><span class="s1">'];\n \n let attributesObj = {\n hardwareSerial: ttnJson['</span><span class="s2">"'"</span><span class="s1">'hardware_serial'</span><span class="s2">"'"</span><span class="s1">'],\n ttnCounter: ttnJson['</span><span class="s2">"'"</span><span class="s1">'counter'</span><span class="s2">"'"</span><span class="s1">']\n };\n \n let featuresObj = {\n temperature: {\n properties: {\n value: payloadFields['</span><span class="s2">"'"</span><span class="s1">'temperature_7'</span><span class="s2">"'"</span><span class="s1">']\n }\n },\n pressure: {\n properties: {\n value: payloadFields['</span><span class="s2">"'"</span><span class="s1">'barometric_pressure_10'</span><span class="s2">"'"</span><span class="s1">']\n }\n },\n humidity: {\n properties: {\n value: payloadFields['</span><span class="s2">"'"</span><span class="s1">'relative_humidity_8'</span><span class="s2">"'"</span><span class="s1">']\n }\n }\n };\n \n let thing = {\n attributes: attributesObj,\n features: featuresObj\n };\n \n let dittoHeaders = {\n '</span><span class="s2">"'"</span><span class="s1">'response-required'</span><span class="s2">"'"</span><span class="s1">': false,\n '</span><span class="s2">"'"</span><span class="s1">'If-Match'</span><span class="s2">"'"</span><span class="s1">': '</span><span class="s2">"'"</span><span class="s1">'*'</span><span class="s2">"'"</span><span class="s1">'\n };\n\n return Ditto.buildDittoProtocolMsg(\n '</span><span class="s2">"'"</span><span class="s1">'org.eclipse.ditto.ttn.demo'</span><span class="s2">"'"</span><span class="s1">',\n deviceId,\n '</span><span class="s2">"'"</span><span class="s1">'things'</span><span class="s2">"'"</span><span class="s1">',\n '</span><span class="s2">"'"</span><span class="s1">'twin'</span><span class="s2">"'"</span><span class="s1">',\n '</span><span class="s2">"'"</span><span class="s1">'commands'</span><span class="s2">"'"</span><span class="s1">',\n '</span><span class="s2">"'"</span><span class="s1">'modify'</span><span class="s2">"'"</span><span class="s1">',\n '</span><span class="s2">"'"</span><span class="s1">'/'</span><span class="s2">"'"</span><span class="s1">',\n dittoHeaders,\n thing\n );\n}", |
| "outgoingScript": "function mapFromDittoProtocolMsg() { return null; }", |
| "loadBytebufferJS": "false", |
| "loadLongJS": "false" |
| } |
| } |
| } |
| } |
| } |
| }'</span> http://localhost:<span class="k">${</span><span class="nv">DITTO_EXTERNAL_PORT</span><span class="k">}</span>/devops/piggyback/connectivity?timeout<span class="o">=</span>8s |
| </code></pre></div></div> |
| |
| <p>Explanation - what is done here:</p> |
| <ul> |
| <li>using curl with the <code class="highlighter-rouge">devops</code> (admin) user and its initial password <code class="highlighter-rouge">foobar</code> we create a connection of type <code class="highlighter-rouge">mqtt</code> |
| (you can find further information on that in Ditto’s <a href="connectivity-protocol-bindings-mqtt.html">MQTT docs</a>)</li> |
| <li>we use the TTN application credentials in the configured <code class="highlighter-rouge">"uri"</code>, connect via plain TCP |
| (SSL is also possible but in this case a little more complicated as the server certificate of the TTN MQTT broker |
| would have to be imported)</li> |
| <li>we add an entry in <code class="highlighter-rouge">"sources"</code>: |
| <ul> |
| <li>defining the MQTT topic (<code class="highlighter-rouge">"addresses"</code>) to subscribe to</li> |
| <li>specifying in which <code class="highlighter-rouge">"authorizationContext"</code> messages from this connection shall be executed</li> |
| <li>defining in the <code class="highlighter-rouge">"enforcement"</code> that, based on the MQTT topic, a device may only update the Ditto twin having the same name</li> |
| <li>declaring that a custom payload mapping shall be applied for each incoming message</li> |
| </ul> |
| </li> |
| <li>in the <code class="highlighter-rouge">"mappingDefinitions"</code> we define the previously used “ttn-demo-mapping” as JavaScript based mapping: |
| <ul> |
| <li>only an “incoming” script is defined as we don’t handle downstream messages to TTN in this example</li> |
| <li>when you want to understand the script in more depth, please take a look at the <a href="#javascript-payload-mapping-script-in-detail">details about it</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <div class="alert alert-success" role="alert"><i class="fa fa-check-square-o"></i> <b>Tip:</b> As you have other custom <code class="highlighter-rouge">payload_fields</code> for your TTN devices, please adjust the script |
| if you want to see the device’s custom payload fields in your Ditto twins.</div> |
| |
| <h2 id="create-a-common-policy-for-the-twins-to-be-created">Create a common policy for the twins to be created</h2> |
| |
| <p>Eclipse Ditto secures each API access to the managed twins by applying authorization of the authenticated user.<br /> |
| Those “rules” which authenticated user may access which twins are defined in <a href="basic-policy.html">Policies</a>.</p> |
| |
| <p>In order to proceed with our scenario, we create a single Policy which shall be used for all twins we create in a later |
| step:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-X</span> PUT <span class="nt">-u</span> ditto:ditto <span class="nt">-H</span> <span class="s1">'Content-Type: application/json'</span> <span class="nt">-d</span> <span class="s1">'{ |
| "policyId": "org.eclipse.ditto.ttn.demo:twin-policy", |
| "entries": { |
| "USER": { |
| "subjects": { |
| "nginx:ditto": { |
| "type": "basic auth user authenticated via nginx" |
| } |
| }, |
| "resources": { |
| "thing:/": { |
| "grant": ["READ", "WRITE"], |
| "revoke": [] |
| }, |
| "policy:/": { |
| "grant": ["READ", "WRITE"], |
| "revoke": [] |
| }, |
| "message:/": { |
| "grant": ["READ", "WRITE"], |
| "revoke": [] |
| } |
| } |
| }, |
| "TTN": { |
| "subjects": { |
| "pre-authenticated:ttn-connection": { |
| "type": "used in the connections authorizationContext to the TTN MQTT" |
| } |
| }, |
| "resources": { |
| "thing:/": { |
| "grant": ["WRITE"], |
| "revoke": [] |
| } |
| } |
| } |
| } |
| }'</span> http://localhost:<span class="k">${</span><span class="nv">DITTO_EXTERNAL_PORT</span><span class="k">}</span>/api/2/policies/org.eclipse.ditto.ttn.demo:twin-policy |
| </code></pre></div></div> |
| |
| <p>Explanation - what is done here:</p> |
| <ul> |
| <li>we create a new Policy with the ID <code class="highlighter-rouge">"org.eclipse.ditto.ttn.demo:twin-policy"</code></li> |
| <li>it contains 2 entries: |
| <ul> |
| <li><code class="highlighter-rouge">"USER"</code>: this Policy entry contains the authorization information of the user of the twin APIs (authenticated via the contained “nginx” acting as reverse proxy). |
| This user may READ+WRITE the things (twins), this created policy and may also send and receive messages.</li> |
| <li><code class="highlighter-rouge">"TTN"</code>: this Policy entry contains the authorization information of the connection to the TTN MQTT broker (the subject was configured as <code class="highlighter-rouge">"authorizationContext"</code> when we created the connection. |
| This connection may only WRITE (update) the things (twins).</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h2 id="create-digital-twins">Create digital twins</h2> |
| |
| <p>Now we have everything in place in order to create digital twins for our devices connected to TTN.</p> |
| |
| <p>Please export all device ids you want to create digital twins for as comma separated environment variable:</p> |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">TTN_DEVICE_IDS</span><span class="o">=</span><span class="s1">'&lt;comma-separated-list-of-your-device-ids&gt;'</span> |
| </code></pre></div></div> |
| |
| <p>After having done that, we can already create the twins in Ditto as the <code class="highlighter-rouge">ditto</code> user:</p> |
| |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>dev_id <span class="k">in</span> <span class="k">${</span><span class="nv">TTN_DEVICE_IDS</span><span class="p">//,/ </span><span class="k">}</span> |
| <span class="k">do</span> |
| <span class="c"># call your procedure/other scripts here below</span> |
| <span class="nb">echo</span> <span class="s2">"Creating digital twin with Thing ID: org.eclipse.ditto.ttn.demo:</span><span class="nv">$dev_id</span><span class="s2">"</span> |
| curl <span class="nt">-X</span> PUT <span class="nt">-u</span> ditto:ditto <span class="nt">-H</span> <span class="s1">'Content-Type: application/json'</span> <span class="nt">-d</span> <span class="s1">'{ |
| "policyId": "org.eclipse.ditto.ttn.demo:twin-policy" |
| }'</span> http://localhost:<span class="k">${</span><span class="nv">DITTO_EXTERNAL_PORT</span><span class="k">}</span>/api/2/things/org.eclipse.ditto.ttn.demo:<span class="nv">$dev_id</span> |
| <span class="k">done</span> |
| </code></pre></div></div> |
| |
| <p>Explanation - what is done here:</p> |
| <ul> |
| <li>we split the passed in <code class="highlighter-rouge">TTN_DEVICE_IDS</code> environment variable by <code class="highlighter-rouge">,</code> and iterate over all contained device ids</li> |
| <li>for each device ID we create a new Thing (twin) referencing the already previously created Policy</li> |
| </ul> |
| |
| <h2 id="access-your-digital-twins-via-api">Access your digital twins via API</h2> |
| |
| <p>Congratulations, if you have done it so far your TTN devices do now have digital twin representations in Eclipse Ditto.</p> |
| |
| <div class="alert alert-success" role="alert"><i class="fa fa-check-square-o"></i> <b>Tip:</b> Install the command line tool <code class="highlighter-rouge">jq</code> and pipe the output of the below <code class="highlighter-rouge">curl</code> commands to it in order to get |
| prettified and colored JSON</div> |
| |
| <div class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note:</b> Alternatively to <code class="highlighter-rouge">curl</code>, you may also use the locally deployed swagger-ui at http://localhost:${DITTO_EXTERNAL_PORT}/apidoc/ |
| in order to try out Ditto’s HTTP API - <em>make sure to select</em> <code class="highlighter-rouge">/api/2 - local Ditto</code> in the ‘Servers’ |
| section - when asked for credentials, use username ‘ditto’ and password ‘ditto’</div> |
| |
| <p>You can now, for example, use Ditto’s HTTP APIs in order</p> |
| <ul> |
| <li>to retrieve the latest reported values: <code class="highlighter-rouge">curl -u ditto:ditto http://localhost:${DITTO_EXTERNAL_PORT}/api/2/things/org.eclipse.ditto.ttn.demo:&lt;dev_id&gt;</code></li> |
| <li>to get a live stream of updates to the twins using SSE (Server Sent Events): <code class="highlighter-rouge">curl --http2 -u ditto:ditto -H 'Accept:text/event-stream' -N http://localhost:${DITTO_EXTERNAL_PORT}/api/2/things</code></li> |
| <li>to list all available twins via the search API: <code class="highlighter-rouge">curl -u ditto:ditto http://localhost:${DITTO_EXTERNAL_PORT}/api/2/search/things</code> |
| <ul> |
| <li>alternatively, use your browser and open http://localhost:${DITTO_EXTERNAL_PORT}/api/2/search/things</li> |
| <li>when asked for credentials, use username “ditto” and password “ditto”</li> |
| </ul> |
| </li> |
| <li>formulate a search query, e.g. only searching for twins with a temperature above 24°, sorted by the last modification, the most recent first |
| to get the most active twin as first result: |
| <ul> |
| <li><code class="highlighter-rouge">curl -u ditto:ditto "http://localhost:${DITTO_EXTERNAL_PORT}/api/2/search/things?filter=gt(features/temperature/properties/value,24.0)&amp;option=sort(-_modified),size(5)&amp;fields=thingId,policyId,attributes,features,_modified,_revision"</code></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h2 id="which-other-possibilities-do-we-now-have">Which other possibilities do we now have?</h2> |
| |
| <p>Now you have all the possibilities Eclipse Ditto as digital twin framework provides, e.g.:</p> |
| <ul> |
| <li>directly use your device’s data in a web application consuming Ditto’s HTTP API</li> |
| <li>directly use your device’s data in a mobile app using Ditto’s bidirectional <a href="httpapi-protocol-bindings-websocket.html">WebSocket</a></li> |
| <li>make use of the <a href="https://github.com/eclpise/ditto-clients/">Eclipse Ditto Java or JavaScript clients</a> which also use the WebSocket to integrate your device’s data</li> |
| <li>create another connection (optionally also applying JavaScript based payload mapping) |
| <ul> |
| <li>to e.g. <a href="connectivity-protocol-bindings-kafka2.html">Apache Kafka</a> and forward all the modifications made to your devices to there</li> |
| <li>or using <a href="connectivity-protocol-bindings-http.html">HTTP push</a> in order to call another HTTP API (e.g. insert time series data into an InfluxDB via its HTTP API)</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p><br /> |
| <br /></p> |
| |
| <p>For time reasons we do not go deeper into additional topics, they are possible however, please consult the Ditto |
| documentation:</p> |
| <ul> |
| <li>the WebSocket channel and subscribing for change notifications</li> |
| <li>sending downward messages to devices</li> |
| <li>live commands (not retrieving persisted data of devices, but live data)</li> |
| <li>a more detailed introduction into authentication mechanisms (<a href="installation-operating.html#openid-connect">OpenID Connect with OAuth2.0 is possible</a>)</li> |
| <li>possibilities to configure your Policies on every resource level, e.g. allowing individuals to only access certain values of a twin</li> |
| <li>and many other things..</li> |
| </ul> |
| |
| <h2 id="additional-resources">Additional resources</h2> |
| |
| <h3 id="cleanup-after-the-workshop">Cleanup after the workshop</h3> |
| |
| <p>Simply perform in the <code class="highlighter-rouge">ditto/deployment/docker</code> folder:</p> |
| <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-compose down |
| </code></pre></div></div> |
| |
| <p>And unistall docker + docker-compose (for docker-compose, just remove the downloaded file) again, if you don’t need it.</p> |
| |
| <h3 id="javascript-payload-mapping-script-in-detail">JavaScript payload mapping script in detail</h3> |
| |
| <p>Similar to the TTN console’s decoding/converting capabilities of “Payload Formats” of an TTN application, Ditto is able |
| to apply a custom JavaScript function for each consumed message.<br /> |
| That is necessary in order to convert the received data into a <a href="protocol-overview.html">Ditto Protocol</a> message |
| including the JSON hierarchy of a so called <a href="basic-thing.html">Thing</a> being the representation of a digital twin.</p> |
| |
| <p>As the above injected JavaScript payload mapping script is formatted in a single line, this is the script we used pretty |
| formatted, including the jsdoc of the provided function and some other inline comments.</p> |
| |
| <p>If you need to adjust the script in order to use your own <code class="highlighter-rouge">payload_fields</code>, please replace all newlines with <code class="highlighter-rouge">\n</code> and |
| escape the single quotes <code class="highlighter-rouge">'</code> in the script with the following replacement: <code class="highlighter-rouge">'"'"'</code>. Otherwise the single quotes won’t get |
| correctly escaped in the bash. You can remove the comments before making a single line of the script.</p> |
| |
| <div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** |
| * Maps the passed parameters to a Ditto Protocol message. |
| * @param {Object.&lt;string, string&gt;} headers - The headers Object containing all received header values |
| * @param {string} [textPayload] - The String to be mapped |
| * @param {ArrayBuffer} [bytePayload] - The bytes to be mapped as ArrayBuffer |
| * @param {string} [contentType] - The received Content-Type, e.g. "application/json" |
| * @returns {(DittoProtocolMessage|Array&lt;DittoProtocolMessage&gt;)} dittoProtocolMessage(s) - |
| * The mapped Ditto Protocol message, |
| * an array of Ditto Protocol messages or |
| * &lt;code&gt;null&lt;/code&gt; if the message could/should not be mapped |
| */</span> |
| <span class="kd">function</span> <span class="nx">mapToDittoProtocolMsg</span><span class="p">(</span> |
| <span class="nx">headers</span><span class="p">,</span> |
| <span class="nx">textPayload</span><span class="p">,</span> |
| <span class="nx">bytePayload</span><span class="p">,</span> |
| <span class="nx">contentType</span> |
| <span class="p">)</span> <span class="p">{</span> |
| |
| <span class="kd">let</span> <span class="nx">ttnJson</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">textPayload</span><span class="p">);</span> <span class="c1">// we simply parse the incoming TTN message as JSON</span> |
| <span class="kd">let</span> <span class="nx">deviceId</span> <span class="o">=</span> <span class="nx">ttnJson</span><span class="p">[</span><span class="s1">'dev_id'</span><span class="p">];</span> <span class="c1">// and extract some fields we require</span> |
| <span class="kd">let</span> <span class="nx">payloadFields</span> <span class="o">=</span> <span class="nx">ttnJson</span><span class="p">[</span><span class="s1">'payload_fields'</span><span class="p">];</span> <span class="c1">// the 'payload_fields' content is - obviously - different for your application</span> |
| |
| <span class="kd">let</span> <span class="nx">attributesObj</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">// the attributes of a Thing are meant for unstructured data </span> |
| <span class="na">hardwareSerial</span><span class="p">:</span> <span class="nx">ttnJson</span><span class="p">[</span><span class="s1">'hardware_serial'</span><span class="p">],</span> |
| <span class="na">ttnCounter</span><span class="p">:</span> <span class="nx">ttnJson</span><span class="p">[</span><span class="s1">'counter'</span><span class="p">]</span> |
| <span class="p">};</span> |
| |
| <span class="kd">let</span> <span class="nx">featuresObj</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">// the features of a Thing e.g. contain sensor data of devices</span> |
| <span class="na">temperature</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">properties</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">value</span><span class="p">:</span> <span class="nx">payloadFields</span><span class="p">[</span><span class="s1">'temperature_7'</span><span class="p">]</span> |
| <span class="p">}</span> |
| <span class="p">},</span> |
| <span class="na">pressure</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">properties</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">value</span><span class="p">:</span> <span class="nx">payloadFields</span><span class="p">[</span><span class="s1">'barometric_pressure_10'</span><span class="p">]</span> |
| <span class="p">}</span> |
| <span class="p">},</span> |
| <span class="na">humidity</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">properties</span><span class="p">:</span> <span class="p">{</span> |
| <span class="na">value</span><span class="p">:</span> <span class="nx">payloadFields</span><span class="p">[</span><span class="s1">'relative_humidity_8'</span><span class="p">]</span> |
| <span class="p">}</span> |
| <span class="p">}</span> |
| <span class="p">};</span> |
| |
| <span class="kd">let</span> <span class="nx">thing</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">// a Thing can contain both attributes and features</span> |
| <span class="na">attributes</span><span class="p">:</span> <span class="nx">attributesObj</span><span class="p">,</span> |
| <span class="na">features</span><span class="p">:</span> <span class="nx">featuresObj</span> |
| <span class="p">};</span> |
| |
| <span class="kd">let</span> <span class="nx">dittoHeaders</span> <span class="o">=</span> <span class="p">{</span> |
| <span class="s1">'response-required'</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="c1">// we don't expect a response sent back to TTN</span> |
| <span class="s1">'If-Match'</span><span class="p">:</span> <span class="s1">'*'</span> <span class="c1">// we only want to update the thing if it already exists</span> |
| <span class="p">};</span> |
| |
| <span class="k">return</span> <span class="nx">Ditto</span><span class="p">.</span><span class="nx">buildDittoProtocolMsg</span><span class="p">(</span> |
| <span class="s1">'org.eclipse.ditto.ttn.demo'</span><span class="p">,</span> <span class="c1">// this is the namespace used as prefix for Ditto Thing IDs</span> |
| <span class="nx">deviceId</span><span class="p">,</span> <span class="c1">// the TTN device ID is used as "name" part of the Ditto Thing ID </span> |
| <span class="s1">'things'</span><span class="p">,</span> |
| <span class="s1">'twin'</span><span class="p">,</span> |
| <span class="s1">'commands'</span><span class="p">,</span> |
| <span class="s1">'modify'</span><span class="p">,</span> |
| <span class="s1">'/'</span><span class="p">,</span> |
| <span class="nx">dittoHeaders</span><span class="p">,</span> |
| <span class="nx">thing</span> |
| <span class="p">);</span> |
| <span class="p">}</span> |
| </code></pre></div></div> |
| |
| <p>An example message received from the TTN MQTT broker:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"app_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"iot-campus-be12"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"dev_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"node0"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"hardware_serial"</span><span class="p">:</span><span class="w"> </span><span class="s2">"70B3D5499A2D3954"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"port"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"counter"</span><span class="p">:</span><span class="w"> </span><span class="mi">9449</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"payload_raw"</span><span class="p">:</span><span class="w"> </span><span class="s2">"B2cA6AhoKwpzJ8oEAwH4"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"payload_fields"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"analog_out_4"</span><span class="p">:</span><span class="w"> </span><span class="mf">5.04</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"barometric_pressure_10"</span><span class="p">:</span><span class="w"> </span><span class="mf">1018.6</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"relative_humidity_8"</span><span class="p">:</span><span class="w"> </span><span class="mf">21.5</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"temperature_7"</span><span class="p">:</span><span class="w"> </span><span class="mf">23.2</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="err">...</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>would be transformed to the following Ditto Protocol message:</p> |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto/node0/things/twin/commands/modify"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"attributes"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"hardwareSerial"</span><span class="p">:</span><span class="w"> </span><span class="s2">"70B3D5499A2D3954"</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"ttnCounter"</span><span class="p">:</span><span class="w"> </span><span class="mi">9449</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"features"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"temperature"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="mf">23.2</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"pressure"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="mf">1018.6</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">},</span><span class="w"> |
| </span><span class="s2">"humidity"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> |
| </span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="mf">21.5</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Thu, 16 Apr 2020 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2020-04-16-connecting-to-ttn-via-mqtt.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2020-04-16-connecting-to-ttn-via-mqtt.html</guid> |
| |
| <category>blog</category> |
| |
| <category>connectivity</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Eclipse Ditto Release 1.0.0</title> |
| <description><p>Today the Eclipse Ditto is thrilled to announce the availability of Eclipse Ditto’s first major release |
| <a href="https://projects.eclipse.org/projects/iot.ditto/releases/1.0.0">1.0.0</a>.</p> |
| |
| <h2 id="maturity">Maturity</h2> |
| |
| <p>The initial code contribution was done in October 2017, 2 years later and 2 releases |
| (<a href="2018-11-28-release-announcement-080.html">0.8.0</a> and <a href="2019-07-10-release-announcement-090.html">0.9.0</a>) later, we |
| think its time to graduate from the Eclipse “incubation” phase and officially declare the project as mature.</p> |
| |
| <p>Recent adoptions and contributions from our community show us that Eclipse Ditto solves problems which also other |
| companies have. Adopters add Eclipse Ditto as a central part of their own IoT platforms.</p> |
| |
| <h3 id="api-stability">API stability</h3> |
| |
| <p>Having reached 1.0.0, some additional promises towards “API stability” do apply:</p> |
| |
| <h4 id="http-api-stability">HTTP API stability</h4> |
| <p>Ditto uses schema versioning (currently schema version 1 and 2) at the HTTP API level in order to being able to |
| evolve APIs. |
| It is backward compatible to the prior versions 0.8.0 and 0.9.0.</p> |
| |
| <h4 id="json-api-stability">JSON API stability</h4> |
| <p>Ditto kept its main JSON APIs (regarding things, policies and search) backwards compatible to 0.8.0 and 0.9.0 releases. |
| The JSON format of “connections” was changed since 0.9.0 and will from 1.0.0 on be kept backwards compatible as well.</p> |
| |
| <h4 id="java-api-stability">Java API stability</h4> |
| <p>The Java APIs will for the 1.x release be kept backwards compatible, so only non-breaking additions to the APIs will be done. This is enforced by a Maven tooling.</p> |
| |
| <p>The following Java modules are treated as API for which compatibility is enforced:</p> |
| |
| <ul> |
| <li>ditto-json</li> |
| <li>ditto-model-*</li> |
| <li>ditto-signals-*</li> |
| <li>ditto-protocol-adapter</li> |
| <li>ditto-utils</li> |
| <li>ditto-client</li> |
| </ul> |
| |
| <h3 id="scalability">Scalability</h3> |
| |
| <p>The focus on the 0.9.0 and 1.0.0 releases regarding non-functionals were laid on horizontal scalability.</p> |
| |
| <p>With Eclipse Ditto 1.0.0 we are confident to face production grade scalability requirements being capable of handling |
| millions of managed things.</p> |
| |
| <h2 id="changelog">Changelog</h2> |
| |
| <p>The main changes compared to the last release, <a href="release_notes_090.html">0.9.0</a>, are:</p> |
| |
| <ul> |
| <li>addition of a Java and a JavaScript client SDK in separate <a href="https://github.com/eclipse/ditto-clients">GitHub repo</a></li> |
| <li>configurable OpenID Connect authorization servers</li> |
| <li>support for OpenID Connect / OAuth2.0 based authentication in Ditto Java Client</li> |
| <li>invoking custom foreign HTTP endpoints as a result of events/messages</li> |
| <li>ability to reflect Eclipse Hono’s device connection state in Ditto’s things</li> |
| <li>configurable throttling of max. consumed WebSocket commands / time interval</li> |
| <li>Addition of “definition” field in thing at model level containing the model ID a thing may follow</li> |
| <li>Improved connection response handling/mapping</li> |
| </ul> |
| |
| <p>Please have a look at the <a href="release_notes_100.html">1.0.0 release notes</a> for a more detailed information on the release.</p> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Thu, 12 Dec 2019 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2019-12-12-release-announcement-100.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2019-12-12-release-announcement-100.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Ditto Milestone 1.0.0-M2</title> |
| <description><p>The second and last milestone of the upcoming release |
| <a href="https://projects.eclipse.org/projects/iot.ditto/releases/1.0.0">1.0.0</a> was released today.</p> |
| |
| <p>Have a look at the Milestone <a href="release_notes_100-M2.html">1.0.0-M2 release notes</a> for what changed in detail.</p> |
| |
| <p>The main changes and new features since the last release <a href="release_notes_100-M1a.html">1.0.0-M1a release notes</a> are</p> |
| |
| <ul> |
| <li>invoking custom foreign HTTP endpoints as a result of events/messages</li> |
| <li>ability to reflect Eclipse Hono’s device connection state in Ditto’s things</li> |
| <li>support for OpenID Connect / OAuth2.0 based authentication in Ditto Java Client</li> |
| <li>configurbale throttling of max. consumed WebSocket commands / time interval</li> |
| </ul> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Mon, 04 Nov 2019 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2019-11-04-milestone-announcement-100-M2.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2019-11-04-milestone-announcement-100-M2.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Integration of HTTP endpoints/webhooks</title> |
| <description><p>By adding another connectivity type - <a href="connectivity-protocol-bindings-http.html">HTTP</a> - to Ditto’s |
| connectivity, it is now (to be released in the next Ditto milestone 1.0.0-M2) possible to |
| publish <em>twin events</em>, <em>messages</em>, <em>live commands and events</em> to existing HTTP servers/endpoints.</p> |
| |
| <p>That is especially useful for invoking existing APIs (which are most of the time HTTP based) whenever e.g. |
| a digital twin was modified.</p> |
| |
| <p>One example on how to benefit from this new feature is to invoke a custom |
| <a href="https://ifttt.com">IFTTT</a> (if-this-than-that) <a href="https://ifttt.com/maker_webhooks">webhook</a> via a HTTP <code class="highlighter-rouge">POST</code> request |
| which then may trigger other IFTTT follow-up-actions (e.g. send a chat message to a <a href="https://ifttt.com/slack">Slack</a> |
| room).</p> |
| |
| <p>For IFTTT “webhooks” the address would be <code class="highlighter-rouge">POST https://maker.ifttt.com/trigger/&lt;your-event-name&gt;/with/key/&lt;your-key&gt;</code> |
| and the expected JSON body:</p> |
| |
| <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> |
| </span><span class="s2">"value1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"..."</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"..."</span><span class="p">,</span><span class="w"> |
| </span><span class="s2">"value3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"..."</span><span class="w"> |
| </span><span class="p">}</span><span class="w"> |
| </span></code></pre></div></div> |
| |
| <p>In combination with <a href="connectivity-mapping.html">payload mapping</a>, the <code class="highlighter-rouge">value1</code> to <code class="highlighter-rouge">value3</code> fields requested by the IFTTT |
| API can be extracted from the <a href="protocol-specification.html">Ditto Protocol</a> and could contain the changed value.</p> |
| |
| <p>In combination with <a href="basic-connections.html#target-topics-and-filtering">filters for targets</a> you can even specify to |
| only publish e.g. <code class="highlighter-rouge">twin events</code>, where the temperature of a twin exceeded a certain threshold:</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{ |
| "address": "POST:/trigger/&lt;your-event-name&gt;/with/key/&lt;your-key&gt;", |
| "topics": [ |
| "_/_/things/twin/events?filter=gt(features/temperature/properties/value,25)" |
| ], |
| ... |
| } |
| </code></pre></div></div> |
| |
| <p>Get creative on which HTTP APIs to trigger based on twin events. E.g. invoke a “function-as-a-service” API or invoke the |
| Twitter API and let your digital twin tweet whenever it detects, that it is getting too warm in your office.</p> |
| |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2019-10-17-http-connectivity.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2019-10-17-http-connectivity.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| <item> |
| <title>Announcing Ditto Milestone 1.0.0-M1a</title> |
| <description><p>Today the Ditto team is happy to announce the first milestone of the upcoming release |
| <a href="https://projects.eclipse.org/projects/iot.ditto/releases/1.0.0">1.0.0</a>.</p> |
| |
| <p>Have a look at the Milestone <a href="release_notes_100-M1a.html">1.0.0-M1a release notes</a> for what changed in detail.</p> |
| |
| <p>The main changes and new features since the last release <a href="release_notes_090.html">0.9.0</a> are</p> |
| |
| <ul> |
| <li>initial contribution of Java client SDK</li> |
| <li>configurable OpenID Connect authorization servers</li> |
| <li>fine grained access for connections</li> |
| <li>scalable event publishing</li> |
| <li>typed entity IDs</li> |
| </ul> |
| |
| <h2 id="artifacts">Artifacts</h2> |
| |
| <p>The new Java artifacts have been published at the <a href="https://repo.eclipse.org/content/repositories/ditto/">Eclipse Maven repository</a> |
| as well as <a href="https://repo1.maven.org/maven2/org/eclipse/ditto/">Maven central</a>.</p> |
| |
| <p>The Docker images have been pushed to Docker Hub:</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-policies/">eclipse/ditto-policies</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things/">eclipse/ditto-things</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-things-search/">eclipse/ditto-things-search</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-gateway/">eclipse/ditto-gateway</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-connectivity/">eclipse/ditto-connectivity</a></li> |
| <li><a href="https://hub.docker.com/r/eclipse/ditto-concierge/">eclipse/ditto-concierge</a></li> |
| </ul> |
| |
| <p><br /> |
| <br /></p> |
| <figure><img class="docimage" src="images/ditto.svg" alt="Ditto" style="max-width: 500px" /></figure> |
| |
| <p>–<br /> |
| The Eclipse Ditto team</p> |
| </description> |
| <pubDate>Tue, 17 Sep 2019 00:00:00 +0000</pubDate> |
| <link>https://www.eclipse.org/ditto/2019-09-17-milestone-announcement-100-M1a.html</link> |
| <guid isPermaLink="true">https://www.eclipse.org/ditto/2019-09-17-milestone-announcement-100-M1a.html</guid> |
| |
| <category>blog</category> |
| |
| |
| </item> |
| |
| </channel> |
| </rss> |