From 3438ccc06e4bd07aaee78553129129b6b276c52c Mon Sep 17 00:00:00 2001
From: horstmann <horstmann@lisha.ufsc.br>
Date: Mon, 5 Oct 2020 19:53:12 -0300
Subject: [PATCH 1/2] Aggregators Refactoring

Aggregators were changed to remove dependency of range and reflect the documentation at: https://epos.lisha.ufsc.br/IoT+Platform#Data_Aggregation.
---
 bin/smartdata/Aggregators.php | 426 +++++++++++++++++++++++++++++++++-
 1 file changed, 416 insertions(+), 10 deletions(-)

diff --git a/bin/smartdata/Aggregators.php b/bin/smartdata/Aggregators.php
index 06b5c68..81e76f1 100644
--- a/bin/smartdata/Aggregators.php
+++ b/bin/smartdata/Aggregators.php
@@ -25,6 +25,16 @@ final class Aggregator
                     return new LowerThan($parameters);
                 case 'higherThan':
                     return new HigherThan($parameters);
+                case 'drift':
+                    return new Drift($parameters);
+                case 'constantGain':
+                    return new ConstantGain($parameters);
+                case 'constantBias':
+                    return new ConstantBias($parameters);
+                case 'stuckAt':
+                    return new StuckAt($parameters);
+                case 'allAnomalies':
+                    return new AllAnomalies($parameters);
                 case 'confidence':
                     return new Confidence($parameters);
                 case 'can':
@@ -131,15 +141,15 @@ class Limit implements iAggregator
         $this->begin = $this->selected = null;
         if(isset($parameters->range) && $parameters->range > 0) {
             $this->range = $parameters->range;
-            switch ($parameters->name) {
-                case 'min': $this->limit = Limit::Min; break;
-                case 'max': $this->limit = Limit::Max; break;
-                default:
-                    throw (new Exception\CantCreateException());
-                    break;
-            }
         } else {
-            throw (new Exception\CantCreateException());
+            $this->range = 0;
+        }
+        switch ($parameters->name) {
+            case 'min': $this->limit = Limit::Min; break;
+            case 'max': $this->limit = Limit::Max; break;
+            default:
+                throw (new Exception\CantCreateException());
+                break;
         }
     }
 
@@ -181,7 +191,7 @@ class Mean implements iAggregator
         if(isset($parameters->range) && $parameters->range > 0) {
             $this->range = $parameters->range;
         } else {
-            throw (new Exception\CantCreateException());
+            $this->range = 0;
         }
     }
 
