You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@edgent.apache.org by wc...@apache.org on 2016/04/05 21:37:38 UTC

[14/23] incubator-quarks-website git commit: [QUARKS-107] new Range recipes

[QUARKS-107] new Range recipes


Project: http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/commit/647a2ed5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/tree/647a2ed5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/diff/647a2ed5

Branch: refs/heads/master
Commit: 647a2ed5bd732c5b2a312711e109432fdf7c4171
Parents: 113d149
Author: Dale LaBossiere <dl...@us.ibm.com>
Authored: Tue Apr 5 14:40:02 2016 -0400
Committer: Dale LaBossiere <dl...@us.ibm.com>
Committed: Tue Apr 5 14:40:02 2016 -0400

----------------------------------------------------------------------
 site/_data/mydoc/mydoc_sidebar.yml            |  16 +++
 site/recipes/recipe_adaptable_filter_range.md | 125 +++++++++++++++++++++
 site/recipes/recipe_external_filter_range.md  | 121 ++++++++++++++++++++
 3 files changed, 262 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/647a2ed5/site/_data/mydoc/mydoc_sidebar.yml
----------------------------------------------------------------------
diff --git a/site/_data/mydoc/mydoc_sidebar.yml b/site/_data/mydoc/mydoc_sidebar.yml
index cf5b0d4..c8da797 100644
--- a/site/_data/mydoc/mydoc_sidebar.yml
+++ b/site/_data/mydoc/mydoc_sidebar.yml
@@ -122,6 +122,22 @@ entries:
       version: all
       output: web, pdf
 
