thingsboard-aplcache
Changes
ui/src/app/api/widget.service.js 4(+3 -1)
ui/src/app/widget/lib/CanvasDigitalGauge.js 38(+31 -7)
ui/src/app/widget/lib/rpc/index.js 21(+21 -0)
ui/src/app/widget/lib/rpc/knob.directive.js 388(+388 -0)
ui/src/app/widget/lib/rpc/knob.scss 157(+157 -0)
ui/src/app/widget/lib/rpc/knob.svg 36(+36 -0)
ui/src/app/widget/lib/rpc/knob.tpl.html 46(+46 -0)
Details
diff --git a/application/src/main/data/json/system/widget_bundles/control_widgets.json b/application/src/main/data/json/system/widget_bundles/control_widgets.json
index ff920b1..b05a144 100644
--- a/application/src/main/data/json/system/widget_bundles/control_widgets.json
+++ b/application/src/main/data/json/system/widget_bundles/control_widgets.json
@@ -36,6 +36,22 @@
"dataKeySettingsSchema": "{}\n",
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC remote shell\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
}
+ },
+ {
+ "alias": "knob_control",
+ "name": "Knob Control",
+ "descriptor": {
+ "type": "rpc",
+ "sizeX": 5,
+ "sizeY": 4.5,
+ "resources": [],
+ "templateHtml": "<tb-knob ctx='ctx'></tb-knob>",
+ "templateCss": "",
+ "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n",
+ "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"title\": {\n \"title\": \"Knob title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"Set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"minValue\", \"maxValue\", \"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"title\",\n \"requestTimeout\"\n ]\n}",
+ "dataKeySettingsSchema": "{}\n",
+ "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"maxValue\":100,\"initialValue\":50,\"minValue\":0,\"title\":\"Knob control\"},\"title\":\"Knob Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}"
+ }
}
]
}
\ No newline at end of file
ui/src/app/api/widget.service.js 4(+3 -1)
diff --git a/ui/src/app/api/widget.service.js b/ui/src/app/api/widget.service.js
index 8580b80..842b976 100644
--- a/ui/src/app/api/widget.service.js
+++ b/ui/src/app/api/widget.service.js
@@ -22,6 +22,8 @@ import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-wid
import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget';
import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget';
+import thingsboardRpcWidgets from '../widget/lib/rpc';
+
import TbFlot from '../widget/lib/flot-widget';
import TbAnalogueLinearGauge from '../widget/lib/analogue-linear-gauge';
import TbAnalogueRadialGauge from '../widget/lib/analogue-radial-gauge';
@@ -39,7 +41,7 @@ import thingsboardTypes from '../common/types.constant';
import thingsboardUtils from '../common/utils.service';
export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, thingsboardTimeseriesTableWidget,
- thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, thingsboardTypes, thingsboardUtils])
+ thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, thingsboardRpcWidgets, thingsboardTypes, thingsboardUtils])
.factory('widgetService', WidgetService)
.name;
diff --git a/ui/src/app/components/widget/widget.controller.js b/ui/src/app/components/widget/widget.controller.js
index 1efbf7f..f9ff7a6 100644
--- a/ui/src/app/components/widget/widget.controller.js
+++ b/ui/src/app/components/widget/widget.controller.js
@@ -811,14 +811,17 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
return (val - parseFloat( val ) + 1) >= 0;
}
- function formatValue(value, dec, units) {
+ function formatValue(value, dec, units, showZeroDecimals) {
if (angular.isDefined(value) &&
value !== null && isNumeric(value)) {
var formatted = Number(value);
if (angular.isDefined(dec)) {
formatted = formatted.toFixed(dec);
}
- formatted = (formatted * 1).toString();
+ if (!showZeroDecimals) {
+ formatted = (formatted * 1);
+ }
+ formatted = formatted.toString();
if (angular.isDefined(units) && units.length > 0) {
formatted += ' ' + units;
}
ui/src/app/widget/lib/CanvasDigitalGauge.js 38(+31 -7)
diff --git a/ui/src/app/widget/lib/CanvasDigitalGauge.js b/ui/src/app/widget/lib/CanvasDigitalGauge.js
index e51c558..08a54d8 100644
--- a/ui/src/app/widget/lib/CanvasDigitalGauge.js
+++ b/ui/src/app/widget/lib/CanvasDigitalGauge.js
@@ -95,6 +95,15 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge {
options.value = options.minValue;
}
+ if (options.gaugeType === 'donut') {
+ if (!options.donutStartAngle) {
+ options.donutStartAngle = 1.5 * Math.PI;
+ }
+ if (!options.donutEndAngle) {
+ options.donutEndAngle = options.donutStartAngle + 2 * Math.PI;
+ }
+ }
+
var colorsCount = options.levelColors.length;
var inc = colorsCount > 1 ? (1 / (colorsCount - 1)) : 1;
options.colorsRange = [];
@@ -232,6 +241,21 @@ export default class CanvasDigitalGauge extends canvasGauges.BaseGauge {
return this;
}
+ getValueColor() {
+ if (this.contextProgressClone) {
+ var color = this.contextProgressClone.currentColor;
+ if (!color) {
+ if (this.options.neonGlowBrightness) {
+ color = getProgressColor(0, this.options.neonColorsRange);
+ } else {
+ color = getProgressColor(0, this.options.colorsRange);
+ }
+ }
+ return color;
+ } else {
+ return '#000';
+ }
+ }
}
/* eslint-disable angular/document-service */
@@ -473,7 +497,7 @@ function drawBackground(context, options) {
context.lineCap = 'round';
}
if (options.gaugeType === 'donut') {
- context.arc(context.barDimensions.Cx, context.barDimensions.Cy, context.barDimensions.Rm, 1.5 * Math.PI, 3.5 * Math.PI);
+ context.arc(context.barDimensions.Cx, context.barDimensions.Cy, context.barDimensions.Rm, options.donutStartAngle, options.donutEndAngle);
context.stroke();
} else if (options.gaugeType === 'arc') {
context.arc(context.barDimensions.Cx, context.barDimensions.Cy, context.barDimensions.Rm, Math.PI, 2*Math.PI);
@@ -605,7 +629,7 @@ function getProgressColor(progress, colorsRange) {
}
}
-function drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, color, progress, isDonut) {
+function drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, color, progress, isDonut, donutStartAngle, donutEndAngle) {
context.setLineDash([]);
var strokeWidth = Ro - Ri;
var blur = 0.55;
@@ -623,7 +647,7 @@ function drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, color, progress, isDonut) {
context.beginPath();
var e = 0.01 * Math.PI;
if (isDonut) {
- context.arc(Cx, Cy, Rm, 1.5 * Math.PI - e, 1.5 * Math.PI + 2 * Math.PI * progress + e);
+ context.arc(Cx, Cy, Rm, donutStartAngle - e, donutStartAngle + (donutEndAngle - donutStartAngle) * progress + e);
} else {
context.arc(Cx, Cy, Rm, Math.PI - e, Math.PI + Math.PI * progress + e);
}
@@ -660,9 +684,9 @@ function drawBarGlow(context, startX, startY, endX, endY, color, strokeWidth, is
function drawProgress(context, options, progress) {
var neonColor;
if (options.neonGlowBrightness) {
- neonColor = getProgressColor(progress, options.neonColorsRange);
+ context.currentColor = neonColor = getProgressColor(progress, options.neonColorsRange);
} else {
- context.strokeStyle = getProgressColor(progress, options.colorsRange);
+ context.currentColor = context.strokeStyle = getProgressColor(progress, options.colorsRange);
}
let {barLeft, barRight, barTop, baseX, width, barBottom, Cx, Cy, Rm, Ro, Ri, strokeWidth} =
@@ -682,10 +706,10 @@ function drawProgress(context, options, progress) {
context.strokeStyle = neonColor;
}
context.beginPath();
- context.arc(Cx, Cy, Rm, 1.5 * Math.PI, 1.5 * Math.PI + 2 * Math.PI * progress);
+ context.arc(Cx, Cy, Rm, options.donutStartAngle, options.donutStartAngle + (options.donutEndAngle - options.donutStartAngle) * progress);
context.stroke();
if (options.neonGlowBrightness && !options.isMobile) {
- drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, true);
+ drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, true, options.donutStartAngle, options.donutEndAngle);
}
} else if (options.gaugeType === 'arc') {
if (options.neonGlowBrightness) {
ui/src/app/widget/lib/rpc/index.js 21(+21 -0)
diff --git a/ui/src/app/widget/lib/rpc/index.js b/ui/src/app/widget/lib/rpc/index.js
new file mode 100644
index 0000000..ba07eee
--- /dev/null
+++ b/ui/src/app/widget/lib/rpc/index.js
@@ -0,0 +1,21 @@
+/*
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import tbKnob from './knob.directive';
+
+export default angular.module('thingsboard.widgets.rpc', [
+ tbKnob
+]).name;
ui/src/app/widget/lib/rpc/knob.directive.js 388(+388 -0)
diff --git a/ui/src/app/widget/lib/rpc/knob.directive.js b/ui/src/app/widget/lib/rpc/knob.directive.js
new file mode 100644
index 0000000..d62d0fb
--- /dev/null
+++ b/ui/src/app/widget/lib/rpc/knob.directive.js
@@ -0,0 +1,388 @@
+/*
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import './knob.scss';
+
+import CanvasDigitalGauge from './../CanvasDigitalGauge';
+import tinycolor from 'tinycolor2';
+
+import { isNumber } from '../widget-utils';
+
+/* eslint-disable import/no-unresolved, import/default */
+
+import knobTemplate from './knob.tpl.html';
+
+/* eslint-enable import/no-unresolved, import/default */
+
+export default angular.module('thingsboard.widgets.rpc.knob', [])
+ .directive('tbKnob', Knob)
+ .name;
+
+/*@ngInject*/
+function Knob() {
+ return {
+ restrict: "E",
+ scope: true,
+ bindToController: {
+ ctx: '='
+ },
+ controller: KnobController,
+ controllerAs: 'vm',
+ templateUrl: knobTemplate
+ };
+}
+
+/*@ngInject*/
+function KnobController($element, $scope, $document) {
+ let vm = this;
+
+ vm.value = 0;
+ vm.error = '';
+
+ var knob = angular.element('.knob', $element),
+ knobContainer = angular.element('#knob-container', $element),
+ knobTopPointerContainer = knob.find('.top-pointer-container'),
+ knobTopPointer = knob.find('.top-pointer'),
+ knobValueContainer = knob.find('.value-container'),
+ knobValue = knob.find('.knob-value'),
+ knobErrorContainer = knob.find('.error-container'),
+ knobError = knob.find('.knob-error'),
+ knobTitleContainer = knob.find('.title-container'),
+ knobTitle = knob.find('.knob-title'),
+ knobMinmaxContainer = knob.find('.minmax-container'),
+ minmaxLanel = knob.find('.minmax-label'),
+ textMeasure = knob.find('#text-measure'),
+ startDeg = -1,
+ currentDeg = 0,
+ rotation = 0,
+ lastDeg = 0,
+ moving = false;
+
+ var minDeg = -45;
+ var maxDeg = 225;
+
+ var canvasBarElement = angular.element('#canvasBar', $element);
+
+ var levelColors = ['#19ff4b', '#ffff19', '#ff3232'];
+
+ var canvasBar;
+
+ $scope.$watch('vm.ctx', () => {
+ if (vm.ctx) {
+ init();
+ }
+ });
+
+ function init() {
+
+ vm.minValue = angular.isDefined(vm.ctx.settings.minValue) ? vm.ctx.settings.minValue : 0;
+ vm.maxValue = angular.isDefined(vm.ctx.settings.maxValue) ? vm.ctx.settings.maxValue : 100;
+ vm.title = angular.isDefined(vm.ctx.settings.title) ? vm.ctx.settings.title : '';
+
+ vm.darkTheme = vm.ctx.settings.theme == 'dark';
+
+ var canvasBarData = {
+ renderTo: canvasBarElement[0],
+ hideValue: true,
+ neonGlowBrightness: 0,
+ gaugeWidthScale: 0.4,
+ gaugeColor: 'rgba(0, 0, 0, 0)',
+ levelColors: levelColors,
+ minValue: vm.minValue,
+ maxValue: vm.maxValue,
+ gaugeType: 'donut',
+ dashThickness: 2,
+ donutStartAngle: 3/4*Math.PI,
+ donutEndAngle: 9/4*Math.PI,
+ animation: false
+ };
+
+ canvasBar = new CanvasDigitalGauge(canvasBarData).draw();
+
+ knob.on('click', (e) => {
+ if (moving) {
+ moving = false;
+ return false;
+ }
+ e.preventDefault();
+
+ var offset = knob.offset();
+ var center = {
+ y : offset.top + knob.height()/2,
+ x: offset.left + knob.width()/2
+ };
+ var a, b, deg,
+ rad2deg = 180/Math.PI;
+
+ e = (e.originalEvent.touches) ? e.originalEvent.touches[0] : e;
+
+ a = center.y - e.pageY;
+ b = center.x - e.pageX;
+ deg = Math.atan2(a,b)*rad2deg;
+ if(deg < 0){
+ deg = 360 + deg;
+ }
+ if (deg > maxDeg) {
+ if (deg - 360 > minDeg) {
+ deg = deg - 360;
+ } else {
+ return false;
+ }
+ }
+ currentDeg = deg;
+ lastDeg = deg;
+ knobTopPointerContainer.css('transform','rotate('+(currentDeg)+'deg)');
+ turn(degreeToRatio(currentDeg));
+ rotation = currentDeg;
+ startDeg = -1;
+ });
+
+ knob.on('mousedown touchstart', (e) => {
+ e.preventDefault();
+ var offset = knob.offset();
+ var center = {
+ y : offset.top + knob.height()/2,
+ x: offset.left + knob.width()/2
+ };
+
+ var a, b, deg, tmp,
+ rad2deg = 180/Math.PI;
+
+ knob.on('mousemove.rem touchmove.rem', (e) => {
+ moving = true;
+ e = (e.originalEvent.touches) ? e.originalEvent.touches[0] : e;
+
+ a = center.y - e.pageY;
+ b = center.x - e.pageX;
+ deg = Math.atan2(a,b)*rad2deg;
+ if(deg < 0){
+ deg = 360 + deg;
+ }
+
+ if(startDeg == -1){
+ startDeg = deg;
+ }
+
+ tmp = Math.floor((deg-startDeg) + rotation);
+
+ if(tmp < 0){
+ tmp = 360 + tmp;
+ }
+ else if(tmp > 359){
+ tmp = tmp % 360;
+ }
+
+ if (tmp > maxDeg) {
+ if (tmp - 360 > minDeg) {
+ tmp = tmp - 360;
+ } else {
+ var deltaMax = Math.abs(maxDeg - lastDeg);
+ var deltaMin = Math.abs(minDeg - lastDeg);
+ if (deltaMax < deltaMin) {
+ tmp = maxDeg;
+ } else {
+ tmp = minDeg;
+ }
+ }
+ }
+ if(Math.abs(tmp - lastDeg) > 180){
+ startDeg = deg;
+ rotation = currentDeg;
+ return false;
+ }
+
+ currentDeg = tmp;
+ lastDeg = tmp;
+
+ knobTopPointerContainer.css('transform','rotate('+(currentDeg)+'deg)');
+ turn(degreeToRatio(currentDeg));
+ });
+
+ $document.on('mouseup.rem touchend.rem',() => {
+ knob.off('.rem');
+ $document.off('.rem');
+ rotation = currentDeg;
+ startDeg = -1;
+ });
+
+ });
+ vm.ctx.resize = resize;
+ resize();
+ var initialValue = angular.isDefined(vm.ctx.settings.initialValue) ? vm.ctx.settings.initialValue : vm.minValue;
+ setValue(initialValue);
+
+ var subscription = vm.ctx.defaultSubscription;
+ var rpcEnabled = subscription.rpcEnabled;
+
+ vm.isSimulated = $scope.widgetEditMode;
+
+ vm.requestTimeout = 500;
+ if (vm.ctx.settings.requestTimeout) {
+ vm.requestTimeout = vm.ctx.settings.requestTimeout;
+ }
+ vm.getValueMethod = 'getValue';
+ if (vm.ctx.settings.getValueMethod && vm.ctx.settings.getValueMethod.length) {
+ vm.getValueMethod = vm.ctx.settings.getValueMethod;
+ }
+ vm.setValueMethod = 'setValue';
+ if (vm.ctx.settings.setValueMethod && vm.ctx.settings.setValueMethod.length) {
+ vm.setValueMethod = vm.ctx.settings.setValueMethod;
+ }
+ if (!rpcEnabled) {
+ onError('Target device is not set!');
+ } else {
+ if (!vm.isSimulated) {
+ rpcRequestValue();
+ }
+ }
+ }
+
+ function ratioToDegree(ratio) {
+ return minDeg + ratio*(maxDeg-minDeg);
+ }
+
+ function degreeToRatio(degree) {
+ return (degree-minDeg)/(maxDeg-minDeg);
+ }
+
+ function resize() {
+ var width = knobContainer.width();
+ var height = knobContainer.height();
+ var size = Math.min(width, height);
+ knob.css({width: size, height: size});
+ canvasBar.update({width: size, height: size});
+ setFontSize(knobTitle, vm.title, knobTitleContainer.height(), knobTitleContainer.width());
+ setFontSize(knobError, vm.error, knobErrorContainer.height(), knobErrorContainer.width());
+ var minmaxHeight = knobMinmaxContainer.height();
+ minmaxLanel.css({'fontSize': minmaxHeight+'px', 'lineHeight': minmaxHeight+'px'});
+ checkValueSize();
+ }
+
+ function turn(ratio) {
+ var value = (vm.minValue + (vm.maxValue - vm.minValue)*ratio).toFixed(vm.ctx.decimals);
+ if (canvasBar.value != value) {
+ canvasBar.value = value;
+ }
+ updateColor(canvasBar.getValueColor());
+ onValue(value);
+ }
+
+ function setValue(value) {
+ var ratio = (value-vm.minValue) / (vm.maxValue - vm.minValue);
+ rotation = lastDeg = currentDeg = ratioToDegree(ratio);
+ knobTopPointerContainer.css('transform','rotate('+(currentDeg)+'deg)');
+ if (canvasBar.value != value) {
+ canvasBar.value = value;
+ }
+ updateColor(canvasBar.getValueColor());
+ vm.value = formatValue(value);
+ checkValueSize();
+ }
+
+ function updateColor(color) {
+ var glowColor = tinycolor(color).brighten(30).toHexString();
+ knobValue.css({'color': glowColor});
+ var textShadow = `${color} 1px 1px 10px, ${glowColor} 1px 1px 10px`;
+ knobValue.css({'textShadow': textShadow});
+ knobTopPointer.css({'backgroundColor': glowColor});
+ var boxShadow = `inset 1px 0 2px #040404, 1px 1px 8px 2px ${glowColor}`;
+ knobTopPointer.css({'boxShadow': boxShadow});
+ }
+
+ function onValue(value) {
+ $scope.$applyAsync(() => {
+ vm.value = formatValue(value);
+ checkValueSize();
+ rpcUpdateValue(value);
+ });
+ }
+
+ function onError(error) {
+ $scope.$applyAsync(() => {
+ vm.error = error;
+ setFontSize(knobError, vm.error, knobErrorContainer.height(), knobErrorContainer.width());
+ });
+ }
+
+ function formatValue(value) {
+ return vm.ctx.utils.formatValue(value, vm.ctx.decimals, vm.ctx.units, true);
+ }
+
+ function checkValueSize() {
+ var fontSize = knobValueContainer.height()/3.3;
+ var containerWidth = knobValueContainer.width();
+ setFontSize(knobValue, vm.value, fontSize, containerWidth);
+ }
+
+ function setFontSize(element, text, fontSize, maxWidth) {
+ var textWidth = measureTextWidth(text, fontSize);
+ while (textWidth > maxWidth) {
+ fontSize--;
+ textWidth = measureTextWidth(text, fontSize);
+ }
+ element.css({'fontSize': fontSize+'px', 'lineHeight': fontSize+'px'});
+ }
+
+ function measureTextWidth(text, fontSize) {
+ textMeasure.css({'fontSize': fontSize+'px', 'lineHeight': fontSize+'px'});
+ textMeasure.text(text);
+ return textMeasure.width();
+ }
+
+ function rpcRequestValue() {
+ vm.error = '';
+ vm.ctx.controlApi.sendTwoWayCommand(vm.getValueMethod, null, vm.requestTimeout).then(
+ (responseBody) => {
+ if (isNumber(responseBody)) {
+ var numValue = Number(responseBody).toFixed(vm.ctx.decimals);
+ setValue(numValue);
+ } else {
+ var errorText = `Unable to parse response: ${responseBody}`;
+ onError(errorText);
+ }
+ },
+ () => {
+ var errorText = vm.ctx.defaultSubscription.rpcErrorText;
+ onError(errorText);
+ }
+ );
+ }
+
+ function rpcUpdateValue(value) {
+ if (vm.executingUpdateValue) {
+ vm.scheduledValue = value;
+ return;
+ } else {
+ vm.scheduledValue = null;
+ vm.rpcValue = value;
+ vm.executingUpdateValue = true;
+ }
+ vm.error = '';
+ vm.ctx.controlApi.sendOneWayCommand(vm.setValueMethod, value, vm.requestTimeout).then(
+ () => {
+ vm.executingUpdateValue = false;
+ if (vm.scheduledValue != null && vm.scheduledValue != vm.rpcValue) {
+ rpcUpdateValue(vm.scheduledValue);
+ }
+ },
+ () => {
+ vm.executingUpdateValue = false;
+ var errorText = vm.ctx.defaultSubscription.rpcErrorText;
+ onError(errorText);
+ }
+ );
+ }
+}
ui/src/app/widget/lib/rpc/knob.scss 157(+157 -0)
diff --git a/ui/src/app/widget/lib/rpc/knob.scss b/ui/src/app/widget/lib/rpc/knob.scss
new file mode 100644
index 0000000..3e57f66
--- /dev/null
+++ b/ui/src/app/widget/lib/rpc/knob.scss
@@ -0,0 +1,157 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+$knob-img: url('./knob.svg');
+
+$bars-margin-pct: percentage(0.033);
+$background-margin-pct: percentage(0.05);
+$value-container-margin-pct: percentage(0.35);
+$error-height: percentage(0.05);
+$title-height: percentage(0.066);
+$title-container-margin-pct: percentage(0.2);
+$title-container-margin-bottom-pct: percentage(0.05);
+$minmax-height: percentage(0.04);
+$minmax-container-margin-pct: percentage(0.18);
+$minmax-container-margin-bottom-pct: percentage(0.12);
+
+$background-color: #e6e7e8;
+
+.tb-knob {
+ width:100%;
+ height:100%;
+ background: $background-color;
+ &.dark {
+ background: #000;
+ }
+
+ .knob {
+ position: relative;
+ &[draggable] {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ }
+ #canvasBar {
+ position:absolute;
+ top:0;
+ left:0;
+ bottom: 0;
+ right: 0;
+ z-index: 2;
+ }
+ .canvas-background {
+ position:absolute;
+ top: $background-margin-pct;
+ left: $background-margin-pct;
+ bottom: $background-margin-pct;
+ right: $background-margin-pct;
+ border-radius: 50%;
+ background: #3f4346;
+ z-index:2;
+ }
+ .value-container {
+ position:absolute;
+ top: $value-container-margin-pct;
+ left: $value-container-margin-pct;
+ bottom: $value-container-margin-pct;
+ right: $value-container-margin-pct;
+ z-index:4;
+ .knob-value {
+ color: #fff;
+ font-weight: 500;
+ white-space: nowrap;
+ }
+ }
+ .error-container {
+ position:absolute;
+ top: 1%;
+ left: 0;
+ right: 0;
+ z-index:4;
+ height: $error-height;
+ .knob-error {
+ color: #ff3315;
+ white-space: nowrap;
+ }
+ }
+ .title-container {
+ position:absolute;
+ left: $title-container-margin-pct;
+ bottom: $title-container-margin-bottom-pct;
+ right: $title-container-margin-pct;
+ z-index:4;
+ height: $title-height;
+ .knob-title {
+ color: #757575;
+ font-weight: 500;
+ white-space: nowrap;
+ }
+ }
+ .minmax-container {
+ position:absolute;
+ left: $minmax-container-margin-pct;
+ bottom: $minmax-container-margin-bottom-pct;
+ right: $minmax-container-margin-pct;
+ z-index:4;
+ height: $minmax-height;
+ .minmax-label {
+ color: #757575;
+ font-weight: 500;
+ white-space: nowrap;
+ }
+ }
+ .top-pointer-container {
+ position:absolute;
+ top: $bars-margin-pct;
+ left: $bars-margin-pct;
+ bottom: $bars-margin-pct;
+ right: $bars-margin-pct;
+ z-index:3;
+ cursor:pointer !important;
+ .top-pointer {
+ content:'';
+ width:5%;
+ height:5%;
+ background-color:#b5b5b5;
+ position:absolute;
+ top:50%;
+ left:22%;
+ margin-top:-2.5%;
+ border-radius: 50%;
+ cursor:pointer !important;
+ box-shadow: 1px 0 2px #040404;
+ }
+ }
+ .top{
+ position:absolute;
+ top: $bars-margin-pct;
+ left: $bars-margin-pct;
+ bottom: $bars-margin-pct;
+ right: $bars-margin-pct;
+ background:$knob-img no-repeat;
+ background-size: contain;
+ z-index:2;
+ cursor:pointer !important;
+ }
+ #text-measure {
+ position: absolute;
+ visibility: hidden;
+ height: auto;
+ width: auto;
+ white-space: nowrap;
+ }
+ }
+}
ui/src/app/widget/lib/rpc/knob.svg 36(+36 -0)
diff --git a/ui/src/app/widget/lib/rpc/knob.svg b/ui/src/app/widget/lib/rpc/knob.svg
new file mode 100644
index 0000000..81fe994
--- /dev/null
+++ b/ui/src/app/widget/lib/rpc/knob.svg
@@ -0,0 +1,36 @@
+<svg id="svg4451" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="28.222mm" width="28.222mm" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100.00001 100.00001" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs id="defs4453">
+ <linearGradient id="linearGradient4197">
+ <stop id="stop4199" stop-color="#878990" offset="0"/>
+ <stop id="stop4201" stop-color="#f6f6f6" offset="1"/>
+ </linearGradient>
+ <radialGradient id="radialGradient52746-0-4-0" gradientUnits="userSpaceOnUse" cy="991.7" cx="1007" gradientTransform="matrix(-.0050064 -.58050 1.8349 -.015825 -2300 975.09)" r="86.621">
+ <stop id="stop4169" stop-color="#bcbdc1" offset="0"/>
+ <stop id="stop4171" stop-color="#dfdfdf" offset="1"/>
+ </radialGradient>
+ <radialGradient id="radialGradient52746-0-9-15-6" xlink:href="#linearGradient4197" gradientUnits="userSpaceOnUse" cy="991.7" cx="1007" gradientTransform="matrix(-.0053377 -.61891 1.9563 -.016872 -2420 1016.8)" r="86.621"/>
+ <radialGradient id="radialGradient52746-0-9-6-5-6" gradientUnits="userSpaceOnUse" cy="991.7" cx="1007" gradientTransform="matrix(.0058230 .80069 -2.1343 .015521 1622.1 -511.53)" r="86.621">
+ <stop id="stop4270" stop-color="#8c8d93" offset="0"/>
+ <stop id="stop4272" stop-color="#fff" offset="1"/>
+ </radialGradient>
+ <radialGradient id="radialGradient52746-0-9-1-0-9" xlink:href="#linearGradient4197" gradientUnits="userSpaceOnUse" cy="991.7" cx="1007" gradientTransform="matrix(.0031272 .36260 -1.1462 .0098849 645.7 -48.682)" r="86.621"/>
+ <linearGradient id="linearGradient4424" y2="392.18" gradientUnits="userSpaceOnUse" x2="-369.32" gradientTransform="translate(109.7 -2.7245)" y1="293.68" x1="-370.65">
+ <stop id="stop4418" stop-color="#a0a0a0" offset="0"/>
+ <stop id="stop4420" stop-color="#f9faff" offset="1"/>
+ </linearGradient>
+ </defs>
+ <g id="layer1" transform="translate(536.86 -294.93)">
+ <g id="g4501">
+ <g id="g4497" transform="translate(-226.72 4.7227)">
+ <path id="path4414" d="m-260.16 290.67c-19.168-0.22115-37.725 11.849-45.288 29.465-7.973 17.434-4.4546 39.289 8.5831 53.342 12.841 14.512 34.573 20.101 52.82 13.575 18.4-6.082 32.096-23.857 33.289-43.199 1.6579-19.306-9.2817-38.901-26.591-47.615-7.0119-3.6494-14.91-5.5689-22.813-5.5679zm-0.51367 1.6641c18.978-0.21524 37.342 12.022 44.334 29.683 7.0372 17.181 2.95 38.084-9.5553 51.571-0.23129 0.19903-0.58514 0.91551-1.3667 0.57275-0.78156-0.34279-1.868-1.5334-2.5677-2.2508-1.3313-1.365-2.7517-2.5318-1.8623-3.5091 12.362-14.017 15.466-38.947 4.3865-53.994-10.077-14.664-29.972-21.296-46.858-15.752-18.125 5.321-32.394 23.295-31.109 42.522 0.68609 11.361 4.9096 22.828 13.013 30.964-0.52732 1.3864-0.75912 1.4951-2.0893 0.0445-1.4184-1.5468-2.8292-3.0416-5.2228-6.3838-8.8447-13.499-10.547-31.498-3.5798-46.167 6.8006-15.182 22.122-26.317 38.859-27.17 1.2041-0.086 2.4112-0.12896 3.6183-0.13085zm0.43164 28.711c2.6603-0.033 5.7995 0.63181 8.3618 1.8928 2.8152 1.323 5.3991 3.5094 7.1657 5.9467 2.9779 3.9517 4.2346 9.3635 3.5431 13.916-0.63605 5.0851-3.5977 9.93-7.6444 12.856-3.9009 2.9596-9.319 4.2271-13.796 3.5723-4.2078-0.54147-8.0926-2.4558-11.106-5.4642-2.8389-2.8421-4.7656-6.5461-5.3997-10.683-0.41578-2.8552-0.25913-5.5483 0.6416-8.5235 1.1448-3.8517 3.7847-7.4885 6.9779-9.7904 3.1737-2.373 7.3574-3.7297 11.256-3.7236zm-1.7148 0.0859c-0.0536 0.002-0.008 0.009 0 0zm-1.3984 0.18359c-0.0331 0.002-0.002 0.009 0 0zm-13.438 9.377c-0.0247 0.0373 0.004 0.009 0 0zm-0.44727 0.82812c-0.0259 0.0476 0.005 0.009 0 0zm-0.76953 1.7168c-0.0202 0.0478 0.005 0.009 0 0zm-0.71875 2.2363c-0.0164 0.0555 0.006 0.0119 0 0zm-0.50977 6.5332c0.001 0.0536 0.009 0.008 0 0zm0.1836 1.3984c0.003 0.0311 0.008 0.005 0 0zm9.377 13.438c0.0373 0.0247 0.009-0.004 0 0zm0.82812 0.44726c0.0476 0.0259 0.009-0.005 0 0zm1.7168 0.76953c0.0478 0.0202 0.009-0.005 0 0zm2.2363 0.71875c0.0555 0.0164 0.012-0.006 0 0zm6.5332 0.50977c0.0536-0.002 0.008-0.009 0 0zm1.3984-0.1836c0.0331-0.002 0.002-0.009 0 0zm13.438-9.377c0.0247-0.0373-0.004-0.009 0 0zm0.44727-0.82812c0.0259-0.0476-0.005-0.009 0 0zm0.76953-1.7168c0.0202-0.0478-0.005-0.009 0 0zm0.71875-2.2363c0.0164-0.0555-0.006-0.012 0 0zm0.50976-6.5332c-0.002-0.0536-0.009-0.008 0 0zm-0.18359-1.3984c-0.003-0.0311-0.008-0.005 0 0zm-9.377-13.438c-0.0373-0.0247-0.009 0.004 0 0zm-0.82813-0.44726c-0.0476-0.026-0.009 0.005 0 0zm-1.7168-0.76954c-0.0478-0.0202-0.009 0.005 0 0zm-2.2363-0.71875c-0.0555-0.0164-0.012 0.006 0 0zm-20.057 7.7695c-0.0145 0.004 0.008 0.0219 0 0zm-2.6172 16.232 0.006 0.008zm33.26 5.3555 0.002 0.002zm-6.0859 5.5156h0.002zm-3.7949 1.627v0.002z" fill="url(#linearGradient4424)"/>
+ <path id="path4402" d="m-280.11 288.16c-6.4503 0.00002-12.898 1.2835-18.857 3.752-5.9593 2.4684-11.425 6.1206-15.986 10.682-4.5611 4.5611-8.2132 10.027-10.682 15.986-2.4684 5.9593-3.7519 12.407-3.752 18.857 0.00002 6.4503 1.2835 12.898 3.752 18.857 2.4684 5.9593 6.1206 11.425 10.682 15.986 4.5611 4.5611 10.027 8.2132 15.986 10.682 5.9593 2.4684 12.407 3.7519 18.857 3.752 6.4503-0.00002 12.898-1.2835 18.857-3.752 5.9593-2.4684 11.425-6.1206 15.986-10.682 4.5611-4.5611 8.2132-10.027 10.682-15.986 2.4684-5.9593 3.7519-12.407 3.752-18.857-0.00002-6.4503-1.2835-12.898-3.752-18.857-2.4684-5.9593-6.1206-11.425-10.682-15.986-4.5611-4.5611-10.027-8.2132-15.986-10.682-5.9593-2.4684-12.407-3.7519-18.857-3.752zm-0.51563 1.1406a0.72311 0.72311 0 0 1 0.002 0c12.714 0.0109 25.044 5.0665 34.031 14.064 8.987 8.9759 13.911 20.601 13.922 33.309-0.0101 13.081-5.1256 24.968-12.645 33.791-0.42485 0.49849-1.011 0.80473-1.6035 0.79101-0.59249-0.0137-1.1124-0.30623-1.5371-0.70703-0.49206-0.46434-1.272-1.1732-1.9512-1.8066-0.33958-0.31669-0.65482-0.61464-0.90234-0.86133-0.12376-0.12334-0.23034-0.23209-0.32031-0.33203-0.09-0.0999-0.15313-0.14986-0.25196-0.3418-0.23991-0.46586-0.19336-0.92164-0.11132-1.2578 0.041-0.16808 0.0951-0.31228 0.15234-0.43554 0.0572-0.12327 0.0585-0.18508 0.24023-0.36719l-0.0371 0.0391c1.8267-2.1277 3.2432-3.7411 4.7402-5.957 1.4986-2.218 2.7891-4.5865 3.8438-7.0801 0.52748-1.247 0.99838-2.5271 1.4043-3.832 0.40577-1.3048 0.74578-2.6349 1.0234-3.9922 0.27784-1.3572 0.49237-2.7395 0.63477-4.1406 0.14215-1.4016 0.21484-2.8241 0.21484-4.2637 0-1.4398-0.0722-2.8624-0.21484-4.2637-0.14239-1.401-0.35691-2.7814-0.63477-4.1387-0.27768-1.3574-0.61772-2.6895-1.0234-3.9941-0.40592-1.305-0.87682-2.585-1.4043-3.832-1.0547-2.4935-2.3451-4.8621-3.8438-7.0801-1.4984-2.2179-3.2054-4.2836-5.0918-6.1699-1.8864-1.8865-3.9502-3.5935-6.168-5.0918-2.218-1.4985-4.5864-2.7891-7.0801-3.8438-1.2464-0.52718-2.5264-0.99628-3.832-1.4023-1.3048-0.4059-2.6391-0.7477-3.9961-1.0254-1.3567-0.27766-2.7353-0.49049-4.1367-0.63281-1.4022-0.14241-2.8266-0.2168-4.2656-0.2168-1.4391 0-2.8677 0.0742-4.2832 0.21875-1.4151 0.14443-2.8162 0.36081-4.1992 0.64258-1.3824 0.28163-2.7461 0.63103-4.0879 1.043-1.3416 0.41186-2.658 0.8853-3.9492 1.4199-2.5825 1.0694-5.0584 2.3774-7.3867 3.8945-2.3284 1.5172-4.5127 3.2441-6.5156 5.1504-2.0029 1.9062-3.8231 3.9924-5.4297 6.2285-0.80355 1.1182-1.5552 2.274-2.2461 3.4629-0.69079 1.1888-1.3223 2.4124-1.8926 3.666-0.57036 1.2538-1.0792 2.5365-1.5195 3.8457-0.44052 1.3098-0.81488 2.6447-1.1172 4.0039-0.30227 1.359-0.532 2.7427-0.6875 4.1445-0.15574 1.4016-0.23633 2.8226-0.23632 4.2598-0.00001 1.4385 0.0756 2.9137 0.22265 4.4062 0.14704 1.4921 0.36785 3.0021 0.65625 4.5137 0.28842 1.5116 0.64471 3.0223 1.0684 4.5195 0.42365 1.4972 0.9143 2.9805 1.4668 4.4297 0.5524 1.4491 1.1672 2.8646 1.8418 4.2324 0.67463 1.3679 1.4079 2.6886 2.1973 3.9414 0.78962 1.2532 1.6328 2.4399 2.5293 3.5449 0.89618 1.1047 1.8475 2.127 2.8438 3.0527 0.17252 0.16076 0.23062 0.36547 0.24414 0.49219 0.0135 0.12672-0.001 0.20699-0.0137 0.27149-0.025 0.12898-0.0562 0.20192-0.0781 0.25976a0.72311 0.72311 0 0 1 -0.0215 0.0508s-0.12243 0.4885-0.74414 0.74024c0.0278-0.0113-0.12936 0.0761-0.35938 0.0742-0.23002-0.002-0.47421-0.12627-0.61523-0.26172-8.2317-7.9053-13.917-21.064-13.928-33.803a0.72311 0.72311 0 0 1 0 -0.002c0.0208-12.334 4.7929-24.185 13.326-33.092l0.002-0.002c9.0244-9.4611 20.692-14.256 33.754-14.277zm0.51563 29.682c-0.97685 0.00002 1.8819 0.0713 0.90625 0.0234-0.97567-0.0479 1.8745 0.16214 0.90234 0.0664-0.97214-0.0957 1.8647 0.25269 0.89844 0.10937-0.96628-0.14331 1.8507 0.34681 0.89258 0.15625-0.95808-0.19055 1.8323 0.43461 0.88476 0.19727-0.94757-0.23734 1.8078 0.52574 0.87305 0.24219-0.93479-0.28355 1.7791 0.61228 0.85938 0.2832-0.91975-0.32908 1.7482 0.69999 0.8457 0.32617-0.9025-0.37381 1.7112 0.78484 0.82812 0.36719-0.88306-0.41765 1.6701 0.86868 0.8086 0.4082-0.86151-0.46047 1.6269 0.94751 0.78906 0.44532-0.83787-0.5022 1.5778 1.029 0.76562 0.48632-0.81222-0.5427 1.5248 1.1034 0.74024 0.52149-0.78462-0.58191 1.468 1.1763 0.71289 0.55664-0.75512-0.61971 1.4093 1.2478 0.68555 0.5918-0.7238-0.65601 1.347 1.3157 0.65625 0.625-0.69074-0.69074 1.281 1.38 0.625 0.65625-0.65601-0.7238 1.2115 1.4407 0.59179 0.68554-0.6197-0.75511 1.1386 1.4975 0.55664 0.71289-0.5819-0.78461 1.0642 1.5525 0.52149 0.74024-0.54271-0.81222 0.98852 1.6035 0.48633 0.76562-0.5022-0.83787 0.90578 1.6506 0.44531 0.78907-0.46048-0.86151 0.82585 1.6916 0.4082 0.80859-0.41765-0.88307 0.741 1.7306 0.36719 0.82812-0.37381-0.90249 0.65525 1.7655 0.32617 0.84571-0.32908-0.91975 0.56676 1.7942 0.2832 0.85937-0.28355-0.93479 0.47953 1.8206 0.24219 0.87305-0.23734-0.94758 0.38783 1.8428 0.19727 0.88476-0.19056-0.95808 0.29956 1.8589 0.15625 0.89258-0.14332-0.96628 0.2051 1.8706 0.10937 0.89844-0.0957-0.97215 0.11432 1.878 0.0664 0.90234-0.0479-0.97567 0.0234 1.8831 0.0234 0.90625-0.00002-0.97684-0.0713 1.8819-0.0234 0.90625 0.0479-0.97567-0.16214 1.8745-0.0664 0.90235 0.0957-0.97215-0.25269 1.8647-0.10937 0.89843 0.14331-0.96627-0.34681 1.8507-0.15625 0.89258 0.19056-0.95808-0.43461 1.8324-0.19727 0.88477 0.23734-0.94758-0.52574 1.8078-0.24219 0.87305 0.28356-0.93479-0.61228 1.7791-0.2832 0.85937 0.32908-0.91975-0.69998 1.7482-0.32617 0.8457 0.37381-0.90249-0.78484 1.7112-0.36719 0.82813s-0.86868 1.6701-0.4082 0.80859c0.46047-0.8615-0.94751 1.6269-0.44531 0.78907 0.50219-0.83788-1.029 1.5778-0.48633 0.76562 0.5427-0.81222-1.1034 1.5248-0.52149 0.74023 0.58191-0.78461-1.1763 1.468-0.55664 0.71289 0.61971-0.75511-1.2478 1.4094-0.59179 0.68555 0.65601-0.7238-1.3157 1.347-0.625 0.65625 0.69073-0.69073-1.38 1.281-0.65625 0.625 0.72379-0.65601-1.4407 1.2115-0.68555 0.5918 0.75511-0.61971-1.4975 1.1385-0.71289 0.55664 0.78461-0.58191-1.5525 1.0642-0.74024 0.52148 0.81223-0.5427-1.6035 0.98853-0.76562 0.48633 0.83787-0.50219-1.6506 0.90579-0.78906 0.44531 0.8615-0.46047-1.6917 0.82586-0.8086 0.40821 0.88307-0.41765-1.7306 0.741-0.82812 0.36719 0.90249-0.37382-1.7654 0.65525-0.8457 0.32617 0.91974-0.32908-1.7942 0.56675-0.85938 0.2832 0.93479-0.28355-1.8206 0.47953-0.87305 0.24219 0.94758-0.23734-1.8428 0.38782-0.88476 0.19726 0.95808-0.19056-1.8589 0.29957-0.89258 0.15625 0.96628-0.14331-1.8706 0.20511-0.89844 0.10938 0.97215-0.0957-1.878 0.11432-0.90234 0.0664 0.97567-0.0479-1.8831 0.0234-0.90625 0.0234 0.97685-0.00002-1.8819-0.0713-0.90625-0.0234 0.97567 0.0479-1.8745-0.16213-0.90235-0.0664 0.97215 0.0957-1.8647-0.25269-0.89843-0.10938 0.96627 0.14332-1.8507-0.3468-0.89258-0.15625 0.95808 0.19056-1.8323-0.4346-0.88477-0.19726 0.94758 0.23734-1.8078-0.52574-0.87304-0.24219 0.93479 0.28355-1.7791-0.61228-0.85938-0.2832 0.91975 0.32908-1.7482-0.69999-0.8457-0.32617 0.90249 0.37381-1.7112-0.78484-0.82813-0.36719s-1.6701-0.86868-0.80859-0.40821c0.86151 0.46048-1.6269-0.9475-0.78906-0.44531 0.83787 0.5022-1.5778-1.029-0.76563-0.48633 0.81222 0.54271-1.5248-1.1034-0.74023-0.52148 0.78461 0.5819-1.468-1.1763-0.71289-0.55664 0.75511 0.6197-1.4094-1.2478-0.68555-0.5918 0.7238 0.65601-1.347-1.3157-0.65625-0.625 0.69074 0.69074-1.281-1.38-0.625-0.65625 0.65601 0.7238-1.2115-1.4407-0.5918-0.68555 0.61971 0.75512-1.1385-1.4975-0.55664-0.71289 0.58191 0.78462-1.0642-1.5524-0.52148-0.74023 0.5427 0.81222-0.98852-1.6035-0.48633-0.76562 0.50219 0.83787-0.90579-1.6506-0.44531-0.78907 0.46047 0.86151-0.82585-1.6917-0.40821-0.80859 0.41765 0.88306-0.741-1.7306-0.36718-0.82813 0.37381 0.9025-0.65525-1.7654-0.32618-0.8457 0.32908 0.91975-0.56675-1.7942-0.2832-0.85937 0.28355 0.93478-0.47953-1.8206-0.24219-0.87305 0.23734 0.94758-0.38782-1.8428-0.19726-0.88477 0.19056 0.95808-0.29957-1.8588-0.15625-0.89258 0.14332 0.96628-0.20511-1.8706-0.10938-0.89843 0.0957 0.97214-0.11431-1.878-0.0664-0.90235 0.0479 0.97568-0.0234-1.8831-0.0234-0.90625 0.00002 0.97685 0.0713-1.8819 0.0234-0.90625-0.0479 0.97568 0.16213-1.8745 0.0664-0.90234-0.0957 0.97215 0.2527-1.8647 0.10938-0.89844-0.14332 0.96628 0.34681-1.8507 0.15625-0.89258-0.19056 0.95809 0.43461-1.8323 0.19726-0.88476-0.23734 0.94758 0.52574-1.8078 0.24219-0.87305-0.28355 0.93479 0.61228-1.7791 0.2832-0.85937-0.32907 0.91975 0.69999-1.7482 0.32618-0.84571-0.37382 0.9025 0.78483-1.7112 0.36718-0.82812-0.41764 0.88306 0.86868-1.6701 0.40821-0.80859-0.46048 0.8615 0.9475-1.6269 0.44531-0.78907-0.50219 0.83788 1.029-1.5778 0.48633-0.76562-0.54271 0.81222 1.1034-1.5248 0.52148-0.74024-0.5819 0.78462 1.1764-1.468 0.55664-0.71289-0.6197 0.75512 1.2478-1.4093 0.5918-0.68554-0.65601 0.72379 1.3157-1.347 0.625-0.65625-0.69074 0.69073 1.38-1.281 0.65625-0.625-0.7238 0.65601 1.4407-1.2115 0.68555-0.5918-0.75512 0.6197 1.4975-1.1386 0.71289-0.55664-0.78462 0.5819 1.5524-1.0642 0.74023-0.52149-0.81222 0.54271 1.6035-0.98852 0.76563-0.48632-0.83788 0.50219 1.6506-0.90579 0.78906-0.44532-0.86151 0.46048 1.6917-0.82585 0.80859-0.4082-0.88306 0.41765 1.7306-0.741 0.82813-0.36719-0.9025 0.37382 1.7654-0.65525 0.8457-0.32617-0.91975 0.32908 1.7942-0.56675 0.85938-0.2832-0.93479 0.28355 1.8206-0.47953 0.87304-0.24219-0.94757 0.23734 1.8428-0.38782 0.88477-0.19727-0.95808 0.19056 1.8588-0.29956 0.89258-0.15625-0.96628 0.14332 1.8706-0.2051 0.89843-0.10937-0.97214 0.0957 1.878-0.11432 0.90235-0.0664-0.97567 0.0479 1.8831-0.0234 0.90625-0.0234z" transform="matrix(1.0147 0 0 1.0147 24.08 -2.1712)" fill="#e6e7e8"/>
+ </g>
+ <g id="g4957">
+ <path id="path52738-1-8-5-0-9" fill="url(#radialGradient52746-0-9-6-5-6)" d="m-486.86 309.22a35.709 35.709 0 0 0 -35.711 35.709 35.709 35.709 0 0 0 35.711 35.711 35.709 35.709 0 0 0 35.709 -35.711 35.709 35.709 0 0 0 -35.709 -35.709zm0 16.533a19.177 19.177 0 0 1 19.176 19.176 19.177 19.177 0 0 1 -19.176 19.178 19.177 19.177 0 0 1 -19.178 -19.178 19.177 19.177 0 0 1 19.178 -19.176z"/>
+ <path id="path52738-1-8-4-8" d="m-486.86 312.2a32.733 32.733 0 0 0 -32.732 32.734 32.733 32.733 0 0 0 32.732 32.732 32.733 32.733 0 0 0 32.732 -32.732 32.733 32.733 0 0 0 -32.732 -32.734zm0 13.557a19.177 19.177 0 0 1 19.178 19.178 19.177 19.177 0 0 1 -19.178 19.176 19.177 19.177 0 0 1 -19.178 -19.176 19.177 19.177 0 0 1 19.178 -19.178z" stroke="#8c8d93" stroke-width=".49597" fill="url(#radialGradient52746-0-9-15-6)"/>
+ <path id="path52738-1-4-6" fill="url(#radialGradient52746-0-4-0)" d="m-486.86 314.23a30.702 30.702 0 0 0 -30.701 30.701 30.702 30.702 0 0 0 30.701 30.701 30.702 30.702 0 0 0 30.701 -30.701 30.702 30.702 0 0 0 -30.701 -30.701zm0 11.523a19.177 19.177 0 0 1 19.178 19.178 19.177 19.177 0 0 1 -19.178 19.178 19.177 19.177 0 0 1 -19.178 -19.178 19.177 19.177 0 0 1 19.178 -19.178z"/>
+ <path id="path52738-1-8-9-4-0" fill="url(#radialGradient52746-0-9-1-0-9)" d="m-486.86 325.76a19.177 19.177 0 0 0 -19.178 19.178 19.177 19.177 0 0 0 19.178 19.178 19.177 19.177 0 0 0 19.178 -19.178 19.177 19.177 0 0 0 -19.178 -19.178zm0 1.4102a17.768 17.768 0 0 1 17.768 17.768 17.768 17.768 0 0 1 -17.768 17.768 17.768 17.768 0 0 1 -17.768 -17.768 17.768 17.768 0 0 1 17.768 -17.768z"/>
+ </g>
+ </g>
+ </g>
+</svg>
ui/src/app/widget/lib/rpc/knob.tpl.html 46(+46 -0)
diff --git a/ui/src/app/widget/lib/rpc/knob.tpl.html b/ui/src/app/widget/lib/rpc/knob.tpl.html
new file mode 100644
index 0000000..93276b4
--- /dev/null
+++ b/ui/src/app/widget/lib/rpc/knob.tpl.html
@@ -0,0 +1,46 @@
+<!--
+
+ Copyright © 2016-2017 The Thingsboard Authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<div class="tb-knob" layout="column" ng-class="{'dark': vm.darkTheme}" ng-style="{'pointerEvents': vm.ctx.isEdit ? 'none' : 'all'}">
+ <div id="knob-container" flex layout="column" layout-align="center center">
+ <div class="knob">
+ <div class="value-container" layout="row" layout-align="center center">
+ <span class="knob-value">{{ vm.value }}</span>
+ </div>
+ <div class="canvas-background"></div>
+ <canvas id="canvasBar"></canvas>
+ <div class="top-pointer-container">
+ <div class="top-pointer"></div>
+ </div>
+ <div class="top"></div>
+ <div class="error-container" ng-style="{'background': vm.error.length ? 'rgba(255,255,255,0.25)' : 'none'}"
+ layout="row" layout-align="center center">
+ <span class="knob-error">{{ vm.error }}</span>
+ </div>
+ <div class="title-container" layout="row" layout-align="center center">
+ <span class="knob-title">{{ vm.title }}</span>
+ </div>
+ <div class="minmax-container" layout="row" layout-align="start center">
+ <span class="minmax-label">min</span>
+ <span flex></span>
+ <span class="minmax-label">max</span>
+ </div>
+ <div id="text-measure"></div>
+ </div>
+ </div>
+</div>
\ No newline at end of file