http://git-wip-us.apache.org/repos/asf/incubator-edgent-website/blob/9b42cd73/content/docs/power-of-edgent.html ---------------------------------------------------------------------- diff --git a/content/docs/power-of-edgent.html b/content/docs/power-of-edgent.html new file mode 100644 index 0000000..f954085 --- /dev/null +++ b/content/docs/power-of-edgent.html @@ -0,0 +1,1092 @@ +<!DOCTYPE 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=" "> +<title>The Power of Apache Edgent | Apache Edgent Documentation</title> +<link rel="stylesheet" type="text/css" href="../css/syntax.css"> +<link rel="stylesheet" type="text/css" href="../css/font-awesome.min.css"> +<!--<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css">--> +<link rel="stylesheet" type="text/css" href="../css/modern-business.css"> +<link rel="stylesheet" type="text/css" href="../css/lavish-bootstrap.css"> +<link rel="stylesheet" type="text/css" href="../css/customstyles.css"> +<link rel="stylesheet" type="text/css" href="../css/theme-blue.css"> +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> +<script src="../js/jquery.navgoco.min.js"></script> +<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js"></script> +<script src="../js/toc.js"></script> +<script src="../js/customscripts.js"></script> +<link rel="shortcut icon" href="../common_images/favicon.ico" type="image/x-icon"> +<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> +<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> +<!--[if lt IE 9]> +<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> +<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> +<![endif]--> + + + + + + + + + +<script> + $(function () { + $('[data-toggle="tooltip"]').tooltip() + }) +</script> + + + + </head> + +<body> + + <!-- Navigation --> +<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> + <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="fa fa-home fa-lg navbar-brand" href="../docs/home.html"> <span class="projectTitle"> Apache Edgent Documentation</span></a> + + </div> + <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> + <ul class="nav navbar-nav navbar-right"> + <!-- entries without 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">GitHub Repos<b class="caret"></b></a> + <ul class="dropdown-menu"> + + + + <li><a href="https://github.com/apache/incubator-edgent" target="_blank">Source code</a></li> + + + + + + <li><a href="https://github.com/apache/incubator-edgent-website" target="_blank">Website/Documentation</a></li> + + + + + + </ul> + </li> + + + + + <li class="dropdown"> + + + + <a href="#" class="dropdown-toggle" data-toggle="dropdown">Javadoc<b class="caret"></b></a> + <ul class="dropdown-menu"> + + + + <li><a href="..\javadoc\latest">latest</a></li> + + + + + + <li><a href="..\javadoc\r1.1.0">1.1.0</a></li> + + + + + + <li><a href="..\javadoc\r1.0.0">1.0.0</a></li> + + + + + + <li><a href="..\javadoc\r0.4.0">0.4.0</a></li> + + + + + + </ul> + </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">Edgent Resources<b class="caret"></b></a> + <ul class="dropdown-menu"> + + + + <li><a href="downloads">Download</a></li> + + + + + + <li><a href="faq">FAQ</a></li> + + + + + + <li class="dropdownActive"><a href="/">edgent.apache.org</a></li> + + + + + + </ul> + </li> + + + + + <!-- special insertion --> + + + <!-- Send feedback function --> +<script> +function SendLinkByMail(href) { +var subject= "Apache Edgent Documentation feedback"; +var body = "I have some feedback about the The Power of Apache Edgent page: "; +body += window.location.href; +body += ""; +var uri = "mailto:?subject="; +uri += encodeURIComponent(subject); +uri += "&body="; +uri += encodeURIComponent(body); +window.location.href = uri; +} +</script> + +<li><a href="mailto:d...@edgent.incubator.apache.org" target="_blank"><i class="fa fa-envelope-o"></i> Feedback</a></li> + + + <!--uncomment this block if you want simple search instead of algolia--> + <li> + <!--start search--> + <div id="search-demo-container"> + <input type="text" id="search-input" placeholder="search..."> + <ul id="results-container"></ul> + </div> + <script src="../js/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="The Power of Apache Edgent">{title}</a></li>', + noResultsText: 'No results found.', + limit: 10, + fuzzy: true, + }) + </script> + <!--end search--> + </li> + + + </div> + <!-- /.container --> +</nav> + + + + <!-- Page Content --> + <div class="container"> + <div class="col-lg-12"> </div> + + +<!-- Content Row --> +<div class="row"> + <!-- Sidebar Column --> + <div class="col-md-3"> + + <script> + + $(document).ready(function() { + // Initialize navgoco with default options + $("#mysidebar").navgoco({ + caretHtml: '', + accordion: true, + openClass: 'active', // open + save: true, + cookie: { + name: 'navgoco', + expires: false, + path: '/' + }, + slide: { + duration: 400, + easing: 'swing' + } + }); + + $("#collapseAll").click(function(e) { + e.preventDefault(); + $("#mysidebar").navgoco('toggle', false); + }); + + $("#expandAll").click(function(e) { + e.preventDefault(); + $("#mysidebar").navgoco('toggle', true); + }); + + }); + + </script> + + + + + + + + + + + + + <ul id="mysidebar" class="nav"> + + <span class="siteTagline">Edgent</span> + <span class="versionTagline">Version 1.1.0-incubating</span> + + + + + + + <li><a href="#">Overview</a> + <ul> + + + + + <li><a href="../docs/edgent_index.html">Introduction</a></li> + + + + + + + + + + <li><a href="../docs/home.html">Edgent Overview</a></li> + + + + + + + + + + <li class="active"><a href="../docs/power-of-edgent.html">The Power of Edgent</a></li> + + + + + + + + + + <li><a href="../docs/faq.html">FAQ</a></li> + + + + + + + </ul> + + + + <li><a href="#">Get Started</a> + <ul> + + + + + <li><a href="../docs/downloads.html">Downloads</a></li> + + + + + + + + + + <li><a href="../docs/edgent-getting-started.html">Getting Started Guide</a></li> + + + + + + + + + + <li><a href="../docs/edgent-getting-started-samples.html">Quickstart with Edgent Samples</a></li> + + + + + + + + + + <li><a href="../docs/application-development.html">Understanding App Development</a></li> + + + + + + + + + + <li><a href="../docs/quickstart.html">Quickstart IBM Watson IoT Platform</a></li> + + + + + + + + + + <li><a href="../docs/streaming-concepts.html">Streaming concepts</a></li> + + + + + + + + + + <li><a href="../docs/common-edgent-operations.html">Common operations</a></li> + + + + + + + </ul> + + + + <li><a href="#">Edgent Cookbook</a> + <ul> + + + + + <li><a href="../recipes/recipe_hello_edgent.html">Hello Edgent!</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_source_function.html">Writing a source function</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_value_out_of_range.html">Detecting a sensor value out of expected range</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_different_processing_against_stream.html">Applying different processing against a single stream</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_combining_streams_processing_results.html">Splitting a stream to apply different processing and combining the results into a single stream</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_external_filter_range.html">Using an external configuration file for filter ranges</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_adaptable_filter_range.html">Changing a filter's range</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_adaptable_polling_source.html">Changing a polled source stream's period</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_adaptable_deadtime_filter.html">Using an adaptable deadtime filter</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_dynamic_analytic_control.html">Dynamically enabling analytic flows</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_parallel_analytics.html">How can I run analytics on several tuples in parallel?</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_concurrent_analytics.html">How can I run several analytics on a tuple concurrently?</a></li> + + + + + + + + + + <li><a href="../recipes/recipe_writing_a_connector.html">How do I write a connector?</a></li> + + + + + + + </ul> + + + + <li><a href="#">Using the Console</a> + <ul> + + + + + <li><a href="../docs/console.html">Using the console</a></li> + + + + + + + </ul> + + + + <li><a href="#">Get Involved</a> + <ul> + + + + + <li><a href="../docs/community.html">How to participate</a></li> + + + + + + + + + + <li><a href="../docs/committers.html">Committers</a></li> + + + + + + + </ul> + + + + + + <!-- if you aren't using the accordion, uncomment this block: + + <p class="external"> + <a href="#" id="collapseAll">Collapse All</a> | <a href="#" id="expandAll">Expand All</a> + </p> + --> + <br/> + </li> + </ul> + <div class="row"> + <div class="col-md-12"> + +<!-- 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> + </div> + </div> + + <!-- this highlights the active parent class in the navgoco 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> + + + <!-- Content Column --> + <div class="col-md-9"> + + <div class="post-header"> + <h1 class="post-title-main">The Power of Apache Edgent</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> + + + + + <a target="_blank" href="https://github.com/apache/incubator-edgent-website/blob/master/site/docs/power-of-edgent.md" class="btn btn-default githubEditButton" role="button"><i class="fa fa-github fa-lg"></i> Edit me</a> + + <p>Edgent is designed to accelerate your development of event driven flow-graph +style analytic applications running on edge devices. This is achieved by +Edgent's combination of API, connectors, basic analytics, utilities, and openness!</p> + +<p>Let's have some fun with a shallow but broad view into what you +can do in a few of lines of code... an introduction to Edgent's capabilities via +a series of terse code fragments.</p> + +<p>See the <a href="edgent-getting-started">Getting Started Guide</a> for a step by step introduction, +and information about full samples and recipies.</p> + +<p>Let's start with a complete application that periodically samples a sensor +and publishes its values to an Enterprise IoT Hub in less than 10 lines of code</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ImpressiveEdgentExample</span> <span class="o">{</span> + <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="n">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span> + <span class="n">DirectProvider</span> <span class="n">provider</span> <span class="o">=</span> <span class="k">new</span> <span class="n">DirectProvider</span><span class="o">();</span> + <span class="n">Topology</span> <span class="n">top</span> <span class="o">=</span> <span class="n">provider</span><span class="o">.</span><span class="na">newTopology</span><span class="o">();</span> + + <span class="n">IotDevice</span> <span class="n">iotConnector</span> <span class="o">=</span> <span class="n">IotpDevice</span><span class="o">.</span><span class="na">quickstart</span><span class="o">(</span><span class="n">top</span><span class="o">,</span> <span class="s">"edgent-intro-device-2"</span><span class="o">);</span> + <span class="c1">// open https://quickstart.internetofthings.ibmcloud.com/#/device/edgent-intro-device-2</span> + + <span class="c1">// ingest -> transform -> publish</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">top</span><span class="o">.</span><span class="na">poll</span><span class="o">(</span><span class="k">new</span> <span class="n">SimulatedTemperatureSensor</span><span class="o">(),</span> <span class="mi">1</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">JsonFunctions</span><span class="o">.</span><span class="na">valueOfNumber</span><span class="o">(</span><span class="s">"temp"</span><span class="o">));</span> + <span class="n">iotConnector</span><span class="o">.</span><span class="na">events</span><span class="o">(</span><span class="n">events</span><span class="o">,</span> <span class="s">"readingEvents"</span><span class="o">,</span> <span class="n">QoS</span><span class="o">.</span><span class="na">FIRE_AND_FORGET</span><span class="o">);</span> + + <span class="n">provider</span><span class="o">.</span><span class="na">submit</span><span class="o">(</span><span class="n">top</span><span class="o">);</span> + <span class="o">}</span> +<span class="o">}</span> +</code></pre></div> +<p>Ok, that was 11 lines and it omitted the imports, but there are only 7 lines in main()!</p> + +<p>That leveraged the <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/iotp/IotpDevice.html">IotpDevice</a> +connector to the +IBM Watson IoT Platform and the platform's Quickstart feature. +The value of its Quickstart feature is no account or device +preregistration and the ability to open a browser to see the +data being published. Great to quickly get started.</p> + +<p>Hopefully that had enough of a wow factor to encourage you +to keep reading!</p> + +<h3 id="connectors-ingest-and-sink">Connectors, Ingest and Sink</h3> + +<p>Edgent Applications need to create streams of data from external entities, +termed ingest, and sink streams of data to external entities.<br> +There are primitives for those operations and a collection of +connectors to common external entities, +more Connectors contributions are welcome!</p> + +<p>Connectors are just code that make it easier for an Edgent application +to integrate with an external entity. They use Edgent ingest primitives +like (<code>Topology.poll()</code>, <code>Topology.events()</code>, etc), and <code>TStream.sink()</code> +like any other Edgent code. A connector may provide <code>Supplier</code> and +<code>Consumer</code> functions, for ingest and sink respectively, that an +application can use directly with the Edgent API.</p> + +<p>OK... fewer words, more code!</p> + +<p>You've already seen publishing using the <code>IotpDevice</code> connector.</p> + +<p>Want to receive <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/iot/IotDevice.html">IotDevice</a> device commands? Simple!</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">cmds</span> <span class="o">=</span> <span class="n">iotConnector</span><span class="o">.</span><span class="na">commands</span><span class="o">();</span> + <span class="n">cmds</span><span class="o">.</span><span class="na">sink</span><span class="o">(</span><span class="n">cmd</span> <span class="o">-></span> <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"I should handle received cmd: "</span><span class="o">+</span><span class="n">cmd</span><span class="o">));</span> + + <span class="n">or</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">xzyCmds</span> <span class="o">=</span> <span class="n">iotConnector</span><span class="o">.</span><span class="na">command</span><span class="o">(</span><span class="s">"xyzCmds"</span><span class="o">);</span> +</code></pre></div> +<p>There's an <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/iot/IotGateway.html">IotGateway</a> device model too.</p> + +<p>Don't want no stinkin <code>IotDevice</code> model and just +want to pub/sub to an MQTT server? No worries! Use the <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/mqtt/MqttStreams.html">MqttStreams</a> connector</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="c1">//IotDevice iotConnector = IotpDevice.quickstart(top, "edgent-intro-device-2");</span> + <span class="n">MqttStreams</span> <span class="n">iotConnector</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MqttStreams</span><span class="o">(</span><span class="n">top</span><span class="o">,</span> <span class="s">"ssl://myMqttServer:8883"</span><span class="o">,</span> <span class="s">"my-device-client-id"</span><span class="o">);</span> + + <span class="o">...</span> + + <span class="c1">//iotConnector.events(events, "readingEvents", QoS.FIRE_AND_FORGET);</span> + <span class="n">iotConnector</span><span class="o">.</span><span class="na">publish</span><span class="o">(</span><span class="n">events</span><span class="o">,</span> <span class="s">"readingEvents"</span><span class="o">,</span> <span class="n">QoS</span><span class="o">.</span><span class="na">FIRE_AND_FORGET</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span> + + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">xyzTopicMsgs</span> <span class="o">=</span> <span class="n">iotConnector</span><span class="o">.</span><span class="na">subscribe</span><span class="o">(</span><span class="s">"xyzTopic"</span><span class="o">);</span> +</code></pre></div> +<p>Want to connect to Kafka? Use the <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/kafka/KafkaProducer.html">KafkaProducer</a> and <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/kafka/KafkaConsumer.html">KafkaConsumer</a> connectors with similar ease.</p> + +<p>There's a <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/jdbc/JdbcStreams.html">JdbcStreams</a> connector too.</p> + +<p>Want to sink a <code>TStream</code> to rolling text files? Use the <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/file/FileStreams.html">FileStreams</a> connector.</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="k">new</span> <span class="nf">File</span><span class="p">(</span><span class="s">"/tmp/MY-DEMO-FILES"</span><span class="o">).</span><span class="na">mkdir</span><span class="o">();</span> + <span class="n">FileStreams</span><span class="o">.</span><span class="na">textFileWriter</span><span class="o">(</span><span class="n">events</span><span class="o">.</span><span class="na">asString</span><span class="o">(),</span> <span class="o">()</span> <span class="o">-></span> <span class="s">"/tmp/MY-DEMO-FILES/READINGS"</span><span class="o">);</span> + + <span class="c1">// tail -f /tmp/MY-DEMO-FILES/.READINGS</span> +</code></pre></div> +<p>Or watch for, ingest and process text files? <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/csv/Csv.html">Csv</a> can be useful if your input lines of comma separated values</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">String</span> <span class="n">watchedDir</span> <span class="o">=</span> <span class="s">"/some/directory/path"</span><span class="o">;</span> + <span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">csvFieldNames</span> <span class="o">=</span> <span class="o">...</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">pathnames</span> <span class="o">=</span> <span class="n">FileStreams</span><span class="o">.</span><span class="na">directoryWatcher</span><span class="o">(</span><span class="n">top</span><span class="o">,</span> <span class="o">()</span> <span class="o">-></span> <span class="n">watchedDir</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">lines</span> <span class="o">=</span> <span class="n">FileStreams</span><span class="o">.</span><span class="na">textFileReader</span><span class="o">(</span><span class="n">pathnames</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">parsedLines</span> <span class="o">=</span> <span class="n">lines</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">line</span> <span class="o">-></span> <span class="n">Csv</span><span class="o">.</span><span class="na">toJson</span><span class="o">(</span><span class="n">Csv</span><span class="o">.</span><span class="na">parseCsv</span><span class="o">(</span><span class="n">line</span><span class="o">),</span> <span class="n">csvFieldNames</span><span class="o">));</span> +</code></pre></div> +<p>Want to sink to a command's stdin? Use the <a href="/javadoc/latest/index.html?org/apache/edgent/connectors/command/CommandStreams.html">CommandStreams</a> connector</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">MyEvent</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> <span class="o">...</span> + <span class="n">ProcessBuilder</span> <span class="n">cmd</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ProcessBuilder</span><span class="o">(</span><span class="s">"cat"</span><span class="o">).</span><span class="na">redirectOutput</span><span class="o">(</span><span class="k">new</span> <span class="n">File</span><span class="o">(</span><span class="s">"/dev/stdout"</span><span class="o">));</span> + <span class="n">CommandStreams</span><span class="o">.</span><span class="na">sink</span><span class="o">(</span><span class="n">events</span><span class="o">.</span><span class="na">asString</span><span class="o">(),</span> <span class="n">cmd</span><span class="o">);</span> +</code></pre></div> +<p>Or ingest a command's stdout/err?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">ProcessBuilder</span> <span class="n">cmd</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ProcessBuilder</span><span class="o">(</span><span class="s">"date"</span><span class="o">,</span> <span class="s">"-R"</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">>></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">CommandStreams</span><span class="o">.</span><span class="na">periodicSource</span><span class="o">(</span><span class="n">top</span><span class="o">,</span> <span class="n">cmd</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">);</span> + + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> + <span class="n">readings</span> + <span class="o">.</span><span class="na">flatMap</span><span class="o">(</span><span class="n">list</span> <span class="o">-></span> <span class="n">list</span><span class="o">)</span> + <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">JsonFunctions</span><span class="o">.</span><span class="na">valueOfString</span><span class="o">(</span><span class="s">"date"</span><span class="o">));</span> + + <span class="c1">// also note TStream support for a fluent programming style</span> + <span class="c1">// and use of TStream.flatmap() to transform in input list to</span> + <span class="c1">// an output list and then add each output list item as a separate</span> + <span class="c1">// tuple to the output stream</span> +</code></pre></div> +<p>Want to sink to a log via SLF4J or another logging system? Just do it!</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="kn">import</span> <span class="nn">org.slf4j.Logger</span><span class="o">;</span> + <span class="kn">import</span> <span class="nn">org.slf4j.LoggerFactory</span><span class="o">;</span> + <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">MyClass</span><span class="o">.</span><span class="na">class</span><span class="o">);</span> + + <span class="n">readings</span><span class="o">.</span><span class="na">sink</span><span class="o">(</span><span class="n">reading</span> <span class="o">-></span> <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"reading: {}"</span><span class="o">,</span> <span class="n">reading</span><span class="o">));</span> +</code></pre></div> +<p>Want to publish to Elasticsearch? See <a href="https://issues.apache.org/jira/browse/EDGENT-368">EDGENT-368</a> for a full code example.</p> + +<h3 id="more-on-ingest">More on Ingest</h3> + +<p>You've seen how to periodically poll a function to get a some data.<br> +That's just one of the methods defined in <a href="/javadoc/latest/index.html?org/apache/edgent/topology/Topology.html">Topology</a> for ingesting data - for creating source streams.</p> + +<p>Also note that the tuples (a.k.a. events, data, objects) in a <a href="/javadoc/latest/index.html?org/apache/edgent/topology/TStream.html">TStream</a> can be any type. There's no special Edgent tuple type hierarchy.</p> + +<p>Want readings from multiple sensors in a single stream tuple?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">SimulatedTemperatureSensor</span> <span class="n">tempSensor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimulatedTemperatureSensor</span><span class="o">();</span> + <span class="n">SimpleSimulatedSensor</span> <span class="n">pressureSensor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleSimulatedSensor</span><span class="o">();</span> + + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> <span class="n">top</span><span class="o">.</span><span class="na">poll</span><span class="o">(</span> <span class="o">()</span> <span class="o">-></span> <span class="o">{</span> + <span class="n">JsonObject</span> <span class="n">jo</span> <span class="o">=</span> <span class="k">new</span> <span class="n">JsonObject</span><span class="o">();</span> + <span class="n">jo</span><span class="o">.</span><span class="na">addProperty</span><span class="o">(</span><span class="s">"temp"</span><span class="o">,</span> <span class="n">tempSensor</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> + <span class="n">jo</span><span class="o">.</span><span class="na">addProperty</span><span class="o">(</span><span class="s">"pressure"</span><span class="o">,</span> <span class="n">pressureSensor</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> + <span class="k">return</span> <span class="n">jo</span><span class="o">;</span> + <span class="o">},</span> <span class="mi">1</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">);</span> +</code></pre></div> +<p>Want to define a class or use an existing one for a tuple?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="kd">public</span> <span class="kd">class</span> <span class="nc">SensorReading</span> <span class="o">{</span> + <span class="kt">double</span> <span class="n">temp</span><span class="o">;</span> + <span class="kt">double</span> <span class="n">pressure</span><span class="o">;</span> + <span class="kd">public</span> <span class="n">SensorReading</span><span class="o">(</span><span class="kt">double</span> <span class="n">temp</span><span class="o">,</span> <span class="kt">double</span> <span class="n">pressure</span><span class="o">)</span> <span class="o">{</span> + <span class="k">this</span><span class="o">.</span><span class="na">temp</span> <span class="o">=</span> <span class="n">temp</span><span class="o">;</span> + <span class="k">this</span><span class="o">.</span><span class="na">pressure</span> <span class="o">=</span> <span class="n">pressure</span><span class="o">;</span> + <span class="o">}</span> + <span class="o">}</span> + + <span class="n">SimulatedTemperatureSensor</span> <span class="n">tempSensor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimulatedTemperatureSensor</span><span class="o">();</span> + <span class="n">SimpleSimulatedSensor</span> <span class="n">pressureSensor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SimpleSimulatedSensor</span><span class="o">();</span> + + <span class="n">TStream</span><span class="o"><</span><span class="n">SensorReading</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">top</span><span class="o">.</span><span class="na">poll</span><span class="o">(</span> + <span class="o">()</span> <span class="o">-></span> <span class="k">new</span> <span class="n">Reading</span><span class="o">(</span><span class="n">tempSensor</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">pressureSensor</span><span class="o">.</span><span class="na">get</span><span class="o">()),</span> + <span class="mi">1</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">);</span> +</code></pre></div> +<h4 id="simulated-sensors">Simulated Sensors</h4> + +<p>Edgent provides some simple simulated sensors that can be helpful to get going. +You've already seen <code>SimulatedTemperatureSensor</code> and +<code>SimpleSimulatedSensor</code> - included in the Edgent Samples source release bundle. +There are additional ones in the same Java package.</p> + +<h4 id="sensor-library">Sensor library</h4> + +<p>Wondering if Edgent has a sensor library? It does not +because there seems to be little value in supplying one.</p> + +<p>Using Edgent's stream ingest primitives (e.g., <code>Topology.poll(), Topology.events()</code>, +etc) it's trivial for you to call the sensor's APIs to get +readings and compose them into a stream data object of your +choosing to be added a <code>TStream</code>.</p> + +<h3 id="filtering">Filtering</h3> + +<p>Let's get back to our original <code>ImpressiveEdgentExample</code> +and explore making it smarter - push more analytics out +to the edge!</p> + +<p>Want to only publish readings with values less than 5 or more than 30?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="c1">// add this after the poll()</span> + <span class="n">readings</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">tuple</span> <span class="o">-></span> <span class="n">tuple</span> <span class="o"><</span> <span class="mi">5</span><span class="n">d</span> <span class="o">||</span> <span class="n">tuple</span> <span class="o">></span> <span class="mi">30</span><span class="n">d</span><span class="o">);</span> +</code></pre></div> +<p>Your filter predicate function can do what ever it needs to do!</p> + +<p>Or use the <a href="/javadoc/latest/index.html?org/apache/edgent/analytics/sensors/Range.html">Range</a> utility</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">Range</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">range</span> <span class="o">=</span> <span class="n">Ranges</span><span class="o">.</span><span class="na">open</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="mi">30</span><span class="o">);</span> + <span class="n">readings</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">reading</span> <span class="o">-></span> <span class="o">!</span><span class="n">range</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="n">reading</span><span class="o">));</span> +</code></pre></div> +<p>Or</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">readings</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">Ranges</span><span class="o">.</span><span class="na">outsideOf</span><span class="o">(</span><span class="n">Ranges</span><span class="o">.</span><span class="na">open</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="mi">30</span><span class="o">)));</span> +</code></pre></div> +<p>That alone isn't a very compelling use of Range but consider +a larger context. +A Range has a simple String representation (e.g., the above is <code>"(5d,30d)"</code>) +so that value could be read from an application configuration file +on startup, or received from a device command to create a +dynamically configurable application.</p> + +<p><a href="/javadoc/latest/index.html?org/apache/edgent/analytics/sensors/Filters.html">Filters.deadband</a> +offers a more sophisticated filter. +There's a nice graphic depection of the filter behavior in the method's javadoc.</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">Range</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">range</span> <span class="o">=</span> <span class="n">Ranges</span><span class="o">.</span><span class="na">open</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="mi">30</span><span class="o">);</span> + <span class="n">readings</span> <span class="o">=</span> <span class="n">Filters</span><span class="o">.</span><span class="na">deadband</span><span class="o">(</span><span class="n">readings</span><span class="o">,</span> <span class="n">reading</span> <span class="o">-></span> <span class="n">reading</span><span class="o">,</span> <span class="n">range</span><span class="o">);</span> +</code></pre></div> +<p>There's also a <a href="/javadoc/latest/index.html?org/apache/edgent/analytics/sensors/Filters.html">Filters.deadtime</a> filter can can come in handy.</p> + +<h3 id="split">Split</h3> + +<p>Want to split a TStream into multiple TStreams - e.g., to handle +different categories of tuples differently? <code>TStream.split()</code> +is essentially an efficient group of multiple filters.</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">List</span><span class="o"><</span><span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">>></span> <span class="n">twoStreams</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">d</span> <span class="o">-></span> <span class="n">range</span><span class="o">.</span><span class="na">test</span><span class="o">(</span><span class="n">d</span><span class="o">)</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="mi">1</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">inRange</span> <span class="o">=</span> <span class="n">twoStreams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">outOfRange</span> <span class="o">=</span> <span class="n">twoStreams</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span> +</code></pre></div> +<p>Your split function can yield as many output streams as you need. +There's also a form of <code>split()</code> that works with <code>Enum</code> identifiers.</p> + +<h3 id="transforms">Transforms</h3> + +<p>Want to convert a value that's in Centigrade to Farenheit?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">readings</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">reading</span> <span class="o">-></span> <span class="o">(</span><span class="n">reading</span> <span class="o">*</span> <span class="mf">1.8</span><span class="o">)</span> <span class="o">+</span> <span class="mi">32</span><span class="o">);</span> +</code></pre></div> +<p>Your map function can do what ever it needs to do! +E.g., a tuple could be a video image frame and the map +function could generate face detection events.</p> + +<p>We've already seen converting a numeric value to a JsonObject using <a href="/javadoc/latest/index.html?org/apache/edgent/topology/json/JsonFunctions.html">JsonFunctions</a></p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">JsonFunctions</span><span class="o">.</span><span class="na">valueOfNumber</span><span class="o">(</span><span class="s">"temp"</span><span class="o">));</span> +</code></pre></div> +<p>What about scoring against a model? Edgent doesn't have +anything special for that at least at this time.<br> +But it's easy to integrate the use of some scoring model +system into an Edgent application.<br> +Imagine a package defined something like:</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="kd">public</span> <span class="kd">class</span> <span class="nc">Model</span> <span class="o">{</span> + <span class="c1">// load model from a File</span> + <span class="kd">public</span> <span class="n">Model</span><span class="o">(</span><span class="n">File</span> <span class="n">f</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">};</span> + <span class="c1">// score String s against the model</span> + <span class="c1">// return a confidence score between 0.0 and 1.0</span> + <span class="kd">public</span> <span class="n">Double</span> <span class="n">score</span><span class="o">(</span><span class="n">String</span> <span class="n">s</span><span class="o">);</span> + <span class="o">}</span> +</code></pre></div> +<p>An Edgent application might use such a model in this manner</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="kd">final</span> <span class="n">Model</span> <span class="n">model</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Model</span><span class="o">(...);</span> + + <span class="n">TStream</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">events</span> <span class="o">=</span> <span class="o">...</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">scoredEvents</span> <span class="o">=</span> <span class="n">events</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">event</span> <span class="o">-></span> <span class="o">{</span> + <span class="n">Double</span> <span class="n">score</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="na">score</span><span class="o">(</span><span class="n">event</span><span class="o">);</span> + <span class="n">JsonObject</span> <span class="n">jo</span> <span class="o">=</span> <span class="k">new</span> <span class="n">JsonObject</span><span class="o">();</span> + <span class="n">jo</span><span class="o">.</span><span class="na">addProperty</span><span class="o">(</span><span class="s">"event"</span><span class="o">,</span> <span class="n">event</span><span class="o">);</span> + <span class="n">jo</span><span class="o">.</span><span class="na">addProperty</span><span class="o">(</span><span class="s">"score"</span><span class="o">,</span> <span class="n">score</span><span class="o">);</span> + <span class="k">return</span> <span class="n">jo</span><span class="o">;</span> + <span class="o">};</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">interestingEvents</span> <span class="o">=</span> + <span class="n">scoredEvents</span><span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">jo</span> <span class="o">-></span> <span class="n">jo</span><span class="o">.</span><span class="na">getAsJsonPrimitive</span><span class="o">.</span><span class="na">getAsDouble</span><span class="o">(</span><span class="s">"score"</span><span class="o">)</span> <span class="o">></span> <span class="mf">0.75</span><span class="o">);</span> +</code></pre></div> +<p>OK, maybe that one was a bit too large a code fragment for this introduction.</p> + +<h3 id="windowing-and-aggregation">Windowing and aggregation</h3> + +<p>Want to do signal smoothing - create a continuously aggregated average over the last 10 readings? +Here, each time a tuple is added to the window a new aggregated value computed and is added to the output stream.</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TWindow</span><span class="o"><</span><span class="n">Double</span><span class="o">,</span><span class="n">Integer</span><span class="o">></span> <span class="n">window</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="n">Functions</span><span class="o">.</span><span class="na">unpartitioned</span><span class="o">());</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">aggregate</span><span class="o">((</span><span class="n">List</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">list</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">partition</span><span class="o">)</span> <span class="o">-></span> <span class="o">{</span> + <span class="kt">double</span> <span class="n">avg</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span> + <span class="k">for</span> <span class="o">(</span><span class="n">Double</span> <span class="n">d</span> <span class="o">:</span> <span class="n">list</span><span class="o">)</span> <span class="n">avg</span> <span class="o">+=</span> <span class="n">d</span><span class="o">;</span> + <span class="k">if</span> <span class="o">(</span><span class="n">list</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="n">avg</span> <span class="o">/=</span> <span class="n">list</span><span class="o">.</span><span class="na">size</span><span class="o">();</span> + <span class="k">return</span> <span class="n">avg</span><span class="o">;</span> + <span class="o">});</span> +</code></pre></div> +<p>Want a window over the last 10 seconds instead?</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="c1">// TWindow<Double,Integer> window = readings.last(10, Functions.unpartitioned());</span> + <span class="n">TWindow</span><span class="o"><</span><span class="n">Double</span><span class="o">,</span><span class="n">Integer</span><span class="o">></span> <span class="n">window</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">,</span> <span class="n">Functions</span><span class="o">.</span><span class="na">unpartitioned</span><span class="o">());</span> + <span class="o">...</span> +</code></pre></div> +<p>Or want to do data reduction - reduce the readings to one average value every window batch? +Once the window is full, the batch of tuples is aggregated, the result is added to the output +stream and the window is cleared. The next aggregation isn't generated until the window +is full again.</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">batch</span><span class="o">((</span><span class="n">List</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">list</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">partition</span><span class="o">)</span> <span class="o">-></span> <span class="o">{</span> + <span class="kt">double</span> <span class="n">avg</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span> + <span class="k">for</span> <span class="o">(</span><span class="n">Double</span> <span class="n">d</span> <span class="o">:</span> <span class="n">list</span><span class="o">)</span> <span class="n">avg</span> <span class="o">+=</span> <span class="n">d</span><span class="o">;</span> + <span class="k">if</span> <span class="o">(</span><span class="n">list</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="n">avg</span> <span class="o">/=</span> <span class="n">list</span><span class="o">.</span><span class="na">size</span><span class="o">();</span> + <span class="k">return</span> <span class="n">avg</span><span class="o">;</span> + <span class="o">});</span> +</code></pre></div> +<p>Or use <a href="/javadoc/latest/index.html?org/apache/edgent/analytics/math3/Aggregations.html">Aggregations</a> for simple statistics</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">batch</span><span class="o">((</span><span class="n">List</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">list</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">partition</span><span class="o">)</span> <span class="o">-></span> + <span class="n">Aggregations</span><span class="o">.</span><span class="na">aggregate</span><span class="o">(</span><span class="n">list</span><span class="o">,</span> <span class="n">Statistics2</span><span class="o">.</span><span class="na">MEAN</span><span class="o">));</span> +</code></pre></div> +<p>Want to compute several basic statistics and a regression for an aggregation? Use <a href="/javadoc/latest/index.html?org/apache/edgent/analytics/math3/AggregationsN.html">AggregationsN</a></p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TWindow</span><span class="o"><</span><span class="n">Double</span><span class="o">,</span><span class="n">Integer</span><span class="o">></span> <span class="n">window</span> <span class="o">=</span> <span class="n">readings</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="n">Functions</span><span class="o">.</span><span class="na">unpartitioned</span><span class="o">());</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">ResultMap</span><span class="o">></span> <span class="n">aggResults</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">batch</span><span class="o">((</span><span class="n">List</span><span class="o"><</span><span class="n">Double</span><span class="o">></span> <span class="n">list</span><span class="o">,</span> <span class="n">Integer</span> <span class="n">partition</span><span class="o">)</span> <span class="o">-></span> + <span class="n">AggregationsN</span><span class="o">(</span><span class="n">list</span><span class="o">,</span> <span class="n">Statistic2</span><span class="o">.</span><span class="na">MIN</span><span class="o">,</span> <span class="n">Statistic2</span><span class="o">.</span><span class="na">MAX</span><span class="o">,</span> + <span class="n">Statistic2</span><span class="o">.</span><span class="na">SUM</span><span class="o">,</span> <span class="n">Statistic2</span><span class="o">.</span><span class="na">STDDEV</span><span class="o">,</span> + <span class="n">Statistic2</span><span class="o">.</span><span class="na">COUNT</span><span class="o">,</span> <span class="n">Regression2</span><span class="o">.</span><span class="na">SLOPE</span><span class="o">));</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">JsonObject</span><span class="o">></span> <span class="n">joAggResults</span> <span class="o">=</span> <span class="n">aggResults</span><span class="o">(</span><span class="n">ResultMap</span><span class="o">.</span><span class="na">toJsonObject</span><span class="o">());</span> <span class="c1">// optional</span> +</code></pre></div> +<p>There's also support for multi-variable aggregations - independent statistic +aggregations for multiple variables in a list of tuples. e.g., temperatures and +pressures variables in each tuple.</p> + +<p>If the objects in the window are a JsonObject, <a href="/javadoc/latest/index.html?org/apache/edgent/analytics/math3/json/JsonAnalytics.html">JsonAnalytics</a> can be handy.</p> + +<h3 id="misc">Misc</h3> + +<p>Want to run an expensive computation on multiple tuples in parallel?<br> +Easy with <a href="/javadoc/latest/index.html?org/apache/edgent/topology/plumbing/PlumbingStreams.html">PlumbingStreams.parallel()</a>!</p> +<div class="highlight"><pre><code class="language-java" data-lang="java"> <span class="n">TStream</span><span class="o"><</span><span class="n">SensorReading</span><span class="o">></span> <span class="n">readings</span> <span class="o">=</span> <span class="o">...</span> + <span class="c1">// 3 parallel channels - i.e., can process 3 tuples simultaneously on separate theads</span> + <span class="n">TStream</span><span class="o"><</span><span class="n">MyData</span><span class="o">></span> <span class="n">analyzed</span> <span class="o">=</span> <span class="n">PlumbingStreams</span><span class="o">.</span><span class="na">parallel</span><span class="o">(</span><span class="n">readings</span><span class="o">,</span> + <span class="mi">3</span><span class="o">,</span> <span class="n">PlumbingStreams</span><span class="o">.</span><span class="na">roundRobinSplitter</span><span class="o">(),</span> + <span class="o">(</span><span class="n">input</span><span class="o">,</span> <span class="n">channel</span><span class="o">,</span> <span class="n">output</span><span class="o">)</span> <span class="o">-></span> + <span class="n">input</span><span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">reading</span> <span class="o">-></span> <span class="n">myExpensiveComputation</span><span class="o">(</span><span class="n">reading</span><span class="o">)));</span> +</code></pre></div> +<p>See <a href="/javadoc/latest/index.html?org/apache/edgent/topology/plumbing/PlumbingStreams.html">PlumbingStreams.parallelBalanced</a> for a load balanced form that will assigns +a tuple to any idle channel.</p> + +<p>There are a variety of useful features in <a href="/javadoc/latest/index.html?org/apache/edgent/topology/plumbing/PlumbingStreams.html">PlumbingStreams</a>.</p> + +<h3 id="wrap-up">Wrap up</h3> + +<p>We touched on a lot, but not all, of Edgent. +Hopefully you're convinced that the combination of Edgent's API, connectors, etc are powerful and easy to use.</p> + +<p>See the full <a href="/javadoc/latest">Edgent APIs Javadoc</a> +and <a href="edgent-getting-started">Getting Started Guide</a> for more information including pointers to more introductory +material and samples and recipies.</p> + + +<div class="tags"> + +</div> + +<!-- + + <div id="disqus_thread"></div> + <script type="text/javascript"> + /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ + var disqus_shortname = 'idrbwjekyll'; // required: replace example with your forum shortname + + /* * * DON'T EDIT BELOW THIS LINE * * */ + (function() { + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); + })(); + </script> + <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> + --> + +</div> + + + +<footer> + <div class="row"> + <div class="col-lg-12 footer"> + + Site last + generated: Dec 15, 2017 <br/> + + </div> + </div> + <br/> + <div class="row"> + <div class="col-md-12"> + <p class="small">Apache Edgent is an effort undergoing Incubation at The Apache Software + Foundation (ASF), sponsored by the Incubator. Incubation is required of all newly accepted projects + until a further review indicates that the infrastructure, communications, and decision making process + have stabilized in a manner consistent with other successful ASF projects. While incubation status is + not necessarily a reflection of the completeness or stability of the code, it does indicate that the + project has yet to be fully endorsed by the ASF.</p> + </div> + </div> + <div class="row"> + <div class="col-md-12"> + <p class="small">Copyright © 2016 The Apache Software Foundation. Licensed under the Apache + License, Version 2.0. + Apache, the Apache Feather logo, and the Apache Incubator project logo are trademarks of The Apache + Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their + respective owners.</p> + </div> + </div> + + <div class="container"> + <div class="row"> + <div> + <img class="img-responsive center-block" src="../img/edgent_incubation.png" style="display: block; margin: auto;"alt=""> + </div> + </div> +</footer> + + </div><!-- /.row --> + + </div> <!-- /.container --> + +</body> + + +</html> +
http://git-wip-us.apache.org/repos/asf/incubator-edgent-website/blob/9b42cd73/content/docs/quickstart.html ---------------------------------------------------------------------- diff --git a/content/docs/quickstart.html b/content/docs/quickstart.html index 7ecf903..d777d74 100644 --- a/content/docs/quickstart.html +++ b/content/docs/quickstart.html @@ -160,12 +160,6 @@ - <li><a href="samples">Samples</a></li> - - - - - <li><a href="faq">FAQ</a></li> @@ -315,6 +309,26 @@ window.location.href = uri; + <li><a href="../docs/home.html">Edgent Overview</a></li> + + + + + + + + + + <li><a href="../docs/power-of-edgent.html">The Power of Edgent</a></li> + + + + + + + + + <li><a href="../docs/faq.html">FAQ</a></li> @@ -342,7 +356,37 @@ window.location.href = uri; - <li><a href="../docs/edgent-getting-started.html">Getting started guide</a></li> + <li><a href="../docs/edgent-getting-started.html">Getting Started Guide</a></li> + + + + + + + + + + <li><a href="../docs/edgent-getting-started-samples.html">Quickstart with Edgent Samples</a></li> + + + + + + + + + + <li><a href="../docs/application-development.html">Understanding App Development</a></li> + + + + + + + + + + <li class="active"><a href="../docs/quickstart.html">Quickstart IBM Watson IoT Platform</a></li> @@ -510,33 +554,6 @@ window.location.href = uri; - <li><a href="#">Sample Programs</a> - <ul> - - - - - <li><a href="../docs/samples.html">Samples</a></li> - - - - - - - - - - <li class="active"><a href="../docs/quickstart.html">Quickstart IBM Watson IoT Platform</a></li> - - - - - - - </ul> - - - <li><a href="#">Using the Console</a> <ul> @@ -738,7 +755,7 @@ and Edgent provides a <a href="/javadoc/latest/index.html?org/apache/edgent/conn <div class="col-lg-12 footer"> Site last - generated: May 15, 2017 <br/> + generated: Dec 15, 2017 <br/> </div> </div>