blob: b3d01fe02b96c706f462816c2bc8a0e19c56ad58 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keywords" content="connectivity, mapping, transformation, payload, javascript">
<title> Payload mapping in connectivity service • Eclipse Ditto • a digital twin framework</title>
<link rel="stylesheet" href="css/syntax.css">
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="css/modern-business.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="css/customstyles.css">
<link rel="stylesheet" href="css/boxshadowproperties.css">
<link rel="stylesheet" href="css/theme-ditto.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js" crossorigin="anonymous"></script>
<script src="js/toc.js"></script>
<script src="js/customscripts.js"></script>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "https://eclipse.org/ditto/",
"logo": "https://eclipse.org/ditto/images/ditto.svg"
}
</script>
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="images/favicon-96x96.png" sizes="96x96">
<link rel="alternate" type="application/rss+xml" title="Eclipse Ditto Blog" href="https://www.eclipse.org/ditto/feed.xml">
<!-- Eclipse Foundation cookie consent: -->
<link rel="stylesheet" type="text/css" href="//www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/vendor/cookieconsent/cookieconsent.min.css" />
<script src="//www.eclipse.org/eclipse.org-common/themes/solstice/public/javascript/vendor/cookieconsent/default.min.js"></script>
<script>
$(document).ready(function() {
$("#tg-sb-link").click(function() {
$("#tg-sb-sidebar").toggle();
$("#tg-sb-content").toggleClass('col-md-9');
$("#tg-sb-content").toggleClass('col-md-12');
$("#tg-sb-icon").toggleClass('fa-toggle-on');
$("#tg-sb-icon").toggleClass('fa-toggle-off');
});
});
</script>
</head>
<script>
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),
dl=l!='dataLayer'?'&l='+l:'';
j.async=true;
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5WLCZXC');
</script>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container topnavlinks">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-ditto-home" href="index.html">&nbsp;<img src="images/ditto_allwhite_symbolonly.svg" class="ditto-navbar-symbol" alt="Home"> <img src="images/ditto_allwhite_textonly.svg" class="ditto-navbar-symbol-text" alt="Ditto"></a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<!-- toggle sidebar button -->
<!--<li><a id="tg-sb-link" href="#"><i id="tg-sb-icon" class="fa fa-toggle-on"></i> Nav</a></li>-->
<!-- entries without drop-downs appear here -->
<li><a href="blog.html">Blog</a></li>
<li><a href="intro-overview.html">Documentation</a></li>
<li><a href="http-api-doc.html">HTTP API</a></li>
<li><a href="sandbox.html">Sandbox</a></li>
<li><a href="https://github.com/eclipse/ditto" target="_blank">GitHub</a></li>
<li><a href="https://github.com/eclipse/ditto-examples" target="_blank">GitHub examples</a></li>
<!-- entries with drop-downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Links<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="https://projects.eclipse.org/projects/iot.ditto" target="_blank">Eclipse Ditto Project</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/364/" target="_blank">Forum</a></li>
<li><a href="https://ci.eclipse.org/ditto/" target="_blank">Jenkins</a></li>
<li><a href="https://dev.eclipse.org/mhonarc/lists/ditto-dev/" target="_blank">Mailing list archives</a></li>
<li><a href="https://gitter.im/eclipse/ditto" target="_blank">Gitter.im chat</a></li>
</ul>
</li>
<!--comment out this block if you want to hide search-->
<li>
<!--start search-->
<div id="search-demo-container">
<input type="text" id="search-input" placeholder="search...">
<ul id="results-container"></ul>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/simple-jekyll-search/0.0.9/jekyll-search.js" type="text/javascript"></script>
<script type="text/javascript">
SimpleJekyllSearch.init({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
dataSource: 'search.json',
searchResultTemplate: '<li><a href="{url}" title="Payload mapping in connectivity service">{title}</a></li>',
noResultsText: 'No results found.',
limit: 10,
fuzzy: true,
})
</script>
<!--end search-->
</li>
</ul>
</div>
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<div id="main">
<!-- Content Row -->
<div class="row">
<!-- Sidebar Column -->
<div class="col-md-3" id="tg-sb-sidebar">
<ul id="mysidebar" class="nav">
<li class="sidebarTitle">
<label for="docVersion">Eclipse Ditto version:</label>
<div class="select-wrapper">
<select id="docVersion" name="docVersion">
<option value="">development</option>
<option value="1.0">1.0</option>
<option value="1.1">1.1</option>
<option value="1.2">1.2</option>
<option value="1.3">1.3</option>
<option value="1.4">1.4</option>
</select>
</div>
<div id="dev-warning">
<div markdown="span" class="alert alert-warning" role="alert" style="font-size:0.6em"><i class="fa fa-warning"></i> <b>Important:</b> This documentation reflects the latest 'development'. You might want to choose a released version.</div>
</div>
</li>
<li class="subfolders">
<a href="#"><span></span>Introduction</a>
<ul>
<li><a href="intro-overview.html">Overview</a></li>
<li><a href="intro-digitaltwins.html">Digital twins</a></li>
<li><a href="intro-hello-world.html">Hello world</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Release Notes</a>
<ul>
<li><a href="release_notes_130.html">1.3.0</a></li>
<li><a href="release_notes_121.html">1.2.1</a></li>
<li><a href="release_notes_120.html">1.2.0</a></li>
<li><a href="release_notes_115.html">1.1.5</a></li>
<li><a href="release_notes_113.html">1.1.3</a></li>
<li><a href="release_notes_112.html">1.1.2</a></li>
<li><a href="release_notes_111.html">1.1.1</a></li>
<li><a href="release_notes_110.html">1.1.0</a></li>
<li><a href="release_notes_100.html">1.0.0</a></li>
<li><a href="release_notes_090.html">0.9.0</a></li>
<li><a href="release_notes_080.html">0.8.0</a></li>
<li class="subfolders">
<a href="#"><span></span>Milestone releases</a>
<ul>
<li><a href="release_notes_100-M2.html">1.0.0-M2</a></li>
<li><a href="release_notes_100-M1a.html">1.0.0-M1a</a></li>
<li><a href="release_notes_090-M2.html">0.9.0-M2</a></li>
<li><a href="release_notes_090-M1.html">0.9.0-M1</a></li>
<li><a href="release_notes_080-M3.html">0.8.0-M3</a></li>
<li><a href="release_notes_080-M2.html">0.8.0-M2</a></li>
<li><a href="release_notes_080-M1.html">0.8.0-M1</a></li>
<li><a href="release_notes_030-M2.html">0.3.0-M2</a></li>
<li><a href="release_notes_030-M1.html">0.3.0-M1</a></li>
<li><a href="release_notes_020-M1.html">0.2.0-M1</a></li>
<li><a href="release_notes_010-M3.html">0.1.0-M3</a></li>
<li><a href="release_notes_010-M1.html">0.1.0-M1</a></li>
</ul>
</li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Installation</a>
<ul>
<li><a href="installation-building.html">Building Ditto</a></li>
<li><a href="installation-running.html">Running Ditto</a></li>
<li><a href="installation-operating.html">Operating Ditto</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Basic concepts</a>
<ul>
<li><a href="basic-overview.html">Overview</a></li>
<li class="subfolders">
<a href="#"><span></span>Model entities</a>
<ul>
<li><a href="basic-thing.html">Thing</a></li>
<li><a href="basic-acl.html">Access Control List (ACL)</a></li>
<li><a href="basic-feature.html">Feature</a></li>
<li><a href="basic-policy.html">Policy</a></li>
<li><a href="basic-namespaces-and-names.html">Namespaces and Names</a></li>
<li><a href="basic-metadata.html">Thing Metadata</a></li>
<li><a href="basic-errors.html">Errors</a></li>
</ul>
</li>
<li><a href="basic-auth.html">Authentication and Authorization</a></li>
<li><a href="basic-messages.html">Messages</a></li>
<li><a href="basic-signals.html">Signals</a></li>
<li class="subfolders">
<a href="#"><span></span>Signal types</a>
<ul>
<li><a href="basic-signals-command.html">Command</a></li>
<li><a href="basic-signals-commandresponse.html">Command response</a></li>
<li><a href="basic-signals-errorresponse.html">Error response</a></li>
<li><a href="basic-signals-event.html">Event</a></li>
</ul>
</li>
<li><a href="basic-apis.html">APIs</a></li>
<li><a href="basic-connections.html">Connections</a></li>
<li><a href="basic-placeholders.html">Placeholders</a></li>
<li><a href="basic-changenotifications.html">Change notifications</a></li>
<li><a href="basic-rql.html">RQL expressions</a></li>
<li><a href="basic-enrichment.html">Signal enrichment</a></li>
<li><a href="basic-search.html">Search</a></li>
<li><a href="basic-acknowledgements.html">Acknowledgements / QoS</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Architecture</a>
<ul>
<li><a href="architecture-overview.html">Overview</a></li>
<li class="subfolders">
<a href="#"><span></span>Services</a>
<ul>
<li><a href="architecture-services-policies.html">Policies</a></li>
<li><a href="architecture-services-things.html">Things</a></li>
<li><a href="architecture-services-things-search.html">Things-Search</a></li>
<li><a href="architecture-services-connectivity.html">Connectivity</a></li>
<li><a href="architecture-services-concierge.html">Concierge</a></li>
<li><a href="architecture-services-gateway.html">Gateway</a></li>
</ul>
</li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>HTTP API</a>
<ul>
<li><a href="httpapi-overview.html">Overview</a></li>
<li><a href="httpapi-concepts.html">Concepts</a></li>
<li><a href="httpapi-search.html">Search</a></li>
<li><a href="httpapi-messages.html">Messages</a></li>
<li><a href="httpapi-protocol-bindings-websocket.html">WebSocket protocol binding</a></li>
<li><a href="httpapi-sse.html">Server sent events</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Connectivity API</a>
<ul>
<li><a href="connectivity-overview.html">Overview</a></li>
<li><a href="connectivity-manage-connections.html">Manage connections</a></li>
<li><a href="connectivity-protocol-bindings-amqp091.html">AMQP 0.9.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-amqp10.html">AMQP 1.0 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-mqtt.html">MQTT 3.1.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-mqtt5.html">MQTT 5 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-http.html">HTTP 1.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-kafka2.html">Kafka 2.x protocol binding</a></li>
<li class="active"><a href="connectivity-mapping.html">Payload mapping</a></li>
<li><a href="connectivity-header-mapping.html">Header mapping</a></li>
<li><a href="connectivity-tls-certificates.html">TLS certificates</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Client SDK</a>
<ul>
<li><a href="client-sdk-overview.html">Overview</a></li>
<li><a href="client-sdk-java.html">Java</a></li>
<li><a href="client-sdk-javascript.html">JavaScript</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Ditto Protocol</a>
<ul>
<li><a href="protocol-overview.html">Overview</a></li>
<li><a href="protocol-twinlive.html">Twin/live channel</a></li>
<li><a href="protocol-specification.html">Specification</a></li>
<li><a href="protocol-specification-topic.html">Protocol topic</a></li>
<li><a href="protocol-specification-things.html">Things group</a></li>
<li class="subfolders">
<a href="#"><span></span>→ commands/events</a>
<ul>
<li><a href="protocol-specification-things-create-or-modify.html">Create/Modify</a></li>
<li><a href="protocol-specification-things-retrieve.html">Retrieve</a></li>
<li><a href="protocol-specification-things-delete.html">Delete</a></li>
<li><a href="protocol-specification-acks.html">Acknowledgements</a></li>
<li><a href="protocol-specification-errors.html">Errors</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>→ search/messages</a>
<ul>
<li><a href="protocol-specification-things-search.html">Search</a></li>
<li><a href="protocol-specification-things-messages.html">Messages</a></li>
</ul>
</li>
<li><a href="protocol-specification-policies.html">Policies group</a></li>
<li class="subfolders">
<a href="#"><span></span>→ commands/events</a>
<ul>
<li><a href="protocol-specification-policies-create-or-modify.html">Create/Modify</a></li>
<li><a href="protocol-specification-policies-retrieve.html">Retrieve</a></li>
<li><a href="protocol-specification-policies-delete.html">Delete</a></li>
</ul>
</li>
<li><a href="protocol-bindings.html">Bindings</a></li>
<li><a href="protocol-examples.html">Examples</a></li>
<li class="subfolders">
<a href="#"><span></span>→ Things examples</a>
<ul>
<li><a href="protocol-examples-creatething.html">Create a Thing</a></li>
<li><a href="protocol-examples-deletething.html">Delete a Thing</a></li>
<li><a href="protocol-examples-modifything.html">Modify a Thing</a></li>
<li><a href="protocol-examples-retrievething.html">Retrieve a Thing</a></li>
<li><a href="protocol-examples-retrievethings.html">Retrieve multiple Things</a></li>
<li><a href="protocol-examples-modifypolicyid.html">Modify the Policy ID of a Thing</a></li>
<li><a href="protocol-examples-createattributes.html">Create Attributes</a></li>
<li><a href="protocol-examples-deleteattributes.html">Delete Attributes</a></li>
<li><a href="protocol-examples-modifyattributes.html">Modify Attributes</a></li>
<li><a href="protocol-examples-retrieveattributes.html">Retrieve Attributes</a></li>
<li><a href="protocol-examples-createattribute.html">Create a single Attribute</a></li>
<li><a href="protocol-examples-deleteattribute.html">Delete a single Attribute</a></li>
<li><a href="protocol-examples-modifyattribute.html">Modify a single Attribute</a></li>
<li><a href="protocol-examples-retrieveattribute.html">Retrieve a single Attribute</a></li>
<li><a href="protocol-examples-createthingdefinition.html">Create a Definition</a></li>
<li><a href="protocol-examples-deletethingdefinition.html">Delete a Definition</a></li>
<li><a href="protocol-examples-modifythingdefinition.html">Modify a Definition</a></li>
<li><a href="protocol-examples-retrievethingdefinition.html">Retrieve a Definition</a></li>
<li><a href="protocol-examples-createfeatures.html">Create Features</a></li>
<li><a href="protocol-examples-deletefeatures.html">Delete Features</a></li>
<li><a href="protocol-examples-modifyfeatures.html">Modify Features</a></li>
<li><a href="protocol-examples-retrievefeatures.html">Retrieve Features</a></li>
<li><a href="protocol-examples-createfeature.html">Create a single Feature</a></li>
<li><a href="protocol-examples-deletefeature.html">Delete a single Feature</a></li>
<li><a href="protocol-examples-modifyfeature.html">Modify a single Feature</a></li>
<li><a href="protocol-examples-retrievefeature.html">Retrieve a single Feature</a></li>
<li><a href="protocol-examples-createdefinition.html">Create Feature Definition</a></li>
<li><a href="protocol-examples-deletedefinition.html">Delete Feature Definition</a></li>
<li><a href="protocol-examples-modifydefinition.html">Modify Feature Definition</a></li>
<li><a href="protocol-examples-retrievedefinition.html">Retrieve Feature Definition</a></li>
<li><a href="protocol-examples-createproperties.html">Create Feature Properties</a></li>
<li><a href="protocol-examples-deleteproperties.html">Delete Feature Properties</a></li>
<li><a href="protocol-examples-modifyproperties.html">Modify Feature Properties</a></li>
<li><a href="protocol-examples-retrieveproperties.html">Retrieve Feature Properties</a></li>
<li><a href="protocol-examples-createproperty.html">Create a single Property</a></li>
<li><a href="protocol-examples-deleteproperty.html">Delete a single Property</a></li>
<li><a href="protocol-examples-modifyproperty.html">Modify a single Property</a></li>
<li><a href="protocol-examples-retrieveproperty.html">Retrieve a single Property</a></li>
<li><a href="protocol-examples-errorresponses.html">Error responses</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>→ Policies examples</a>
<ul>
<li><a href="protocol-examples-policies-createpolicy.html">Create a Policy</a></li>
<li><a href="protocol-examples-policies-deletepolicy.html">Delete a Policy</a></li>
<li><a href="protocol-examples-policies-modifypolicy.html">Modify a Policy</a></li>
<li><a href="protocol-examples-policies-retrievepolicy.html">Retrieve a Policy</a></li>
<li><a href="protocol-examples-policies-modifypolicyentries.html">Modify entries</a></li>
<li><a href="protocol-examples-policies-retrievepolicyentries.html">Retrieve entries</a></li>
<li><a href="protocol-examples-policies-createpolicyentry.html">Create a single entry</a></li>
<li><a href="protocol-examples-policies-deletepolicyentry.html">Delete a single entry</a></li>
<li><a href="protocol-examples-policies-modifypolicyentry.html">Modify a single entry</a></li>
<li><a href="protocol-examples-policies-retrievepolicyentry.html">Retrieve a single entry</a></li>
<li><a href="protocol-examples-policies-modifysubjects.html">Modify subjects</a></li>
<li><a href="protocol-examples-policies-retrievesubjects.html">Retrieve subjects</a></li>
<li><a href="protocol-examples-policies-createsubject.html">Create a single subject</a></li>
<li><a href="protocol-examples-policies-deletesubject.html">Delete a single subject</a></li>
<li><a href="protocol-examples-policies-modifysubject.html">Modify a single subject</a></li>
<li><a href="protocol-examples-policies-retrievesubject.html">Retrieve a single subject</a></li>
<li><a href="protocol-examples-policies-modifyresources.html">Modify resources</a></li>
<li><a href="protocol-examples-policies-retrieveresources.html">Retrieve resources</a></li>
<li><a href="protocol-examples-policies-createresource.html">Create a single resource</a></li>
<li><a href="protocol-examples-policies-deleteresource.html">Delete a single resource</a></li>
<li><a href="protocol-examples-policies-modifyresource.html">Modify a single resource</a></li>
<li><a href="protocol-examples-policies-retrieveresource.html">Retrieve a single resource</a></li>
<li><a href="protocol-examples-policies-errorresponses.html">Error responses</a></li>
</ul>
</li>
<li><a href="protocol-examples-search.html">→ Search examples</a></li>
</ul>
</li>
<li><a href="sandbox.html">Sandbox</a></li>
<li><a href="presentations.html">Presentations</a></li>
<li><a href="glossary.html">Glossary</a></li>
<li><a href="feedback.html">Feedback</a></li>
<p class="external">
<a href="#" id="collapseAll">Collapse All</a> | <a href="#" id="expandAll">Expand All</a>
</p>
</ul>
<!-- this highlights the active parent class in the sidebar. this is critical so that the parent expands when you're viewing a page. This must appear below the sidebar code above. Otherwise, if placed inside customscripts.js, the script runs before the sidebar code runs and the class never gets inserted.-->
<script>$("li.active").parents('li').toggleClass("active");
</script>
</div>
<!-- Content Column -->
<div class="col-md-9" id="tg-sb-content">
<div class="post-header">
<h1 class="post-title-main">Payload mapping in connectivity service</h1>
</div>
<div class="post-content">
<!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
<script>
$( document ).ready(function() {
// Handler for .ready() called.
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
/* this offset helps account for the space taken up by the floating toolbar. */
$('#toc').on('click', 'a', function() {
var target = $(this.getAttribute('href'))
, scroll_target = target.offset().top
$(window).scrollTop(scroll_target - 10);
return false
})
});
</script>
<div id="toc"></div>
<div class="bs-callout bs-callout-primary"><strong>TL;DR</strong><br />The payload mapping feature in Ditto’s connectivity APIs can be used to
transform arbitrary payload consumed via the different supported protocols
to <a href="protocol-overview.html">Ditto Protocol</a> messages and vice versa.</div>
<h2 id="motivation">Motivation</h2>
<p>Eclipse Ditto is about providing access to IoT devices via the <a href="intro-digitaltwins.html">digital twin</a> pattern. In order to
provide structured APIs for different heterogeneous devices Ditto defines a lightweight JSON based <a href="basic-overview.html">model</a>.</p>
<p>A <a href="basic-thing.html">Thing</a> might look like in the following example:</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">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"the.namespace:the-thing-id"</span><span class="p">,</span><span class="w">
</span><span class="s2">"policyId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"the.namespace:the-policy-id"</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">"location"</span><span class="p">:</span><span class="w"> </span><span class="s2">"kitchen"</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">"transmission"</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">"cur_speed"</span><span class="p">:</span><span class="w"> </span><span class="mi">90</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>Devices in the IoT, may they be brownfield devices or newly produced devices, will probably not send their data to the
cloud in the structure and <a href="protocol-overview.html">protocol</a> Ditto requires.</p>
<p>They should not need to be aware of something like Ditto running in the cloud mirroring them as digital twins.</p>
<p>So for example device payload could 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">"val"</span><span class="p">:</span><span class="w"> </span><span class="s2">"23.42 °C"</span><span class="p">,</span><span class="w">
</span><span class="s2">"ts"</span><span class="p">:</span><span class="w"> </span><span class="mi">1523946112727</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>In case of constrained devices or IoT protocols, even binary payload might be common.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x08BD (hex representation)
</code></pre></div></div>
<h2 id="builtin-mappers">Builtin mappers</h2>
<p>The following message mappers are included in the Ditto codebase:</p>
<table>
<thead>
<tr>
<th>Mapper Alias</th>
<th>Description</th>
<th>Inbound</th>
<th>Outbound</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#ditto-mapper">Ditto</a></td>
<td>Assumes that inbound/outbound messages are already in <a href="protocol-overview.html">Ditto Protocol</a> (JSON) format.</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#javascript-mapper">JavaScript</a></td>
<td>Converts arbitrary messages from and to the <a href="protocol-overview.html">Ditto Protocol</a> format using <strong>custom</strong> JavaScript code executed by Ditto.</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#normalized-mapper">Normalized</a></td>
<td>Transforms the payload of events to a normalized view.</td>
<td> </td>
<td></td>
</tr>
<tr>
<td><a href="#connectionstatus-mapper">ConnectionStatus</a></td>
<td>This mapper handles messages containing <code class="highlighter-rouge">creation-time</code> and <code class="highlighter-rouge">ttd</code> headers by updating a feature of the targeted thing with <a href="basic-feature.html#feature-definition">definition</a> <a href="https://vorto.eclipse.org/#/details/org.eclipse.ditto:ConnectionStatus:1.0.0">ConnectionStatus</a>.</td>
<td></td>
<td> </td>
</tr>
<tr>
<td><a href="#rawmessage-mapper">RawMessage</a></td>
<td>For outgoing message commands and responses, this mapper extracts the payload for publishing directly into the channel. For incoming messages, this mapper wraps them in a configured message command or response envelope.</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#implicitthingcreation-mapper">ImplicitThingCreation</a></td>
<td>This mapper handles messages for which a Thing should be created automatically based on a defined template</td>
<td></td>
<td> </td>
</tr>
</tbody>
</table>
<h3 id="ditto-mapper">Ditto mapper</h3>
<p>This is the default <a href="protocol-overview.html">Ditto Protocol</a> mapper. If you do not specify any payload mapping this
mapper is used to map inbound and outbound messages. The mapper requires has no mandatory options, so its alias can
be directly used as a mapper reference.</p>
<p>It assumes that received messages are in <a href="protocol-specification.html">Ditto Protocol JSON</a> and emits outgoing messages
also in that format.</p>
<h3 id="javascript-mapper">JavaScript mapper</h3>
<p>This mapper may be used whenever any inbound messages are not yet in <a href="protocol-overview.html">Ditto Protocol</a>. By using
the built in <a href="#javascript-mapping-engine">JavaScript mapping engine</a> (based on Rhino) custom defined JavaScript scripts
can be executed which are responsible for creating <a href="protocol-specification.html">Ditto Protocol JSON</a> message from
arbitrary consumed payload.</p>
<p>The same is possible for outbound messages in order to transform <a href="protocol-specification.html">Ditto Protocol JSON</a>
messages (e.g. events or responses) to arbitrary other formats.</p>
<h4 id="configuration-options">Configuration options</h4>
<ul>
<li><code class="highlighter-rouge">incomingScript</code> (required): the mapping script for incoming messages</li>
<li><code class="highlighter-rouge">outgoingScript</code> (required): the mapping script for outgoing messages</li>
<li><code class="highlighter-rouge">loadBytebufferJS</code> (optional, default: <code class="highlighter-rouge">"false"</code>): whether to load ByteBufferJS library</li>
<li><code class="highlighter-rouge">loadLongJS</code> (optional, default: <code class="highlighter-rouge">"false"</code>): whether to load LongJS library</li>
</ul>
<h3 id="normalized-mapper">Normalized mapper</h3>
<p>This mapper transforms <code class="highlighter-rouge">created</code> and <code class="highlighter-rouge">modified</code> events (other type of messages are dropped) to a normalized view.
Events are mapped to a nested sparse JSON.</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">"thing/id/things/twin/events/modified"</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">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/vnd.eclipse.ditto+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">"/features/sensors/properties/temperature/indoor/value"</span><span class="p">,</span><span class="w">
</span><span class="s2">"value"</span><span class="p">:</span><span class="w"> </span><span class="mi">42</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>would result in the following normalized JSON representation:</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">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"thing:id"</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">"sensors"</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">"temperature"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"indoor"</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="mi">42</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><span class="s2">"_context"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"topic"</span><span class="p">:</span><span class="w"> </span><span class="s2">"thing/id/things/twin/events/modified"</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/sensors/properties/temperature/indoor/value"</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">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/vnd.eclipse.ditto+json"</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>The <code class="highlighter-rouge">_context</code> field contains the original message content excluding the <code class="highlighter-rouge">value</code>.</p>
<h4 id="configuration-options-1">Configuration options</h4>
<ul>
<li><code class="highlighter-rouge">fields</code> (optional, default: all fields): comma separated list of fields that are contained in the result (see also
chapter about <a href="httpapi-concepts.html#with-field-selector">field selectors</a>)</li>
</ul>
<h3 id="connectionstatus-mapper">ConnectionStatus mapper</h3>
<p>This mapper transforms the information from the <code class="highlighter-rouge">ttd</code> and <code class="highlighter-rouge">creation-time</code> message headers (see Eclipse Hono <a href="https://www.eclipse.org/hono/docs/concepts/device-notifications/">device
notifications</a>) into a ModifyFeature
command that complies with the <a href="https://vorto.eclipse.org/#/details/org.eclipse.ditto:ConnectionStatus:1.0.0">Vorto functionblock</a> <code class="highlighter-rouge">org.eclipse.ditto:ConnectionStatus</code>.</p>
<p>The connectivity state of the device is then represented in a Feature.<br />
It is mostly used in conjunction with another mapper that transforms the payload e.g.:<br />
<code class="highlighter-rouge">"payloadMapping": [ "Ditto" , "connectionStatus" ]</code></p>
<p>Example of a resulting <code class="highlighter-rouge">ConnectionStatus</code> feature:</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">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"eclipse:ditto"</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">"ConnectionStatus"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"definition"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"org.eclipse.ditto:ConnectionStatus:1.0.0"</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">"status"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"readySince"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2019-10-29T14:16:18Z"</span><span class="p">,</span><span class="w">
</span><span class="s2">"readyUntil"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2019-10-29T14:21:18Z"</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>
<h4 id="configuration-options-2">Configuration options</h4>
<ul>
<li><code class="highlighter-rouge">thingId</code> (required): The ID of the Thing that is updated with the connectivity state. It can either be a fixed value
or a header placeholder (e.g. <code class="highlighter-rouge">{{ header:device_id }}</code>).</li>
<li><code class="highlighter-rouge">featureId</code> (optional, default: <code class="highlighter-rouge">ConnectionStatus</code>): The ID of the Feature that is updated. It can either be a
fixed value or resolved from a message header (e.g. <code class="highlighter-rouge">{{ header:feature_id }}</code>).</li>
</ul>
<h3 id="rawmessage-mapper">RawMessage mapper</h3>
<p>This mapper relates the payload in the <code class="highlighter-rouge">"value"</code> field of message commands and message responses to the payload
of AMQP, MQTT and Kafka messages and the body of HTTP requests. The encoding of the payload is chosen according to
the configured content type. The subject, direction, thing ID and feature ID of the envelope for incoming message
commands and responses need to be configured.</p>
<p>Messages with the Ditto protocol content type <code class="highlighter-rouge">application/vnd.eclipse.ditto+json</code> or signals that are not message
commands or responses are mapped by the <a href="#ditto-mapper">Ditto mapper</a> instead.</p>
<p>For example, the mapper maps between the feature message command response</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/smartcoffee/things/live/messages/heatUp"</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">"content-type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/octet-stream"</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/water-tank/inbox/messages/heatUp"</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">"AQIDBAUG"</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">200</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>and an AMQP, MQTT 5, Kafka message with payload or an HTTP request with body of 6 bytes</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x01 02 03 04 05 06
</code></pre></div></div>
<p>and headers</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>content-type: application/octet-stream
status: 200
subject: heatUp
ditto-message-direction: TO
ditto-message-thing-id: org.eclipse.ditto:smartcoffee
ditto-message-feature-id: water-tank
</code></pre></div></div>
<p>The headers are lost for connection protocols without application headers such as MQTT 3.</p>
<h4 id="configuration-options-3">Configuration options</h4>
<p>Example configuration:</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">"outgoingContentType"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/octet-stream"</span><span class="p">,</span><span class="w">
</span><span class="s2">"incomingMessageHeaders"</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">"{{ header:content-type | fn:default('application/octet-stream') }}"</span><span class="p">,</span><span class="w">
</span><span class="s2">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:status }}"</span><span class="p">,</span><span class="w">
</span><span class="s2">"subject"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:subject | fn:default('fallback-subject') }}"</span><span class="p">,</span><span class="w">
</span><span class="s2">"ditto-message-direction"</span><span class="p">:</span><span class="w"> </span><span class="s2">"TO"</span><span class="p">,</span><span class="w">
</span><span class="s2">"ditto-message-thing-id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:ditto-message-thing-id | fn:default('ns:fallback-thing') }}"</span><span class="p">,</span><span class="w">
</span><span class="s2">"ditto-message-feature-id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:ditto-message-feature-id }}"</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>
<ul>
<li><code class="highlighter-rouge">outgoingContentType</code> (optional): The fallback content-type for outgoing message commands and responses without
the content-type header. Default to <code class="highlighter-rouge">text/plain; charset=UTF-8</code>.</li>
<li><code class="highlighter-rouge">incomingMessageHeaders</code> (optional): A JSON object containing the following headers needed to construct a message
command or response envelope containing the incoming message as payload in the field <code class="highlighter-rouge">"value"</code>. Placeholder expressions
reading from the protocol headers of incoming messages may be used.
<ul>
<li><code class="highlighter-rouge">content-type</code> (optional): The content type with which to encode the incoming message as payload.
Default to <code class="highlighter-rouge">{{ header:content-type | fn:default('application/octet-stream') }}</code>.
If resolved to the Ditto protocol content type <code class="highlighter-rouge">application/vnd.eclipse.ditto+json</code>, then the entire payload
is interpreted as a Ditto protocol message instead.</li>
<li><code class="highlighter-rouge">status</code> (optional): Include for message responses. Exclude for message commands. Default to
<code class="highlighter-rouge">{{ header:status }}</code>.</li>
<li><code class="highlighter-rouge">subject</code> (mandatory for MQTT 3): Subject of the message. Default to <code class="highlighter-rouge">{{ header:subject }}</code>.
Mapping will fail if not resolvable.</li>
<li><code class="highlighter-rouge">ditto-message-direction</code> (optional): The message direction. Default to <code class="highlighter-rouge">TO</code>, which corresponds to <code class="highlighter-rouge">inbox</code> in
message commands and responses.</li>
<li><code class="highlighter-rouge">ditto-message-thing-id</code> (mandatory for MQTT 3): ID of the thing to send the message command or response to.
Default to <code class="highlighter-rouge">{{ header:ditto-message-thing-id }}</code>. Mapping will fail if not resolvable.</li>
<li><code class="highlighter-rouge">ditto-message-feature-id</code> (optional): Include to send the message or message response to a feature of the thing.
Exclude to send it to the thing itself. Default to <code class="highlighter-rouge">{{ header:ditto-message-feature-id }}</code>.</li>
</ul>
</li>
</ul>
<h3 id="implicitthingcreation-mapper">ImplicitThingCreation Mapper</h3>
<p>This mapper implicitly creates a new thing for an incoming message.</p>
<p>The created thing contains the values defined in the template, configured in the <code class="highlighter-rouge">mappingDefinitions</code> <code class="highlighter-rouge">options</code>.<br /></p>
<h4 id="configuration-options-4">Configuration options</h4>
<ul>
<li><code class="highlighter-rouge">thing</code> (required): The values of the thing that is created implicitly. It can either contain fixed values
or header placeholders (e.g. <code class="highlighter-rouge">{{ header:device_id }}</code>).</li>
</ul>
<p>Example of a template defined in <code class="highlighter-rouge">options</code>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"thing"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:device_id }}"</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">"CreatedBy"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ImplicitThingCreation"</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>
<h2 id="example-connection-with-multiple-mappers">Example connection with multiple mappers</h2>
<p>The following example connection defines a <code class="highlighter-rouge">ConnectionStatus</code> mapping with the ID <code class="highlighter-rouge">status</code> and references it in a
source.<br />
Messages received via this source will be mapped by the <code class="highlighter-rouge">Ditto</code> mapping and the <code class="highlighter-rouge">ConnectionStatus</code> mapping.<br />
The <code class="highlighter-rouge">Ditto</code> mapping requires no options to be configured, so you can directly use its alias <code class="highlighter-rouge">Ditto</code>.</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">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"exampleConnection"</span><span class="p">,</span><span class="w">
</span><span class="s2">"sources"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="w">
</span><span class="s2">"addresses"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"&lt;source&gt;"</span><span class="p">],</span><span class="w">
</span><span class="s2">"authorizationContext"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"ditto:inbound"</span><span class="p">],</span><span class="w">
</span><span class="s2">"payloadMapping"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Ditto"</span><span class="p">,</span><span class="w"> </span><span class="s2">"status"</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">"mappingDefinitions"</span><span class="p">:</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="p">{</span><span class="w">
</span><span class="s2">"mappingEngine"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ConnectionStatus"</span><span class="p">,</span><span class="w">
</span><span class="s2">"options"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:device_id }}"</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>
<div class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note:</b> Starting aliases with an uppercase character and IDs with a lowercase character is
encouraged to avoid confusion but this is not enforced. </div>
<h2 id="example-connection-with-mapping-conditions">Example connection with mapping conditions</h2>
<p>The following example connection defines <code class="highlighter-rouge">incomingConditions</code> and <code class="highlighter-rouge">outgoingConditions</code>for the ConnectionStatus mapping engine.<br />
Optional incomingConditions are validated before the mapping of inbound messages.<br />
Optional outgoingConditions are validated before the mapping of outbound messages.<br />
Conditional Mapping can be achieved by using <a href="basic-placeholders.html#function-expressions">function expressions</a>.
When multiple incoming or outgoing conditions are set for one <code class="highlighter-rouge">mappingEngine</code>, all have to equal true for the mapping to be executed.</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">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"exampleConnection"</span><span class="p">,</span><span class="w">
</span><span class="s2">"sources"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="w">
</span><span class="s2">"addresses"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"&lt;source&gt;"</span><span class="p">],</span><span class="w">
</span><span class="s2">"authorizationContext"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"ditto:inbound"</span><span class="p">],</span><span class="w">
</span><span class="s2">"payloadMapping"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"status"</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">"mappingDefinitions"</span><span class="p">:</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="p">{</span><span class="w">
</span><span class="s2">"mappingEngine"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ConnectionStatus"</span><span class="p">,</span><span class="w">
</span><span class="s2">"incomingConditions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"sampleCondition"</span><span class="p">:</span><span class="w"> </span><span class="s2">"fn:filter(header:incoming-mapping-required,'eq','true')"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"outgoingConditions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"sampleCondition"</span><span class="p">:</span><span class="w"> </span><span class="s2">"fn:filter(header:outgoing-mapping-required,'eq','true')"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"options"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ header:device_id }}"</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>
<h2 id="javascript-mapping-engine">JavaScript mapping engine</h2>
<p>Ditto utilizes the <a href="https://github.com/mozilla/rhino">Rhino</a> JavaScript engine for Java for evaluating the JavaScript
to apply for mapping payloads.</p>
<p>Using Rhino instead of Nashorn, the newer JavaScript engine shipped with Java, has the benefit that sandboxing can be
applied in a better way.</p>
<p>Sandboxing of different payload scripts is required as Ditto is intended to be run as cloud service where multiple
connections to different endpoints are managed for different tenants at the same time. This requires the isolation of
each single script to avoid interference with other scripts and to protect the JVM executing the script against harmful
code execution.</p>
<h3 id="constraints">Constraints</h3>
<p>Rhino does not fully support EcmaScript 6. Check which language constructs are supported before using
them in a mapping function. See <a href="http://mozilla.github.io/rhino/compat/engines.html">http://mozilla.github.io/rhino/compat/engines.html</a>.</p>
<p>Ditto currently includes Rhino version <code class="highlighter-rouge">1.7.11</code> and has the <code class="highlighter-rouge">VERSION_ES6</code> flag enabled.</p>
<h4 id="sandboxing">Sandboxing</h4>
<p>For sandboxing/security reasons following restrictions apply:</p>
<ul>
<li>access to Java packages and classes is not possible</li>
<li>using <code class="highlighter-rouge">exit</code>, <code class="highlighter-rouge">quit</code>, <code class="highlighter-rouge">print</code>, etc. is not possible</li>
<li>file access is not possible</li>
<li>doing remote calls (e.g. to foreign web-servers) is not possible</li>
<li>programming an endless-loop will terminate the script</li>
<li>programming a recursion will terminate the script</li>
<li>the file size of the script is limited</li>
<li>no foreign JS libraries can be loaded (unless they fit in the file size limit and are included into the mapping script)</li>
</ul>
<h3 id="helper-libraries">Helper libraries</h3>
<p>In order to work more conveniently with binary payloads, the following libraries may be loaded for payload transformations:</p>
<ul>
<li><a href="https://github.com/dcodeIO/bytebuffer.js">bytebuffer.js</a> a ByteBuffer implementation using ArrayBuffers</li>
<li><a href="https://github.com/dcodeIO/long.js">long.js</a> for representing a 64-bit two’s-complement integer value</li>
</ul>
<h3 id="helper-functions">Helper functions</h3>
<p>Ditto comes with a few helper functions, which makes writing the mapping scripts easier. They are available under the
<code class="highlighter-rouge">Ditto</code> scope:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* Builds a Ditto Protocol message from the passed parameters.
* @param {string} namespace - The namespace of the entity in java package notation, e.g.: "org.eclipse.ditto"
* @param {string} id - The ID of the entity
* @param {string} group - The affected group/entity, one of: "things"
* @param {string} channel - The channel for the signal, one of: "twin"|"live"
* @param {string} criterion - The criterion to apply, one of: "commands"|"events"|"search"|"messages"|"errors"
* @param {string} action - The action to perform, one of: "create"|"retrieve"|"modify"|"delete"
* @param {string} path - The path which is affected by the message, e.g.: "/attributes"
* @param {Object.&lt;string, string&gt;} dittoHeaders - The headers Object containing all Ditto Protocol header values
* @param {*} [value] - The value to apply / which was applied (e.g. in a "modify" action)
* @param {number} status - The status code that indicates the result of the command.
* @param {Object} extra - The enriched extra fields when selected via "extraFields" option.
* @returns {DittoProtocolMessage} dittoProtocolMessage -
* the mapped Ditto Protocol message 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">buildDittoProtocolMsg</span><span class="p">(</span><span class="nx">namespace</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">group</span><span class="p">,</span> <span class="nx">channel</span><span class="p">,</span> <span class="nx">criterion</span><span class="p">,</span> <span class="nx">action</span><span class="p">,</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">dittoHeaders</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">status</span><span class="p">,</span> <span class="nx">extra</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">dittoProtocolMsg</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">topic</span> <span class="o">=</span> <span class="nx">namespace</span> <span class="o">+</span> <span class="s2">"/"</span> <span class="o">+</span> <span class="nx">id</span> <span class="o">+</span> <span class="s2">"/"</span> <span class="o">+</span> <span class="nx">group</span> <span class="o">+</span> <span class="s2">"/"</span> <span class="o">+</span> <span class="nx">channel</span> <span class="o">+</span> <span class="s2">"/"</span> <span class="o">+</span> <span class="nx">criterion</span> <span class="o">+</span> <span class="s2">"/"</span> <span class="o">+</span> <span class="nx">action</span><span class="p">;</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">path</span> <span class="o">=</span> <span class="nx">path</span><span class="p">;</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">headers</span> <span class="o">=</span> <span class="nx">dittoHeaders</span><span class="p">;</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">status</span> <span class="o">=</span> <span class="nx">status</span><span class="p">;</span>
<span class="nx">dittoProtocolMsg</span><span class="p">.</span><span class="nx">extra</span> <span class="o">=</span> <span class="nx">extra</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">dittoProtocolMsg</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/**
* Builds an external message from the passed parameters.
* @param {Object.&lt;string, string&gt;} headers - The external headers Object containing header values
* @param {string} [textPayload] - The external mapped String
* @param {ArrayBuffer} [bytePayload] - The external mapped bytes as ArrayBuffer
* @param {string} [contentType] - The returned Content-Type
* @returns {ExternalMessage} externalMessage -
* the mapped external message
* 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">buildExternalMsg</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">externalMsg</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">externalMsg</span><span class="p">.</span><span class="nx">headers</span> <span class="o">=</span> <span class="nx">headers</span><span class="p">;</span>
<span class="nx">externalMsg</span><span class="p">.</span><span class="nx">textPayload</span> <span class="o">=</span> <span class="nx">textPayload</span><span class="p">;</span>
<span class="nx">externalMsg</span><span class="p">.</span><span class="nx">bytePayload</span> <span class="o">=</span> <span class="nx">bytePayload</span><span class="p">;</span>
<span class="nx">externalMsg</span><span class="p">.</span><span class="nx">contentType</span> <span class="o">=</span> <span class="nx">contentType</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">externalMsg</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/**
* Transforms the passed ArrayBuffer to a String interpreting the content of the passed arrayBuffer as unsigned 8
* bit integers.
*
* @param {ArrayBuffer} arrayBuffer the ArrayBuffer to transform to a String
* @returns {String} the transformed String
*/</span>
<span class="kd">function</span> <span class="nx">arrayBufferToString</span><span class="p">(</span><span class="nx">arrayBuffer</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">arrayBuffer</span><span class="p">));</span>
<span class="p">}</span>
<span class="cm">/**
* Transforms the passed String to an ArrayBuffer using unsigned 8 bit integers.
*
* @param {String} string the String to transform to an ArrayBuffer
* @returns {ArrayBuffer} the transformed ArrayBuffer
*/</span>
<span class="kd">function</span> <span class="nx">stringToArrayBuffer</span><span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">buf</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">ArrayBuffer</span><span class="p">(</span><span class="nx">string</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">bufView</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">buf</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="nx">strLen</span><span class="o">=</span><span class="nx">string</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;</span><span class="nx">strLen</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">bufView</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">string</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">buf</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/**
* Transforms the passed ArrayBuffer to a {ByteBuffer} (from bytebuffer.js library which needs to be loaded).
*
* @param {ArrayBuffer} arrayBuffer the ArrayBuffer to transform
* @returns {ByteBuffer} the transformed ByteBuffer
*/</span>
<span class="kd">function</span> <span class="nx">asByteBuffer</span><span class="p">(</span><span class="nx">arrayBuffer</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">byteBuffer</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">ArrayBuffer</span><span class="p">(</span><span class="nx">arrayBuffer</span><span class="p">.</span><span class="nx">byteLength</span><span class="p">);</span>
<span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">byteBuffer</span><span class="p">).</span><span class="kd">set</span><span class="p">(</span><span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">arrayBuffer</span><span class="p">));</span>
<span class="k">return</span> <span class="nx">dcodeIO</span><span class="p">.</span><span class="nx">ByteBuffer</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">byteBuffer</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="mapping-incoming-messages">Mapping incoming messages</h3>
<p>Incoming external messages can be mapped to Ditto Protocol conform messages by implementing the following JavaScript function:</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="c1">// ###</span>
<span class="c1">// Insert your mapping logic here:</span>
<span class="c1">// ###</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="nx">namespace</span><span class="p">,</span>
<span class="nx">id</span><span class="p">,</span>
<span class="nx">group</span><span class="p">,</span>
<span class="nx">channel</span><span class="p">,</span>
<span class="nx">criterion</span><span class="p">,</span>
<span class="nx">action</span><span class="p">,</span>
<span class="nx">path</span><span class="p">,</span>
<span class="nx">dittoHeaders</span><span class="p">,</span>
<span class="nx">value</span><span class="p">,</span>
<span class="nx">status</span>
<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The result of the function has to be a JavaScript object in <a href="protocol-overview.html">Ditto Protocol</a> or an array of
such JavaScript objects. That’s where the helper method <code class="highlighter-rouge">Ditto.buildDittoProtocolMsg</code> is useful: it explicitly
defines which parameters are required for the Ditto Protocol message.</p>
<h3 id="mapping-outgoing-messages">Mapping outgoing messages</h3>
<p>Outgoing Ditto Protocol messages (e.g. <a href="basic-signals-commandresponse.html">responses</a> or <a href="basic-signals-event.html">events</a>)
can be mapped to external messages by implementing the following JavaScript function:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* Maps the passed parameters which originated from a Ditto Protocol message to an external message.
* @param {string} namespace - The namespace of the entity in java package notation, e.g.: "org.eclipse.ditto"
* @param {string} id - The ID of the entity
* @param {string} channel - The channel for the signal, one of: "twin"|"live"
* @param {string} group - The affected group/entity, one of: "things"
* @param {string} criterion - The criterion to apply, one of: "commands"|"events"|"search"|"messages"|"errors"
* @param {string} action - The action to perform, one of: "create"|"retrieve"|"modify"|"delete"
* @param {string} path - The path which is affected by the message, e.g.: "/attributes"
* @param {Object.&lt;string, string&gt;} dittoHeaders - The headers Object containing all Ditto Protocol header values
* @param {*} [value] - The value to apply / which was applied (e.g. in a "modify" action)
* @param {number} status - The status code that indicates the result of the command.
* @param {Object} extra - The enriched extra fields when selected via "extraFields" option.
* @returns {(ExternalMessage|Array&lt;ExternalMessage&gt;)} externalMessage -
* The mapped external message,
* an array of external 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">mapFromDittoProtocolMsg</span><span class="p">(</span>
<span class="nx">namespace</span><span class="p">,</span>
<span class="nx">id</span><span class="p">,</span>
<span class="nx">group</span><span class="p">,</span>
<span class="nx">channel</span><span class="p">,</span>
<span class="nx">criterion</span><span class="p">,</span>
<span class="nx">action</span><span class="p">,</span>
<span class="nx">path</span><span class="p">,</span>
<span class="nx">dittoHeaders</span><span class="p">,</span>
<span class="nx">value</span><span class="p">,</span>
<span class="nx">status</span><span class="p">,</span>
<span class="nx">extra</span>
<span class="p">)</span> <span class="p">{</span>
<span class="c1">// ###</span>
<span class="c1">// Insert your mapping logic here:</span>
<span class="c1">// ###</span>
<span class="k">return</span> <span class="nx">Ditto</span><span class="p">.</span><span class="nx">buildExternalMsg</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>
</code></pre></div></div>
<p>The result of the function has to be a JavaScript object or an array of JavaScript objects with the fields <code class="highlighter-rouge">headers</code>,
<code class="highlighter-rouge">textPayload</code>, <code class="highlighter-rouge">bytePayload</code> and <code class="highlighter-rouge">contentType</code>. That’s where the helper method <code class="highlighter-rouge">Ditto.buildExternalMsg</code> is useful: it
explicitly defines which parameters are required for the external message.</p>
<h2 id="javascript-payload-types">JavaScript payload types</h2>
<p>Both, text payloads and byte payloads may be mapped.</p>
<h3 id="text-payloads">Text payloads</h3>
<p>Working with text payloads is as easy as it gets in JavaScript. For example, for the content-type <code class="highlighter-rouge">application/json</code>
structured data may be processed like this:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">value</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">contentType</span> <span class="o">===</span> <span class="s1">'application/json'</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">parsedJson</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="nx">value</span> <span class="o">=</span> <span class="nx">parsedJson</span><span class="p">.</span><span class="nx">number1</span> <span class="o">+</span> <span class="nx">parsedJson</span><span class="p">[</span><span class="s1">'sub-field'</span><span class="p">];</span> <span class="c1">// remember to access JSON keys with dashes in a JS special way</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// a script may decide to not map other content-types than application/json</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// proceed ...</span>
</code></pre></div></div>
<h3 id="byte-payloads">Byte payloads</h3>
<p>Working with byte payloads is also possible but does require a little bit of knowledge about JavaScipt’s
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray">TypedArrays</a> and
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView">DataView</a>.</p>
<p>What you get in the mapping scripts is a <code class="highlighter-rouge">bytePayload</code> of type <code class="highlighter-rouge">ArrayBuffer</code> which lets you work on the bytes in different ways:</p>
<h4 id="typed-arrays">Typed Arrays</h4>
<blockquote>
<p>A TypedArray [is] a view into an ArrayBuffer where every item has the same size and type.<br /> <a href="https://hacks.mozilla.org/2017/01/typedarray-or-dataview-understanding-byte-order/">source</a></p>
</blockquote>
<p>With TypedArrays you can simply wrap the <code class="highlighter-rouge">bytePayload</code> <code class="highlighter-rouge">ArrayBuffer</code> and work on all the items e.g. as unsigned 8-bit integers:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">bytes</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">bytePayload</span><span class="p">);</span>
<span class="nx">bytes</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="c1">// access the first byte</span>
<span class="nx">bytes</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="c1">// access the second byte</span>
</code></pre></div></div>
<h4 id="dataviews">DataViews</h4>
<blockquote>
<p>The DataView [is] another view into an ArrayBuffer, but one which allows items of different size and type in the ArrayBuffer.<br /> <a href="https://hacks.mozilla.org/2017/01/typedarray-or-dataview-understanding-byte-order/">source</a></p>
</blockquote>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">view</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">DataView</span><span class="p">(</span><span class="nx">bytePayload</span><span class="p">);</span>
<span class="nx">view</span><span class="p">.</span><span class="nx">getInt8</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// access a 8-bit signed integer (byte) on offset=0</span>
<span class="nx">view</span><span class="p">.</span><span class="nx">getUint16</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// access a 16-bit unsigned integer (usigned short) on offset=1</span>
</code></pre></div></div>
<p>DataViews also allow to <code class="highlighter-rouge">set</code> bytes to an underlying ArrayBuffer conveniently.</p>
<h4 id="bytebufferjs">ByteBuffer.js</h4>
<p>Alternatively, Ditto’s JavaScript transformation may be loaded with the <a href="#helper-libraries">above mentioned</a> libraries, e.g. “bytebuffer.js”.<br />
With <code class="highlighter-rouge">ByteBuffer</code>, the content of an <code class="highlighter-rouge">ArrayBuffer</code> can be accessed in a buffered way:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">byteBuf</span> <span class="o">=</span> <span class="nx">Ditto</span><span class="p">.</span><span class="nx">asByteBuffer</span><span class="p">(</span><span class="nx">bytePayload</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">numberFromBytes</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">byteBuf</span><span class="p">.</span><span class="nx">toHex</span><span class="p">(),</span> <span class="mi">16</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">base64encoded</span> <span class="o">=</span> <span class="nx">byteBuf</span><span class="p">.</span><span class="nx">toBase64</span><span class="p">();</span>
<span class="kd">let</span> <span class="nx">buf</span> <span class="o">=</span> <span class="nx">dcodeIO</span><span class="p">.</span><span class="nx">ByteBuffer</span><span class="p">.</span><span class="nx">fromBase64</span><span class="p">(</span><span class="nx">base64encoded</span><span class="p">);</span>
<span class="nx">buf</span><span class="p">.</span><span class="nx">readInt</span><span class="p">();</span> <span class="c1">// read a 32bit signed integer + advances the offset in the buffer</span>
<span class="nx">buf</span><span class="p">.</span><span class="nx">readUTF8String</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="c1">// read 4 characters of UTF-8 encoded string + advances the offset in the buffer</span>
<span class="nx">buf</span><span class="p">.</span><span class="nx">remaining</span><span class="p">();</span> <span class="c1">// gets the number of remaining readable bytes in the buffer</span>
</code></pre></div></div>
<p>Check the <a href="https://github.com/dcodeIO/bytebuffer.js/wiki/API">ByteBuffer API documentation</a> to find out what is possible with that helper.</p>
<h2 id="javascript-examples">JavaScript Examples</h2>
<h3 id="text-payload-example">Text payload example</h3>
<p>Let’s assume your device sends telemetry data via <a href="https://www.eclipse.org/hono/">Eclipse Hono’s</a> MQTT adapter into the cloud.
And that an example payload of your device is:</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">"temp"</span><span class="p">:</span><span class="w"> </span><span class="s2">"23.42 °C"</span><span class="p">,</span><span class="w">
</span><span class="s2">"hum"</span><span class="p">:</span><span class="w"> </span><span class="mi">78</span><span class="p">,</span><span class="w">
</span><span class="s2">"pres"</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="mi">760</span><span class="p">,</span><span class="w">
</span><span class="s2">"unit"</span><span class="p">:</span><span class="w"> </span><span class="s2">"mmHg"</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>We want to map a single message of this device containing updates for all 3 values to a Thing in the following structure:</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">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"the.namespace:the-thing-id"</span><span class="p">,</span><span class="w">
</span><span class="s2">"policyId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"the.namespace:the-policy-id"</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.42</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="mi">760</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="mi">78</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>Therefore, we define following <code class="highlighter-rouge">incoming</code> mapping function:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><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="k">if</span> <span class="p">(</span><span class="nx">contentType</span> <span class="o">!==</span> <span class="s1">'application/json'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span> <span class="c1">// only handle messages with content-type application/json</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">jsonData</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="kd">let</span> <span class="nx">value</span> <span class="o">=</span> <span class="p">{</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">jsonData</span><span class="p">.</span><span class="nx">temp</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="c1">// omit the unit</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">jsonData</span><span class="p">.</span><span class="nx">pres</span><span class="p">.</span><span class="nx">value</span>
<span class="p"