thingsboard-aplcache

Details

diff --git a/application/pom.xml b/application/pom.xml
index c113064..9364cfc 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/common/data/pom.xml b/common/data/pom.xml
index bb23177..ffee17c 100644
--- a/common/data/pom.xml
+++ b/common/data/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>
diff --git a/common/message/pom.xml b/common/message/pom.xml
index d3f770b..5362f68 100644
--- a/common/message/pom.xml
+++ b/common/message/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>

common/pom.xml 2(+1 -1)

diff --git a/common/pom.xml b/common/pom.xml
index 6342c05..798bec4 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/common/transport/pom.xml b/common/transport/pom.xml
index 9b66c2f..c537756 100644
--- a/common/transport/pom.xml
+++ b/common/transport/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>common</artifactId>
     </parent>
     <groupId>org.thingsboard.common</groupId>

dao/pom.xml 2(+1 -1)

diff --git a/dao/pom.xml b/dao/pom.xml
index 83598ee..cc3804f 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/extensions/extension-kafka/pom.xml b/extensions/extension-kafka/pom.xml
index 029c626..6c35bd2 100644
--- a/extensions/extension-kafka/pom.xml
+++ b/extensions/extension-kafka/pom.xml
@@ -22,7 +22,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>extensions</artifactId>
     </parent>
     <groupId>org.thingsboard.extensions</groupId>
diff --git a/extensions/extension-rabbitmq/pom.xml b/extensions/extension-rabbitmq/pom.xml
index 9f8da69..941165d 100644
--- a/extensions/extension-rabbitmq/pom.xml
+++ b/extensions/extension-rabbitmq/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>extensions</artifactId>
     </parent>
     <groupId>org.thingsboard.extensions</groupId>
diff --git a/extensions/extension-rest-api-call/pom.xml b/extensions/extension-rest-api-call/pom.xml
index 6a4e548..a732dc8 100644
--- a/extensions/extension-rest-api-call/pom.xml
+++ b/extensions/extension-rest-api-call/pom.xml
@@ -22,7 +22,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>extensions</artifactId>
     </parent>
     <groupId>org.thingsboard.extensions</groupId>
diff --git a/extensions/pom.xml b/extensions/pom.xml
index ff3b146..2c1fdfe 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/extensions-api/pom.xml b/extensions-api/pom.xml
index 804333e..87ad867 100644
--- a/extensions-api/pom.xml
+++ b/extensions-api/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/extensions-core/pom.xml b/extensions-core/pom.xml
index b1b8744..923d474 100644
--- a/extensions-core/pom.xml
+++ b/extensions-core/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index f602b41..fe95d9b 100755
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.thingsboard</groupId>
     <artifactId>thingsboard</artifactId>
-    <version>1.2.3</version>
+    <version>1.3.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>Thingsboard</name>

tools/pom.xml 2(+1 -1)

diff --git a/tools/pom.xml b/tools/pom.xml
index 67f0369..2b83e13 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml
index eebfbae..8f15edc 100644
--- a/transport/coap/pom.xml
+++ b/transport/coap/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/http/pom.xml b/transport/http/pom.xml
index 0fa84c4..004c57e 100644
--- a/transport/http/pom.xml
+++ b/transport/http/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index aa7cfd3..2de70a7 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>transport</artifactId>
     </parent>
     <groupId>org.thingsboard.transport</groupId>
diff --git a/transport/pom.xml b/transport/pom.xml
index f2b6ddd..fb47647 100644
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>

ui/package.json 2(+1 -1)