+    - title: Recipe 6. Using an External Configuration File for Filter Ranges
+      url: /recipes/recipe_external_filter_range.html
+      audience: writers, designers
+      platform: all
+      product: all
+      version: all
+      output: web, pdf
+
+    - title: Recipe 7. Adaptable Filter Behavior
+      url: /recipes/recipe_adaptable_filter_range.html
+      audience: writers, designers
+      platform: all
+      product: all
+      version: all
+      output: web, pdf
+
   - title: Sample Programs
     audience: writers, designers
     platform: all

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/647a2ed5/site/recipes/recipe_adaptable_filter_range.md
----------------------------------------------------------------------
diff --git a/site/recipes/recipe_adaptable_filter_range.md b/site/recipes/recipe_adaptable_filter_range.md
new file mode 100644
index 0000000..036d1d3
--- /dev/null
+++ b/site/recipes/recipe_adaptable_filter_range.md
@@ -0,0 +1,125 @@
+---
+title: Recipe: Adaptable filter behavior.
+---
+
+The [Detecting a Sensor Value Out of Range](recipe_value_out_of_range.html) recipe introduced the basics of filtering as well as the use of a [Range](http://quarks-edge.github.io/quarks/docs/javadoc/quarks/analytics/sensors/Range.html).
+
+Oftentimes, a user wants a filter's behavior to be adaptable rather than static.  A filter's range can be made changeable via commands from some external source or just changed as a result of some other local analytics.
+
+A Quarks IotProvider and IoTDevice with its command streams would be a natural way to control the application.  In this recipe we will just simulate a "set optimal temp range" command stream.
+
+The string form of a ``Range`` is natural, consise, and easy to use.  As such it's a convenient form to use as external range format. The range string can easily be converted back into a ``Range``.
+
+We're going to assume familiarity with that earlier recipe and those concepts and focus on just the "adaptable range specification" aspect of this recipe.
+
+## Define the range
+
+A ``java.util.concurrent.atomic.AtomicReference`` is used to provide the necessary thread synchronization.
+
+```java
+    static Range<Double> DEFAULT_TEMP_RANGE = Ranges.valueOfDouble("[77.0..91.0]");
+    static AtomicReference<Range<Double>> optimalTempRangeRef =
+            new AtomicReference<>(DEFAULT_TEMP_RANGE);
+```
+
+## Define a method to change the range
+
+```java
+    static void setOptimalTempRange(Range<Double> range) {
+        System.out.println("Using optimal temperature range: " + range);
+        optimalTempRangeRef.set(range);
+    }
+```
+
+The filter just uses ``optimalTempRangeRef.get()`` to use the current range setting.
+
+## Simulate a setOptimalTempRange command stream
+
+Create a ``TStream<Range<Double>> setRangeCmds`` stream where a new range specification tuple is created every 10 seconds.  A ``sink`` on the stream calls ``setOptimalTempRange()`` to change the range and hence the filter's bahavior.
+
+```java
+    // Simulate a command stream to change the optimal range.
+    // Such a stream might be from an IotDevice command.
+    String[] ranges = new String[] {
+        "[70.0..120.0]", "[80.0..130.0]", "[90.0..140.0]",
+    };
+    AtomicInteger count = new AtomicInteger(0);
+    TStream<Range<Double>> setRangeCmds = top.poll(() 
+            -> Ranges.valueOfDouble(ranges[count.incrementAndGet() % ranges.length]),
+            10, TimeUnit.SECONDS);
+
+    setRangeCmds.sink(tuple -> setOptimalTempRange(tuple));
+```
+
+## The final application
+
+```java
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import quarks.analytics.sensors.Range;
+import quarks.analytics.sensors.Ranges;
+import quarks.providers.direct.DirectProvider;
+import quarks.samples.utils.sensor.SimulatedTemperatureSensor;
+import quarks.topology.TStream;
+import quarks.topology.Topology;
+
+/**
+ * Detect a sensor value out of expected range.
+ * Simulate an adaptable range changed by external commands.
+ */
+public class AdaptableFilterRange {
+    /**
+     * Optimal temperatures (in Fahrenheit)
+     */
+    static Range<Double> DEFAULT_TEMP_RANGE = Ranges.valueOfDouble("[77.0..91.0]");
+    static AtomicReference<Range<Double>> optimalTempRangeRef =
+            new AtomicReference<>(DEFAULT_TEMP_RANGE);
+    
+    static void setOptimalTempRange(Range<Double> range) {
+        System.out.println("Using optimal temperature range: " + range);
+        optimalTempRangeRef.set(range);
+    }
+                                                                                                                                           
+    /**
+     * Polls a simulated temperature sensor to periodically obtain
+     * temperature readings (in Fahrenheit). Use a simple filter
+     * to determine when the temperature is out of the optimal range.
+     */
+    public static void main(String[] args) throws Exception {
+
+        DirectProvider dp = new DirectProvider();
+
+        Topology top = dp.newTopology("TemperatureSensor");
+
+        // Generate a stream of temperature sensor readings
+        SimulatedTemperatureSensor tempSensor = new SimulatedTemperatureSensor();
+        TStream<Double> temp = top.poll(tempSensor, 1, TimeUnit.SECONDS);
+
+        // Simple filter: Perform analytics on sensor readings to detect when
+        // the temperature is out of the optimal range and generate warnings
+        TStream<Double> simpleFiltered = temp.filter(tuple ->
+                !optimalTempRangeRef.get().contains(tuple));
+        simpleFiltered.sink(tuple -> System.out.println("Temperature is out of range! "
+                + "It is " + tuple + "\u00b0F!"));
+
+        // See what the temperatures look like
+        temp.print();
+
+        // Simulate a command stream to change the optimal range.
+        // Such a stream might be from an IotDevice command.
+        String[] ranges = new String[] {
+            "[70.0..120.0]", "[80.0..130.0]", "[90.0..140.0]",
+        };
+        AtomicInteger count = new AtomicInteger(0);
+        TStream<Range<Double>> setRangeCmds = top.poll(
+                () -> Ranges.valueOfDouble(ranges[count.incrementAndGet() % ranges.length]),
+                10, TimeUnit.SECONDS);
+
+        setRangeCmds.sink(tuple -> setOptimalTempRange(tuple));
+
+        dp.submit(top);
+    }
+}
+```

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/647a2ed5/site/recipes/recipe_external_filter_range.md
----------------------------------------------------------------------
diff --git a/site/recipes/recipe_external_filter_range.md b/site/recipes/recipe_external_filter_range.md
new file mode 100644
index 0000000..5bb1fcc
--- /dev/null
+++ b/site/recipes/recipe_external_filter_range.md
@@ -0,0 +1,121 @@
+---
+title: Recipe: Use an external configuration file for a filter range specification.
+---
+
+The [Detecting a Sensor Value Out of Range](recipe_value_out_of_range.html) recipe introduced the basics of filtering as well as the use of a [Range](http://quarks-edge.github.io/quarks/docs/javadoc/quarks/analytics/sensors/Range.html).
+
+Oftentimes, a user wants to initialize a range specification from an external configuration file so the application code is more easily configured and reusable.
+
+The string form of a ``Range`` is natural, consise, and easy to use.  As such it's a convenient form to use in configuration files or for users to enter.  The range string can easily be converted back into a ``Range``.
+
+We're going to assume familiarity with that earlier recipe and those concepts and focus on just the "external range specification" aspect of this recipe.
+
+## Create a configuration file
+
+The file's syntax is that for a java.util.Properties object.
+See the Range documentation for the Range string syntax.
+
+Put this into a file:
+
+```java
+# the Range string for the temperature sensor optimal range
+optimalTempRange=[77.0..91.0]
+```
+
+Supply the pathname to this file as an argument to the application when you run it.
+
+## Loading the Configuration file
+
+A ``java.util.Properties`` object is often used for configuration parameters
+and it is easy to load the properties from a file.
+
+```java
+    // Load the configuration file with the path string in configFilePath
+    Properties props = new Properties();
+    props.load(Files.newBufferedReader(new File(configFilePath).toPath()));
+```
+
+## Initializing the Range
+
+```java
+    // initialize the range from a Range string in the properties.
+    // Use a default value if a range isn't present.
+    static String DEFAULT_TEMP_RANGE_STR = "[60.0..100.0]";                                                                                
+    static Range<Double> optimalTempRange = Ranges.valueOfDouble(
+        props.getProperty("optimalTempRange", defaultRange));
+```
+
+## The final application
+
+```java
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import quarks.analytics.sensors.Range;
+import quarks.analytics.sensors.Ranges;
+import quarks.providers.direct.DirectProvider;
+import quarks.samples.utils.sensor.SimulatedTemperatureSensor;
+import quarks.topology.TStream;
+import quarks.topology.Topology;                                                                                                           
+                                                                                                                                        
+/**
+ * Detect a sensor value out of expected range.
+ * Get the range specification from a configuration file.
+ */                                                                                                                                        
+public class ExternalFilterRange {
+    /**
+     * Optimal temperatures (in Fahrenheit)
+     */
+    static String DEFAULT_TEMP_RANGE_STR = "[60.0..100.0]";
+    static Range<Double> optimalTempRange;
+
+    /** Initialize the application's configuration */
+    static void initializeConfiguration(String configFilePath) throws Exception {
+        // Load the configuration file
+        Properties props = new Properties();
+        props.load(Files.newBufferedReader(new File(configFilePath).toPath()));
+
+        // initialize the range from a Range string in the properties.
+        // Use a default value if a range isn't present in the properties.
+        optimalTempRange = Ranges.valueOfDouble(
+                props.getProperty("optimalTempRange", DEFAULT_TEMP_RANGE_STR));
+        System.out.println("Using optimal temperature range: " + optimalTempRange);
+    }
+
+    /**
+     * Polls a simulated temperature sensor to periodically obtain
+     * temperature readings (in Fahrenheit). Use a simple filter
+     * to determine when the temperature is out of the optimal range.
+     */
+    public static void main(String[] args) throws Exception {
+        if (args.length != 1)
+            throw new Exception("missing pathname to configuration file");
+        String configFilePath = args[0];
+
+        DirectProvider dp = new DirectProvider();                                                                                          
+
+        Topology top = dp.newTopology("TemperatureSensor");
+
+        // Initialize the configuration
+        initializeConfiguration(configFilePath);
+                                                                                           
+        // Generate a stream of temperature sensor readings
+        SimulatedTemperatureSensor tempSensor = new SimulatedTemperatureSensor();
+        TStream<Double> temp = top.poll(tempSensor, 1, TimeUnit.SECONDS);
+
+        // Simple filter: Perform analytics on sensor readings to detect when
+        // the temperature is out of the optimal range and generate warnings
+        TStream<Double> simpleFiltered = temp.filter(tuple ->
+                !optimalTempRange.contains(tuple));
+        simpleFiltered.sink(tuple -> System.out.println("Temperature is out of range! "
+                + "It is " + tuple + "\u00b0F!"));
+
+        // See what the temperatures look like
+        temp.print();
+
+        dp.submit(top);
+    }
+}
+```