@@ -191,7 +201,7 @@ class Mean implements iAggregator
         if($this->begin == null) {
             $this->begin = $smartdata->time;
         } else {
-            if($smartdata->time > ($this->begin+$this->range)) {
+            if($smartdata->time >= ($this->begin+$this->range)) {
                 $ret = clone $this->last;
                 $ret->time = (int)($this->begin + $this->last->time)/2;
                 $ret->value = $this->sum/$this->count;
@@ -217,7 +227,403 @@ class Mean implements iAggregator
     private $count;
 }
 
+class Drift implements iAggregator
+{
+    public function __construct($parameters) {
+        $this->begin = null;
+        $this->count = 0;
+
+        if(isset($parameters->range) && $parameters->range >= 0) {
+            $this->range = $parameters->range;
+        } else {
+            $this->range = 0;
+        }
+        if (isset($parameters->parameter)) {
+            $this->slope = $parameters->parameter;
+        } else {
+            $this->slope = 0;
+        }
+        if (isset($parameters->offset) && $parameters->offset > 0) {
+            $this->offset = $parameters->offset;
+        } else {
+            $this->offset = 0;
+        }
+        if (isset($parameters->spacing) && $parameters->spacing > 0) {
+            $this->spacing = $parameters->spacing;
+        } else {
+            $this->spacing = 0;
+        }
+    }
+
+    public function aggregate(SmartData $smartdata) {
+        $ret = null;
+
+        if($this->begin == null) {
+            $this->begin = $smartdata->time + $this->offset;
+        }
+        if ($this->range === 0 && $smartdata->time >= $this->begin) {
+            $ret = clone $smartdata;
+            $ret->value = (float)$smartdata->value + (float)($this->slope * ($this->count + 1));
+            $this->count++;
+        } else {
+            if($smartdata->time > ($this->begin+$this->range) || $smartdata->time < $this->begin) {
+                $ret = clone $smartdata;
+                $this->count = 0;
+                if ($this->spacing > 0) {
+                    if ($smartdata->time >= ($this->begin+$this->range+$this->spacing)) {
+                        $this->begin = $smartdata->time;
+                        $ret = clone $smartdata;
+                        $ret->value = (float)$smartdata->value + (float)($this->slope * ($this->count + 1));
+                        $this->count++;
+                    }
+                }
+            } else {
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value + (float)($this->slope * ($this->count + 1));
+                $this->count++;
+            }
+        }
+        return $ret;
+    }
+    public function finish() { return null; }
+
+    private $range;
+    private $begin;
+    private $offset;
+    private $spacing;
+
+    private $slope;
+    private $count;
+}
+
+class StuckAt implements iAggregator
+{
+    public function __construct($parameters) {
+        $this->begin = null;
+        $this->count = 0;
+
+        if(isset($parameters->range) && $parameters->range >= 0) {
+            $this->range = $parameters->range;
+            $this->value = (float)0;
+        } else {
+            $this->range = 0;
+            $this->value = (float)0;
+        }
+        if (isset($parameters->offset) && $parameters->offset > 0) {
+            $this->offset = $parameters->offset;
+        } else {
+            $this->offset = 0;
+        }
+        if (isset($parameters->spacing) && $parameters->spacing > 0) {
+            $this->spacing = $parameters->spacing;
+        } else {
+            $this->spacing = 0;
+        }
+    }
+
+    public function aggregate(SmartData $smartdata) {
+        $ret = null;
+
+        if($this->begin == null) {
+            $this->begin = $smartdata->time + $this->offset;
+            $this->value = $smartdata->value;
+        }
+        if ($this->range === 0 && $smartdata->time >= $this->begin) {
+            $ret = clone $smartdata;
+            $ret->value = $this->value;
+            $this->count++;
+        } else {
+            if($smartdata->time > ($this->begin+$this->range) || $smartdata->time < $this->begin) {
+                $ret = clone $smartdata;
+                $this->count = 0;
+                $this->value = $smartdata->value;
+                if ($this->spacing > 0) {
+                    if ($smartdata->time >= ($this->begin+$this->range+$this->spacing)) {
+                        $this->begin = $smartdata->time;
+                        $ret = clone $smartdata;
+                        $ret->value = $this->value;
+                        $this->count++;
+                    }
+                }
+            } else {
+                $ret = clone $smartdata;
+                $ret->value = $this->value;
+                $this->count++;
+            }
+        }
+
+        return $ret;
+    }
+
+    public function finish() { return null; }
+
+    private $range;
+    private $begin;
+    private $offset;
+    private $spacing;
+
+    private $value;
+    private $count;
+}
+
+class ConstantBias implements iAggregator
+{
+    public function __construct($parameters) {
+        $this->begin = null;
+        $this->count = 0;
 
+        if(isset($parameters->range) && $parameters->range > 0) {
+            $this->range = $parameters->range;
+        } else {
+            $this->range = 0;
+        }
+        if (isset($parameters->parameter)) {
+            $this->bias = (float)$parameters->parameter;
+        } else {
+            $this->bias = 0;
+        }
+        if (isset($parameters->offset) && $parameters->offset > 0) {
+            $this->offset = $parameters->offset;
+        } else {
+            $this->offset = 0;
+        }
+        if (isset($parameters->spacing) && $parameters->spacing > 0) {
+            $this->spacing = $parameters->spacing;
+        } else {
+            $this->spacing = 0;
+        }
+    }
+
+    public function aggregate(SmartData $smartdata) {
+        $ret = null;
+
+        if($this->begin == null) {
+            $this->begin = $smartdata->time + $this->offset; //seting a time window before applying the aggr
+        }
+        if ($this->range === 0 && $smartdata->time >= $this->begin) {
+            $ret = clone $smartdata;
+            $ret->value = (float)$smartdata->value + ($this->bias);
+            $this->count++;
+        } else {
+            if($smartdata->time > ($this->begin+$this->range) || $smartdata->time < $this->begin) {
+                $ret = clone $smartdata;
+                $this->count = 0;
+                if ($this->spacing > 0) {
+                    if ($smartdata->time >= ($this->begin+$this->range+$this->spacing)) {
+                        $this->begin = $smartdata->time;
+                        $ret = clone $smartdata;
+                        $ret->value = (float)$smartdata->value + ($this->bias);
+                        $this->count++;
+                    }
+                }
+            } else {
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value + ($this->bias);
+                $this->count++;
+            }
+        }
+
+        return $ret;
+    }
+
+    public function finish() { return null; }
+
+    private $range;
+    private $begin;
+    private $offset;
+    private $spacing;
+
+    private $bias;
+    private $count;
+}
+
+class ConstantGain implements iAggregator
+{
+    public function __construct($parameters) {
+        $this->begin = null;
+        $this->count = 0;
+
+        if(isset($parameters->range) && $parameters->range > 0) {
+            $this->range = $parameters->range;
+        } else {
+            $this->range = 0;
+        }
+        if (isset($parameters->parameter)) {
+            $this->gain = (float)$parameters->parameter;
+        } else {
+            $this->gain = 0;
+        }
+        if (isset($parameters->offset) && $parameters->offset > 0) {
+            $this->offset = $parameters->offset;
+        } else {
+            $this->offset = 0;
+        }
+        if (isset($parameters->spacing) && $parameters->spacing > 0) {
+            $this->spacing = $parameters->spacing;
+        } else {
+            $this->spacing = 0;
+        }
+    }
+
+    public function aggregate(SmartData $smartdata) {
+        $ret = null;
+
+        if($this->begin == null) {
+            $this->begin = $smartdata->time + $this->offset;
+        }
+        if($this->range === 0 && $smartdata->time >= $this->begin) {
+            $ret = clone $smartdata;
+            $ret->value = (float)$smartdata->value * ($this->gain);
+            $this->count++;
+        } else {
+            if($smartdata->time > ($this->begin+$this->range) || $smartdata->time < $this->begin) {
+                $ret = clone $smartdata;
+                $this->count = 0;
+                if ($this->spacing > 0) {
+                    if ($smartdata->time > ($this->begin+$this->range+$this->spacing)) {
+                        $this->begin = $smartdata->time;
+                        $ret = clone $smartdata;
+                        $ret->value = (float)$smartdata->value * ($this->gain);
+                        $this->count++;
+                    }
+                }
+            } else {
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value * ($this->gain);
+                $this->count++;
+            }
+        }
+        return $ret;
+    }
+
+    public function finish() { return null; }
+
+    private $range;
+    private $begin;
+    private $offset;
+    private $spacing;
+
+    private $gain;
+    private $count;
+}
+
+class AllAnomalies implements iAggregator
+{
+    public function __construct($parameters) {
+        $this->begin = null;
+        $this->count = 0;
+        $this->applied = 0;
+        if(isset($parameters->range) && $parameters->range >= 0) {
+            $this->range = $parameters->range;
+        } else {
+            $this->range = 0;
+        }
+        if (isset($parameters->drift) && $parameters->drift > 0) {
+            $this->slope = $parameters->drift;
+        } else {
+            $this->slope = 0;
+        }
+        if (isset($parameters->stuck) && $parameters->stuck > 0) {
+            $this->stuck = $parameters->stuck;
+        } else {
+            $this->stuck = 0;
+        }
+        if (isset($parameters->bias) && $parameters->bias > 0) {
+            $this->bias = $parameters->bias;
+        } else {
+            $this->bias = 0;
+        }
+        if (isset($parameters->gain) && $parameters->gain > 0) {
+            $this->gain = $parameters->gain;
+        } else {
+            $this->gain = 0;
+        }
+        if (isset($parameters->offset) && $parameters->offset > 0) {
+            $this->offset = $parameters->offset;
+        } else {
+            $this->offset = 0;
+        }
+        if (isset($parameters->spacing) && $parameters->spacing > 0) {
+            $this->spacing = $parameters->spacing;
+        } else {
+            $this->spacing = 0;
+        }
+    }
+
+    public function aggregate(SmartData $smartdata) {
+        $ret = null;
+
+        if($this->begin == null) {
+            $this->begin = $smartdata->time + $this->offset;
+        }
+        if($smartdata->time > ($this->begin+$this->range) || $smartdata->time < $this->begin) {
+            $ret = clone $smartdata;
+            $this->count = 0;
+            if($smartdata->time > ($this->begin+$this->range)) {
+                $this->begin = $smartdata->time + $this->spacing;
+                $this->applied++;
+                $this->count = 0;
+                $this->value = $smartdata->value;
+            }
+        } else {
+            if($this->applied == 0) {
+                //apply drift
+                if ($this->slope == 0) {
+                    $this->applied++;
+                }
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value + (float)($this->slope * ($this->count + 1));
+                $this->count++;
+            }
+            if($this->applied == 1) {
+                //apply stuckAt
+                if ($this->stuck == 0) {
+                    $this->applied++;
+                }
+                $ret = clone $smartdata;
+                $ret->value = $this->value;
+                $this->count++;
+            }
+            if($this->applied == 2) {
+                //apply constantBias
+                if ($this->bias == 0) {
+                    $this->applied++;
+                }
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value + ($this->bias);
+                $this->count++;
+            }
+            if($this->applied == 3) {
+                //apply constantGain
+                if ($this->gain == 0) {
+                    $this->applied++;
+                }
+                $ret = clone $smartdata;
+                $ret->value = (float)$smartdata->value * ($this->gain);
+                $this->count++;
+            }
+            if ($this->applied > 3) {
+                $ret = clone $smartdata;
+            }
+        }
+        return $ret;
+    }
+    public function finish() { return null; }
+
+    private $range;
+    private $begin;
+    private $offset;
+    private $spacing;
+
+    private $slope;
+    private $stuck;
+    private $bias;
+    private $gain;
+    private $count;
+    private $value;
+
+    private $applied;
+}
 
 
 
-- 
GitLab


From 5f590b403a984b48645d7b4035a3312a51b68de1 Mon Sep 17 00:00:00 2001
From: horstmann <horstmann@lisha.ufsc.br>
Date: Mon, 5 Oct 2020 20:15:33 -0300
Subject: [PATCH 2/2] Adjusting Grafana plugin to reflect Aggregators change

---
 lib/grafana/plugin/src/datasource.js          |  4 +-
 .../plugin/src/partials/query.editor.html     | 64 +++----------------
 lib/grafana/plugin/src/query_ctrl.js          |  2 +-
 3 files changed, 12 insertions(+), 58 deletions(-)

diff --git a/lib/grafana/plugin/src/datasource.js b/lib/grafana/plugin/src/datasource.js
index ab81dc2..7b68fb5 100644
--- a/lib/grafana/plugin/src/datasource.js
+++ b/lib/grafana/plugin/src/datasource.js
@@ -78,8 +78,8 @@ export class SmartDataDS {
                 request_parameters['aggregator']['parameter'] = parseFloat(options.targets[target_index].aggregatorParameter);
 
             //add here the json
-            if ('aggregatorDelay' in options.targets[target_index] && options.targets[target_index].aggregatorDelay.length && options.targets[target_index].aggregator.length)
-                request_parameters['aggregator']['delay'] = parseInt(options.targets[target_index].aggregatorDelay);
+            if ('aggregatorOffset' in options.targets[target_index] && options.targets[target_index].aggregatorOffset.length && options.targets[target_index].aggregator.length)
+                request_parameters['aggregator']['offset'] = parseInt(options.targets[target_index].aggregatorOffset);
             if ('aggregatorSpacing' in options.targets[target_index] && options.targets[target_index].aggregatorSpacing.length && options.targets[target_index].aggregator.length)
                 request_parameters['aggregator']['spacing'] = parseFloat(options.targets[target_index].aggregatorSpacing);
 
diff --git a/lib/grafana/plugin/src/partials/query.editor.html b/lib/grafana/plugin/src/partials/query.editor.html
index a4d892c..14f3da3 100644
--- a/lib/grafana/plugin/src/partials/query.editor.html
+++ b/lib/grafana/plugin/src/partials/query.editor.html
@@ -144,15 +144,16 @@
         <div class="clearfix"></div>
     </div>
 
+
     <div class="gf-form">
         <label class="gf-form-label width-6">Aggregator</label>
 
         <select class="gf-form-input ng-pristine ng-valid ng-not-empty width-8"
-            ng-model="ctrl.target.aggregator" ng-options="o for o in ['', 'min', 'mean', 'max', 'dbp', 'lowerThan','higherThan', 'lastValue', 'confidence', 'can', 'drift', 'stuckAt', 'constantGain', 'constantBias', 'allAnomalies']" ng-blur="ctrl.targetBlur()" on-change="ctrl.onChangeInternal()"/>
+            ng-model="ctrl.target.aggregator" ng-options="o for o in ['', 'min', 'mean', 'max', 'dbp', 'lowerThan','higherThan', 'lastValue', 'confidence', 'can', 'drift', 'stuckAt', 'constantGain', 'constantBias']" ng-blur="ctrl.targetBlur()" on-change="ctrl.onChangeInternal()"/>
 
         <label class="gf-form-label width-6">Range</label>
 
-        <input type="text" class="input-xxlarge gf-form-input"
+        <input type="text" class="input-small gf-form-input"
                 ng-model="ctrl.target.aggregatorRange"
                 spellcheck="false"
                 ng-readonly="false"
@@ -161,24 +162,17 @@
 
         <label class="gf-form-label width-6">Parameter</label>
 
-        <input type="text" class="input-xxlarge gf-form-input"
+        <input type="text" class="input-small gf-form-input"
                 ng-model="ctrl.target.aggregatorParameter"
                 spellcheck="false"
                 ng-readonly="false"
                 ng-blur="ctrl.targetBlur()"
                 on-change="ctrl.onChangeInternal()">
 
-        <div class="clearfix"></div>
-    </div>
-
-    <div class="gf-form">
-        <!--
-        add here the json (text input to the whole json)
-        -->
-        <label class="gf-form-label width-6">Delay</label>
+        <label class="gf-form-label width-6">Offset</label>
 
-        <input type="text" class="input-xxlarge gf-form-input"
-                ng-model="ctrl.target.aggregatorDelay"
+        <input type="text" class="input-small gf-form-input"
+                ng-model="ctrl.target.aggregatorOffset"
                 spellcheck="false"
                 ng-readonly="false"
                 ng-blur="ctrl.targetBlur()"
@@ -186,7 +180,7 @@
 
         <label class="gf-form-label width-6">Spacing</label>
 
-        <input type="text" class="input-xxlarge gf-form-input"
+        <input type="text" class="input-small gf-form-input"
                 ng-model="ctrl.target.aggregatorSpacing"
                 spellcheck="false"
                 ng-readonly="false"
@@ -197,48 +191,8 @@
 
     </div>
 
-
-    <!-- <div class="gf-form">
-        <label class="gf-form-label width-6">Drift</label>
-
-        <input type="text" class="input-xxlarge gf-form-input"
-                ng-model="ctrl.target.aggregatorDrift"
-                spellcheck="false"
-                ng-readonly="false"
-                ng-blur="ctrl.targetBlur()"
-                on-change="ctrl.onChangeInternal()">
-
-        <label class="gf-form-label width-6">Stuck</label>
-
-        <input type="text" class="input-xxlarge gf-form-input"
-                ng-model="ctrl.target.aggregatorStuck"
-                spellcheck="false"
-                ng-readonly="false"
-                ng-blur="ctrl.targetBlur()"
-                on-change="ctrl.onChangeInternal()">
-
-        <label class="gf-form-label width-6">Bias</label>
-
-        <input type="text" class="input-xxlarge gf-form-input"
-                ng-model="ctrl.target.aggregatorBias"
-                spellcheck="false"
-                ng-readonly="false"
-                ng-blur="ctrl.targetBlur()"
-                on-change="ctrl.onChangeInternal()">
-
-        <label class="gf-form-label width-6">Gain</label>
-
-        <input type="text" class="input-xxlarge gf-form-input"
-                ng-model="ctrl.target.aggregatorGain"
-                spellcheck="false"
-                ng-readonly="false"
-                ng-blur="ctrl.targetBlur()"
-                on-change="ctrl.onChangeInternal()">
-        <div class="clearfix"></div>
-    </div> -->
-
     <div class="gf-form">
-     <label class="gf-form-label width-6">Extra</label>
+     <label class="gf-form-label width-6">Aggregators Extra</label>
 
      <input type="text" class="input-xxlarge gf-form-input"
              ng-model="ctrl.target.aggregatorExtra"
diff --git a/lib/grafana/plugin/src/query_ctrl.js b/lib/grafana/plugin/src/query_ctrl.js
index b6f6012..9d02d80 100644
--- a/lib/grafana/plugin/src/query_ctrl.js
+++ b/lib/grafana/plugin/src/query_ctrl.js
@@ -24,7 +24,7 @@ export class SmartDataDSQueryCtrl extends QueryCtrl {
         this.target.aggregator          = this.target.aggregator || '';
         this.target.aggregatorRange     = this.target.aggregatorRange || '';
         this.target.aggregatorParameter = this.target.aggregatorParameter || '';
-        this.target.aggregatorDelay     = this.target.aggregatorDelay || '';
+        this.target.aggregatorOffset     = this.target.aggregatorOffset || '';
         this.target.aggregatorSpacing   = this.target.aggregatorSpacing || '';
         this.target.aggregatorExtra     = this.target.aggregatorExtra || '';
         // this.target.aggregatorDrift     = this.target.aggregatorDrift || '';
-- 
GitLab