diff --git a/ui/package.json b/ui/package.json
index ddcc96e..73d7bcd 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -1,7 +1,7 @@
 {
   "name": "thingsboard",
   "private": true,
-  "version": "1.2.3",
+  "version": "1.3.0",
   "description": "Thingsboard UI",
   "licenses": [
     {

ui/pom.xml 2(+1 -1)

diff --git a/ui/pom.xml b/ui/pom.xml
index cf5406d..1efb29a 100644
--- a/ui/pom.xml
+++ b/ui/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.thingsboard</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0-SNAPSHOT</version>
         <artifactId>thingsboard</artifactId>
     </parent>
     <groupId>org.thingsboard</groupId>
diff --git a/ui/src/app/api/subscription.js b/ui/src/app/api/subscription.js
index 633bcc3..fb774a1 100644
--- a/ui/src/app/api/subscription.js
+++ b/ui/src/app/api/subscription.js
@@ -126,6 +126,7 @@ export default class Subscription {
                         dataKey: dataKey,
                         dataIndex: dataIndex++
                     };
+                    legendKey.dataKey.hidden = false;
                     this.legendData.keys.push(legendKey);
                     var legendKeyData = {
                         min: null,
@@ -146,11 +147,11 @@ export default class Subscription {
             this.legendData.keys = this.ctx.$filter('orderBy')(this.legendData.keys, '+label');
             registration = this.ctx.$scope.$watch(
                 function() {
-                    return subscription.legendData.data;
+                    return subscription.legendData.keys;
                 },
                 function (newValue, oldValue) {
                     for(var i = 0; i < newValue.length; i++) {
-                        if(newValue[i].hidden != oldValue[i].hidden) {
+                        if(newValue[i].dataKey.hidden != oldValue[i].dataKey.hidden) {
                             subscription.updateDataVisibility(i);
                         }
                     }
@@ -307,7 +308,7 @@ export default class Subscription {
     }
 
     updateDataVisibility(index) {
-        var hidden = this.legendData.data[index].hidden;
+        var hidden = this.legendData.keys[index].dataKey.hidden;
         if (hidden) {
             this.hiddenData[index].data = this.data[index].data;
             this.data[index].data = [];
@@ -418,7 +419,7 @@ export default class Subscription {
         this.notifyDataLoaded();
         var update = true;
         var currentData;
-        if (this.displayLegend && this.legendData.data[datasourceIndex + dataKeyIndex].hidden) {
+        if (this.displayLegend && this.legendData.keys[datasourceIndex + dataKeyIndex].dataKey.hidden) {
             currentData = this.hiddenData[datasourceIndex + dataKeyIndex];
         } else {
             currentData = this.data[datasourceIndex + dataKeyIndex];
@@ -445,18 +446,21 @@ export default class Subscription {
     }
 
     updateLegend(dataIndex, data, apply) {
+        var dataKey = this.legendData.keys[dataIndex].dataKey;
+        var decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals : this.decimals;
+        var units = dataKey.units && dataKey.units.length ? dataKey.units : this.units;
         var legendKeyData = this.legendData.data[dataIndex];
         if (this.legendConfig.showMin) {
-            legendKeyData.min = this.ctx.widgetUtils.formatValue(calculateMin(data), this.decimals, this.units);
+            legendKeyData.min = this.ctx.widgetUtils.formatValue(calculateMin(data), decimals, units);
         }
         if (this.legendConfig.showMax) {
-            legendKeyData.max = this.ctx.widgetUtils.formatValue(calculateMax(data), this.decimals, this.units);
+            legendKeyData.max = this.ctx.widgetUtils.formatValue(calculateMax(data), decimals, units);
         }
         if (this.legendConfig.showAvg) {
-            legendKeyData.avg = this.ctx.widgetUtils.formatValue(calculateAvg(data), this.decimals, this.units);
+            legendKeyData.avg = this.ctx.widgetUtils.formatValue(calculateAvg(data), decimals, units);
         }
         if (this.legendConfig.showTotal) {
-            legendKeyData.total = this.ctx.widgetUtils.formatValue(calculateTotal(data), this.decimals, this.units);
+            legendKeyData.total = this.ctx.widgetUtils.formatValue(calculateTotal(data), decimals, units);
         }
         this.callbacks.legendDataUpdated(this, apply !== false);
     }
diff --git a/ui/src/app/components/datakey-config.directive.js b/ui/src/app/components/datakey-config.directive.js
index 9b3081e..90810af 100644
--- a/ui/src/app/components/datakey-config.directive.js
+++ b/ui/src/app/components/datakey-config.directive.js
@@ -76,6 +76,8 @@ function DatakeyConfig($compile, $templateCache, $q, types) {
                 scope.model.name = ngModelCtrl.$viewValue.name;
                 scope.model.label = ngModelCtrl.$viewValue.label;
                 scope.model.color = ngModelCtrl.$viewValue.color;
+                scope.model.units = ngModelCtrl.$viewValue.units;
+                scope.model.decimals = ngModelCtrl.$viewValue.decimals;
                 scope.model.funcBody = ngModelCtrl.$viewValue.funcBody;
                 scope.model.postFuncBody = ngModelCtrl.$viewValue.postFuncBody;
                 scope.model.usePostProcessing = scope.model.postFuncBody ? true : false;
@@ -97,6 +99,8 @@ function DatakeyConfig($compile, $templateCache, $q, types) {
                 value.name = scope.model.name;
                 value.label = scope.model.label;
                 value.color = scope.model.color;
+                value.units = scope.model.units;
+                value.decimals = scope.model.decimals;
                 value.funcBody = scope.model.funcBody;
                 if (!scope.model.postFuncBody) {
                     delete value.postFuncBody;
diff --git a/ui/src/app/components/datakey-config.tpl.html b/ui/src/app/components/datakey-config.tpl.html
index f170220..755c4f4 100644
--- a/ui/src/app/components/datakey-config.tpl.html
+++ b/ui/src/app/components/datakey-config.tpl.html
@@ -48,6 +48,16 @@
 		    md-color-history="false">
 		</div>    
 	</div>
+	<div layout="row" layout-align="start center">
+		<md-input-container flex>
+			<label translate>datakey.units</label>
+			<input name="units" ng-model="model.units">
+		</md-input-container>
+		<md-input-container flex>
+			<label translate>datakey.decimals</label>
+			<input name="decimals" ng-model="model.decimals" type="number" min="0" max="15" step="1" ng-pattern="/^\d*$/">
+		</md-input-container>
+	</div>
 	<section layout="column" ng-if="model.type === types.dataKeyType.function">
 		<span translate>datakey.data-generation-func</span>
 		<br/>
diff --git a/ui/src/app/components/legend.directive.js b/ui/src/app/components/legend.directive.js
index 196629c..39c8e58 100644
--- a/ui/src/app/components/legend.directive.js
+++ b/ui/src/app/components/legend.directive.js
@@ -45,7 +45,7 @@ function Legend($compile, $templateCache, types) {
             scope.legendConfig.position === types.position.top.value;
 
         scope.toggleHideData = function(index) {
-            scope.legendData.data[index].hidden = !scope.legendData.data[index].hidden;
+            scope.legendData.keys[index].dataKey.hidden = !scope.legendData.keys[index].dataKey.hidden;
         }
 
         $compile(element.contents())(scope);
diff --git a/ui/src/app/components/legend.tpl.html b/ui/src/app/components/legend.tpl.html
index 8350320..18c9137 100644
--- a/ui/src/app/components/legend.tpl.html
+++ b/ui/src/app/components/legend.tpl.html
@@ -30,7 +30,7 @@
             <td><span class="tb-legend-line"  ng-style="{backgroundColor: legendKey.dataKey.color}"></span></td>
             <td class="tb-legend-label"
                 ng-click="toggleHideData(legendKey.dataIndex)"
-                ng-class="{ 'tb-hidden-label': legendData.data[legendKey.dataIndex].hidden, 'tb-horizontal': isHorizontal }">
+                ng-class="{ 'tb-hidden-label': legendData.keys[legendKey.dataIndex].dataKey.hidden, 'tb-horizontal': isHorizontal }">
                 {{ legendKey.dataKey.label }}
             </td>
             <td class="tb-legend-value" ng-if="legendConfig.showMin === true">{{ legendData.data[legendKey.dataIndex].min }}</td>
diff --git a/ui/src/app/components/widget-config.directive.js b/ui/src/app/components/widget-config.directive.js
index 122889d..c3793be 100644
--- a/ui/src/app/components/widget-config.directive.js
+++ b/ui/src/app/components/widget-config.directive.js
@@ -355,10 +355,10 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti
             var matches = false;
             do {
                 matches = false;
-                if (value.datasources) {
-                    for (var d in value.datasources) {
-                        var datasource = value.datasources[d];
-                        for (var k in datasource.dataKeys) {
+                if (value.config.datasources) {
+                    for (var d=0;d<value.config.datasources.length;d++) {
+                        var datasource = value.config.datasources[d];
+                        for (var k=0;k<datasource.dataKeys.length;k++) {
                             var dataKey = datasource.dataKeys[k];
                             if (dataKey.label === label) {
                                 i++;
@@ -375,9 +375,9 @@ function WidgetConfig($compile, $templateCache, $rootScope, $timeout, types, uti
         scope.genNextColor = function () {
             var i = 0;
             var value = ngModelCtrl.$viewValue;
-            if (value.datasources) {
-                for (var d in value.datasources) {
-                    var datasource = value.datasources[d];
+            if (value.config.datasources) {
+                for (var d=0;d<value.config.datasources.length;d++) {
+                    var datasource = value.config.datasources[d];
                     i += datasource.dataKeys.length;
                 }
             }
diff --git a/ui/src/app/dashboard/dashboard.controller.js b/ui/src/app/dashboard/dashboard.controller.js
index e18ebb8..c446be4 100644
--- a/ui/src/app/dashboard/dashboard.controller.js
+++ b/ui/src/app/dashboard/dashboard.controller.js
@@ -983,8 +983,11 @@ export default function DashboardController(types, dashboardUtils, widgetService
                 if (revert) {
                     vm.dashboard = vm.prevDashboard;
                     vm.dashboardConfiguration = vm.dashboard.configuration;
+                    vm.dashboardCtx.dashboardTimewindow = vm.dashboardConfiguration.timewindow;
                     openDashboardState(vm.prevDashboardState);
                     entityAliasesUpdated();
+                } else {
+                    vm.dashboard.configuration.timewindow = vm.dashboardCtx.dashboardTimewindow;
                 }
             }
         }
diff --git a/ui/src/app/dashboard/dashboard.tpl.html b/ui/src/app/dashboard/dashboard.tpl.html
index 078daab..94e016e 100644
--- a/ui/src/app/dashboard/dashboard.tpl.html
+++ b/ui/src/app/dashboard/dashboard.tpl.html
@@ -63,7 +63,7 @@
                                            is-toolbar
                                            direction="left"
                                            tooltip-direction="bottom" aggregation
-                                           ng-model="vm.dashboardConfiguration.timewindow">
+                                           ng-model="vm.dashboardCtx.dashboardTimewindow">
                             </tb-timewindow>
                             <tb-aliases-entity-select ng-show="!vm.isEdit && vm.displayEntitiesSelect()"
                                                       tooltip-direction="bottom"
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index 7f52eac..6e6308d 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -385,6 +385,8 @@ export default angular.module('thingsboard.locale', [])
                     "advanced": "Advanced",
                     "label": "Label",
                     "color": "Color",
+                    "units": "Special symbol to show next to value",
+                    "decimals": "Number of digits after floating point",
                     "data-generation-func": "Data generation function",
                     "use-data-post-processing-func": "Use data post-processing function",
                     "configuration": "Data key configuration",
diff --git a/ui/src/app/widget/lib/analogue-linear-gauge.js b/ui/src/app/widget/lib/analogue-linear-gauge.js
index 1a7c99a..a045f94 100644
--- a/ui/src/app/widget/lib/analogue-linear-gauge.js
+++ b/ui/src/app/widget/lib/analogue-linear-gauge.js
@@ -41,8 +41,7 @@ export default class TbAnalogueLinearGauge {
 
         var valueInt = settings.valueInt || 3;
 
-        var valueDec = (angular.isDefined(settings.valueDec) && settings.valueDec !== null)
-            ? settings.valueDec : ctx.decimals;
+        var valueDec = getValueDec(settings);
 
         step = parseFloat(parseFloat(step).toFixed(valueDec));
 
@@ -74,6 +73,32 @@ export default class TbAnalogueLinearGauge {
         var progressColorStart = tinycolor(keyColor).setAlpha(0.05).toRgbString();
         var progressColorEnd = tinycolor(keyColor).darken().toRgbString();
 
+        function getUnits(settings) {
+            var dataKey;
+            if (ctx.data && ctx.data[0]) {
+                dataKey = ctx.data[0].dataKey;
+            }
+            if (dataKey && dataKey.units && dataKey.units.length) {
+                return dataKey.units;
+            } else {
+                return angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units;
+            }
+        }
+
+        function getValueDec(settings) {
+            var dataKey;
+            if (ctx.data && ctx.data[0]) {
+                dataKey = ctx.data[0].dataKey;
+            }
+            if (dataKey && angular.isDefined(dataKey.decimals)) {
+                return dataKey.decimals;
+            } else {
+                return (angular.isDefined(settings.valueDec) && settings.valueDec !== null)
+                    ? settings.valueDec : ctx.decimals;
+            }
+        }
+
+
         function getFontFamily(fontSettings) {
             var family = fontSettings && fontSettings.family ? fontSettings.family : 'Roboto';
             if (family === 'RobotoDraft') {
@@ -92,7 +117,7 @@ export default class TbAnalogueLinearGauge {
             maxValue: maxValue,
             majorTicks: majorTicks,
             minorTicks: settings.minorTicks || 2,
-            units: angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units,
+            units: getUnits(settings),
             title: ((settings.showUnitTitle !== false) ?
                 (settings.unitTitle && settings.unitTitle.length > 0 ?
                     settings.unitTitle : dataKey.label) : ''),
diff --git a/ui/src/app/widget/lib/analogue-radial-gauge.js b/ui/src/app/widget/lib/analogue-radial-gauge.js
index 3a526bd..76a2c38 100644
--- a/ui/src/app/widget/lib/analogue-radial-gauge.js
+++ b/ui/src/app/widget/lib/analogue-radial-gauge.js
@@ -42,8 +42,7 @@ export default class TbAnalogueRadialGauge {
 
         var valueInt = settings.valueInt || 3;
 
-        var valueDec = (angular.isDefined(settings.valueDec) && settings.valueDec !== null)
-            ? settings.valueDec : ctx.decimals;
+        var valueDec = getValueDec(settings);
 
         step = parseFloat(parseFloat(step).toFixed(valueDec));
 
@@ -71,6 +70,31 @@ export default class TbAnalogueRadialGauge {
 
         var colorNumbers = tinycolor(keyColor).darken(20).toRgbString();
 
+        function getUnits(settings) {
+            var dataKey;
+            if (ctx.data && ctx.data[0]) {
+                dataKey = ctx.data[0].dataKey;
+            }
+            if (dataKey && dataKey.units && dataKey.units.length) {
+                return dataKey.units;
+            } else {
+                return angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units;
+            }
+        }
+
+        function getValueDec(settings) {
+            var dataKey;
+            if (ctx.data && ctx.data[0]) {
+                dataKey = ctx.data[0].dataKey;
+            }
+            if (dataKey && angular.isDefined(dataKey.decimals)) {
+                return dataKey.decimals;
+            } else {
+                return (angular.isDefined(settings.valueDec) && settings.valueDec !== null)
+                    ? settings.valueDec : ctx.decimals;
+            }
+        }
+
         function getFontFamily(fontSettings) {
             var family = fontSettings && fontSettings.family ? fontSettings.family : 'Roboto';
             if (family === 'RobotoDraft') {
@@ -89,7 +113,7 @@ export default class TbAnalogueRadialGauge {
             maxValue: maxValue,
             majorTicks: majorTicks,
             minorTicks: settings.minorTicks || 2,
-            units: angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units,
+            units: getUnits(settings),
             title: ((settings.showUnitTitle !== false) ?
                 (settings.unitTitle && settings.unitTitle.length > 0 ?
                     settings.unitTitle : dataKey.label) : ''),
diff --git a/ui/src/app/widget/lib/canvas-digital-gauge.js b/ui/src/app/widget/lib/canvas-digital-gauge.js
index 33283ef..1290f5f 100644
--- a/ui/src/app/widget/lib/canvas-digital-gauge.js
+++ b/ui/src/app/widget/lib/canvas-digital-gauge.js
@@ -54,10 +54,13 @@ export default class TbCanvasDigitalGauge {
             this.localSettings.levelColors = settings.levelColors.slice();
         }
 
-        this.localSettings.decimals = (angular.isDefined(settings.decimals) && settings.decimals !== null)
-            ? settings.decimals : ctx.decimals;
+        this.localSettings.decimals = angular.isDefined(dataKey.decimals) ? dataKey.decimals :
+            ((angular.isDefined(settings.decimals) && settings.decimals !== null)
+            ? settings.decimals : ctx.decimals);
+
+        this.localSettings.units = dataKey.units && dataKey.units.length ? dataKey.units :
+            (angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units);
 
-        this.localSettings.units = angular.isDefined(settings.units) && settings.units.length > 0 ? settings.units : ctx.units;
         this.localSettings.hideValue = settings.showValue !== true;
         this.localSettings.hideMinMax = settings.showMinMax !== true;
 
diff --git a/ui/src/app/widget/lib/flot-widget.js b/ui/src/app/widget/lib/flot-widget.js
index af70de1..56eb278 100644
--- a/ui/src/app/widget/lib/flot-widget.js
+++ b/ui/src/app/widget/lib/flot-widget.js
@@ -104,8 +104,10 @@ export default class TbFlot {
 
         if (this.chartType === 'pie') {
             ctx.tooltipFormatter = function(item) {
+                var units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : tbFlot.ctx.trackUnits;
+                var decimals = angular.isDefined(item.series.dataKey.decimals) ? item.series.dataKey.decimals : tbFlot.ctx.trackDecimals;
                 var divElement = seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color,
-                    item.datapoint[1][0][1], tbFlot.ctx.trackUnits, tbFlot.ctx.trackDecimals, true, item.series.percent);
+                    item.datapoint[1][0][1], units, decimals, true, item.series.percent);
                 return divElement.prop('outerHTML');
             };
         } else {
@@ -127,18 +129,19 @@ export default class TbFlot {
                     if (tbFlot.ctx.tooltipIndividual && seriesHoverInfo.index !== seriesIndex) {
                         continue;
                     }
+                    var units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : tbFlot.ctx.trackUnits;
+                    var decimals = angular.isDefined(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : tbFlot.ctx.trackDecimals;
                     var divElement = seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color,
-                        seriesHoverInfo.value, tbFlot.ctx.trackUnits, tbFlot.ctx.trackDecimals, seriesHoverInfo.index === seriesIndex);
+                        seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex);
                     content += divElement.prop('outerHTML');
                 }
                 return content;
             };
         }
 
-        ctx.trackDecimals = angular.isDefined(settings.decimals) ?
-            settings.decimals : ctx.decimals;
+        ctx.trackDecimals = ctx.decimals;
 
-        ctx.trackUnits = angular.isDefined(settings.units) ? settings.units : ctx.units;
+        ctx.trackUnits = ctx.units;
 
         ctx.tooltipIndividual = this.chartType === 'pie' || (angular.isDefined(settings.tooltipIndividual) ? settings.tooltipIndividual : false);
         ctx.tooltipCumulative = angular.isDefined(settings.tooltipCumulative) ? settings.tooltipCumulative : false;
@@ -172,7 +175,7 @@ export default class TbFlot {
                 font: angular.copy(font),
                 labelFont: angular.copy(font)
             };
-            options.yaxis = {
+            this.yaxis = {
                 font: angular.copy(font),
                 labelFont: angular.copy(font)
             };
@@ -188,32 +191,33 @@ export default class TbFlot {
                 options.xaxis.labelFont.size = options.xaxis.font.size+2;
                 options.xaxis.labelFont.weight = "bold";
             }
-            if (settings.yaxis) {
+
+            ctx.yAxisTickFormatter = function(value/*, axis*/) {
                 if (settings.yaxis.showLabels === false) {
-                    options.yaxis.tickFormatter = function() {
-                        return '';
-                    };
-                } else if (ctx.trackUnits && ctx.trackUnits.length > 0) {
-                    options.yaxis.tickFormatter = function(value, axis) {
-                        var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1,
-                            formatted = "" + Math.round(value * factor) / factor;
-                        if (axis.tickDecimals != null) {
-                            var decimal = formatted.indexOf("."),
-                                precision = decimal === -1 ? 0 : formatted.length - decimal - 1;
-
-                            if (precision < axis.tickDecimals) {
-                                formatted = (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);
-                            }
-                        }
-                        formatted += ' ' + tbFlot.ctx.trackUnits;
-                        return formatted;
-                    };
+                    return '';
+                }
+                var factor = this.tickDecimals ? Math.pow(10, this.tickDecimals) : 1,
+                    formatted = "" + Math.round(value * factor) / factor;
+                if (this.tickDecimals != null) {
+                    var decimal = formatted.indexOf("."),
+                        precision = decimal === -1 ? 0 : formatted.length - decimal - 1;
+
+                    if (precision < this.tickDecimals) {
+                        formatted = (precision ? formatted : formatted + ".") + ("" + factor).substr(1, this.tickDecimals - precision);
+                    }
                 }
-                options.yaxis.font.color = settings.yaxis.color || options.yaxis.font.color;
-                options.yaxis.label = settings.yaxis.title || null;
-                options.yaxis.labelFont.color = options.yaxis.font.color;
-                options.yaxis.labelFont.size = options.yaxis.font.size+2;
-                options.yaxis.labelFont.weight = "bold";
+                formatted += ' ' + this.tickUnits;
+                return formatted;
+            }
+
+            this.yaxis.tickFormatter = ctx.yAxisTickFormatter;
+
+            if (settings.yaxis) {
+                this.yaxis.font.color = settings.yaxis.color || this.yaxis.font.color;
+                this.yaxis.label = settings.yaxis.title || null;
+                this.yaxis.labelFont.color = this.yaxis.font.color;
+                this.yaxis.labelFont.size = this.yaxis.font.size+2;
+                this.yaxis.labelFont.weight = "bold";
             }
 
             options.grid.borderWidth = 1;
@@ -229,7 +233,7 @@ export default class TbFlot {
                     options.xaxis.tickLength = 0;
                 }
                 if (settings.grid.horizontalLines === false) {
-                    options.yaxis.tickLength = 0;
+                    this.yaxis.tickLength = 0;
                 }
             }
 
@@ -311,6 +315,8 @@ export default class TbFlot {
         this.subscription = subscription;
         this.$element = $element;
         var colors = [];
+        this.yaxes = [];
+        var yaxesMap = {};
         for (var i = 0; i < this.subscription.data.length; i++) {
             var series = this.subscription.data[i];
             colors.push(series.dataKey.color);
@@ -342,8 +348,29 @@ export default class TbFlot {
 
             series.highlightColor = lineColor.toRgbString();
 
+            if (this.yaxis) {
+                var units = series.dataKey.units && series.dataKey.units.length ? series.dataKey.units : this.ctx.trackUnits;
+                var yaxis;
+                if (keySettings.showSeparateAxis) {
+                    yaxis = this.createYAxis(keySettings, units);
+                    this.yaxes.push(yaxis);
+                } else {
+                    yaxis = yaxesMap[units];
+                    if (!yaxis) {
+                        yaxis = this.createYAxis(keySettings, units);
+                        yaxesMap[units] = yaxis;
+                        this.yaxes.push(yaxis);
+                    }
+                }
+                series.yaxisIndex = this.yaxes.indexOf(yaxis);
+                series.yaxis = series.yaxisIndex+1;
+                yaxis.keysInfo[i] = {hidden: false};
+                yaxis.hidden = false;
+            }
         }
+
         this.options.colors = colors;
+        this.options.yaxes = angular.copy(this.yaxes);
         if (this.chartType === 'line' || this.chartType === 'bar') {
             if (this.chartType === 'bar') {
                 this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
@@ -373,6 +400,23 @@ export default class TbFlot {
         }
     }
 
+    createYAxis(keySettings, units) {
+        var yaxis = angular.copy(this.yaxis);
+
+        var label = keySettings.axisTitle && keySettings.axisTitle.length ? keySettings.axisTitle : yaxis.label;
+        var tickDecimals = angular.isDefined(keySettings.axisTickDecimals) ? keySettings.axisTickDecimals : 0;
+        var position = keySettings.axisPosition && keySettings.axisPosition.length ? keySettings.axisPosition : "left";
+
+        yaxis.label = label;
+        yaxis.tickUnits = units;
+        yaxis.tickDecimals = tickDecimals;
+        yaxis.alignTicksWithAxis = position == "right" ? 1 : null;
+        yaxis.position = position;
+
+        yaxis.keysInfo = [];
+        return yaxis;
+    }
+
     update() {
         if (this.updateTimeoutHandle) {
             this.ctx.$scope.$timeout.cancel(this.updateTimeoutHandle);
@@ -381,17 +425,64 @@ export default class TbFlot {
         if (this.subscription) {
             if (!this.isMouseInteraction && this.ctx.plot) {
                 if (this.chartType === 'line' || this.chartType === 'bar') {
+
+                    var axisVisibilityChanged = false;
+                    if (this.yaxis) {
+                        for (var i = 0; i < this.subscription.data.length; i++) {
+                            var series = this.subscription.data[i];
+                            var yaxisIndex = series.yaxisIndex;
+                            if (this.yaxes[yaxisIndex].keysInfo[i].hidden != series.dataKey.hidden) {
+                                this.yaxes[yaxisIndex].keysInfo[i].hidden = series.dataKey.hidden;
+                                axisVisibilityChanged = true;
+                            }
+                        }
+                        if (axisVisibilityChanged) {
+                            this.options.yaxes.length = 0;
+                            for (var y = 0; y < this.yaxes.length; y++) {
+                                var yaxis = this.yaxes[y];
+                                var hidden = true;
+                                for (var k = 0; k < yaxis.keysInfo.length; k++) {
+                                    if (yaxis.keysInfo[k]) {
+                                        hidden = hidden && yaxis.keysInfo[k].hidden;
+                                    }
+                                }
+                                yaxis.hidden = hidden
+                                var newIndex = -1;
+                                if (!yaxis.hidden) {
+                                    this.options.yaxes.push(yaxis);
+                                    newIndex = this.options.yaxes.length;
+                                }
+                                for (k = 0; k < yaxis.keysInfo.length; k++) {
+                                    if (yaxis.keysInfo[k]) {
+                                        this.subscription.data[k].yaxis = newIndex;
+                                    }
+                                }
+
+                            }
+                            this.options.yaxis = {
+                                show: this.options.yaxes.length ? true : false
+                            };
+                        }
+                    }
+
                     this.options.xaxis.min = this.subscription.timeWindow.minTime;
                     this.options.xaxis.max = this.subscription.timeWindow.maxTime;
-                    this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime;
-                    this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime;
                     if (this.chartType === 'bar') {
                         this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
-                        this.ctx.plot.getOptions().series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
                     }
-                    this.ctx.plot.setData(this.subscription.data);
-                    this.ctx.plot.setupGrid();
-                    this.ctx.plot.draw();
+
+                    if (axisVisibilityChanged) {
+                        this.redrawPlot();
+                    } else {
+                        this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime;
+                        this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime;
+                        if (this.chartType === 'bar') {
+                            this.ctx.plot.getOptions().series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
+                        }
+                        this.ctx.plot.setData(this.subscription.data);
+                        this.ctx.plot.setupGrid();
+                        this.ctx.plot.draw();
+                    }
                 } else if (this.chartType === 'pie') {
                     if (this.ctx.animatedPie) {
                         this.nextPieDataAnimation(true);
@@ -720,6 +811,26 @@ export default class TbFlot {
                         "title": "Show points",
                             "type": "boolean",
                             "default": false
+                    },
+                    "showSeparateAxis": {
+                        "title": "Show separate axis",
+                        "type": "boolean",
+                        "default": false
+                    },
+                    "axisTitle": {
+                        "title": "Axis title",
+                        "type": "string",
+                        "default": ""
+                    },
+                    "axisTickDecimals": {
+                        "title": "Axis tick number of digits after floating point",
+                        "type": "number",
+                        "default": 0
+                    },
+                    "axisPosition": {
+                        "title": "Axis position",
+                        "type": "string",
+                        "default": "left"
                     }
                 },
                 "required": ["showLines", "fillLines", "showPoints"]
@@ -727,7 +838,26 @@ export default class TbFlot {
                 "form": [
                 "showLines",
                 "fillLines",
-                "showPoints"
+                "showPoints",
+                "showSeparateAxis",
+                "axisTitle",
+                "axisTickDecimals",
+                {
+                    "key": "axisPosition",
+                    "type": "rc-select",
+                    "multiple": false,
+                    "items": [
+                        {
+                            "value": "left",
+                            "label": "Left"
+                        },
+                        {
+                            "value": "right",
+                            "label": "Right"
+                        }
+                    ]
+                }
+
             ]
         }
     }
@@ -754,6 +884,17 @@ export default class TbFlot {
         }
     }
 
+    redrawPlot() {
+        if (this.ctx.plot) {
+            this.ctx.plot.destroy();
+            if (this.chartType === 'pie' && this.ctx.animatedPie) {
+                this.ctx.plot = $.plot(this.$element, this.pieData, this.options);
+            } else {
+                this.ctx.plot = $.plot(this.$element, this.subscription.data, this.options);
+            }
+        }
+    }
+
     destroy() {
         if (this.ctx.plot) {
             this.ctx.plot.destroy();
@@ -968,6 +1109,8 @@ export default class TbFlot {
                     hoverIndex: hoverIndex,
                     color: series.dataKey.color,
                     label: series.dataKey.label,
+                    units: series.dataKey.units,
+                    decimals: series.dataKey.decimals,
                     time: pointTime,
                     distance: hoverDistance,
                     index: i