Commit adc7194669d4a8ee0b38ac99f37dcb663e8a62ee

Authored by Vladyslav
Committed by GitHub
1 parent c55ddd9f

[3.0] Add support ticks to digital gauge (#2508)

* Add support ticks to digital gauge

* Add link code
... ... @@ -15,12 +15,12 @@
15 15 ///
16 16
17 17 import * as CanvasGauges from 'canvas-gauges';
18   -import GenericOptions = CanvasGauges.GenericOptions;
19   -import BaseGauge = CanvasGauges.BaseGauge;
20 18 import { FontStyle, FontWeight } from '@home/components/widget/lib/settings.models';
21 19 import * as tinycolor_ from 'tinycolor2';
22 20 import { ColorFormats } from 'tinycolor2';
23 21 import { isDefined, isString, isUndefined } from '@core/utils';
  22 +import GenericOptions = CanvasGauges.GenericOptions;
  23 +import BaseGauge = CanvasGauges.BaseGauge;
24 24
25 25 const tinycolor = tinycolor_;
26 26
... ... @@ -32,12 +32,12 @@ export interface DigitalGaugeColorRange {
32 32 rgbString: string;
33 33 }
34 34
35   -export interface colorLevelSetting {
  35 +export interface ColorLevelSetting {
36 36 value: number;
37 37 color: string;
38 38 }
39 39
40   -export type levelColors = Array<string | colorLevelSetting>;
  40 +export type levelColors = Array<string | ColorLevelSetting>;
41 41
42 42 export interface CanvasDigitalGaugeOptions extends GenericOptions {
43 43 gaugeType?: GaugeType;
... ... @@ -81,6 +81,11 @@ export interface CanvasDigitalGaugeOptions extends GenericOptions {
81 81 fontValueHeight?: FontHeightInfo;
82 82 fontMinMaxHeight?: FontHeightInfo;
83 83
  84 + ticksValue?: number[];
  85 + ticks?: number[];
  86 + colorTicks?: string;
  87 + tickWidth?: number;
  88 +
84 89 showTimestamp?: boolean;
85 90 }
86 91
... ... @@ -117,6 +122,10 @@ const defaultDigitalGaugeOptions: CanvasDigitalGaugeOptions = { ...GenericOption
117 122
118 123 neonGlowBrightness: 0,
119 124
  125 + colorTicks: 'gray',
  126 + tickWidth: 4,
  127 + ticks: [],
  128 +
120 129 isMobile: false
121 130 }
122 131 };
... ... @@ -243,9 +252,14 @@ export class CanvasDigitalGauge extends BaseGauge {
243 252 options.neonColorsRange = [];
244 253 }
245 254 for (let i = 0; i < options.levelColors.length; i++) {
246   - let levelColor: any = options.levelColors[i];
  255 + const levelColor: any = options.levelColors[i];
247 256 if (levelColor !== null) {
248   - let percentage = isColorProperty ? inc * i : CanvasDigitalGauge.normalizeValue(levelColor.value, options.minValue, options.maxValue);
  257 + let percentage: number;
  258 + if(isColorProperty){
  259 + percentage = inc * i;
  260 + } else {
  261 + percentage = CanvasDigitalGauge.normalizeValue(levelColor.value, options.minValue, options.maxValue);
  262 + }
249 263 let tColor = tinycolor(isColorProperty ? levelColor : levelColor.color);
250 264 options.colorsRange.push({
251 265 pct: percentage,
... ... @@ -263,6 +277,13 @@ export class CanvasDigitalGauge extends BaseGauge {
263 277 }
264 278 }
265 279
  280 + options.ticksValue = [];
  281 + for (const tick of options.ticks) {
  282 + if (tick !== null) {
  283 + options.ticksValue.push(CanvasDigitalGauge.normalizeValue(tick, options.minValue, options.maxValue))
  284 + }
  285 + }
  286 +
266 287 if (options.neonGlowBrightness) {
267 288 options.neonColorTitle = tinycolor(options.colorTitle).brighten(options.neonGlowBrightness).toHexString();
268 289 options.neonColorLabel = tinycolor(options.colorLabel).brighten(options.neonGlowBrightness).toHexString();
... ... @@ -274,7 +295,7 @@ export class CanvasDigitalGauge extends BaseGauge {
274 295 }
275 296
276 297 static normalizeValue (value: number, min: number, max: number): number {
277   - let normalValue = (value - min) / (max - min);
  298 + const normalValue = (value - min) / (max - min);
278 299 if (normalValue <= 0) {
279 300 return 0;
280 301 }
... ... @@ -657,7 +678,7 @@ function determineFontHeight (options: CanvasDigitalGaugeOptions, target: string
657 678 fontStyle: options['font' + target + 'Style']
658 679 };
659 680 const text = $('<span>Hg</span>').css(fontStyle);
660   - const block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');
  681 + const block = $('<div style="display: inline-block; width: 1px; height: 0;"></div>');
661 682
662 683 const div = $('<div></div>');
663 684 div.append(text, block);
... ... @@ -884,6 +905,52 @@ function drawBarGlow(context: DigitalGaugeCanvasRenderingContext2D, startX: numb
884 905 context.stroke();
885 906 }
886 907
  908 +function drawTickArc(context: DigitalGaugeCanvasRenderingContext2D, tickValues: number[], Cx: number, Cy: number,
  909 + Ri: number, Rm: number, Ro: number, startAngle: number, endAngle: number,
  910 + color: string, tickWidth: number) {
  911 + if (!tickValues.length) {
  912 + return;
  913 + }
  914 +
  915 + const strokeWidth = Ro - Ri;
  916 + context.beginPath();
  917 + context.lineWidth = tickWidth;
  918 + context.strokeStyle = color;
  919 + for (const tick of tickValues) {
  920 + const angle = startAngle + tick * endAngle;
  921 + const x1 = Cx + (Ri + strokeWidth) * Math.cos(angle);
  922 + const y1 = Cy + (Ri + strokeWidth) * Math.sin(angle);
  923 + const x2 = Cx + Ri * Math.cos(angle);
  924 + const y2 = Cy + Ri * Math.sin(angle);
  925 + context.moveTo(x1, y1);
  926 + context.lineTo(x2, y2);
  927 + }
  928 + context.stroke();
  929 +}
  930 +
  931 +function drawTickBar(context: DigitalGaugeCanvasRenderingContext2D, tickValues: number[], startX: number, startY: number,
  932 + distanceBar: number, strokeWidth: number, isVertical: boolean, color: string, tickWidth: number) {
  933 + if (!tickValues.length) {
  934 + return;
  935 + }
  936 +
  937 + context.beginPath();
  938 + context.lineWidth = tickWidth;
  939 + context.strokeStyle = color;
  940 + for (const tick of tickValues) {
  941 + const tickValue = tick * distanceBar;
  942 + if (isVertical) {
  943 + context.moveTo(startX - strokeWidth / 2, startY + tickValue - distanceBar);
  944 + context.lineTo(startX + strokeWidth / 2, startY + tickValue - distanceBar);
  945 + } else {
  946 + context.moveTo(startX + tickValue, startY);
  947 + context.lineTo(startX + tickValue, startY + strokeWidth);
  948 + }
  949 + }
  950 + context.stroke();
  951 +}
  952 +
  953 +
887 954 function drawProgress(context: DigitalGaugeCanvasRenderingContext2D,
888 955 options: CanvasDigitalGaugeOptions, progress: number) {
889 956 let neonColor;
... ... @@ -917,6 +984,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D,
917 984 drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, true,
918 985 options.donutStartAngle, options.donutEndAngle);
919 986 }
  987 + drawTickArc(context, options.ticksValue, Cx, Cy, Ri, Rm, Ro, options.donutStartAngle,
  988 + options.donutEndAngle - options.donutStartAngle, options.colorTicks, options.tickWidth);
920 989 } else if (options.gaugeType === 'arc') {
921 990 if (options.neonGlowBrightness) {
922 991 context.strokeStyle = neonColor;
... ... @@ -927,6 +996,7 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D,
927 996 if (options.neonGlowBrightness && !options.isMobile) {
928 997 drawArcGlow(context, Cx, Cy, Ri, Rm, Ro, neonColor, progress, false);
929 998 }
  999 + drawTickArc(context, options.ticksValue, Cx, Cy, Ri, Rm, Ro, Math.PI, Math.PI, options.colorTicks, options.tickWidth);
930 1000 } else if (options.gaugeType === 'horizontalBar') {
931 1001 if (options.neonGlowBrightness) {
932 1002 context.strokeStyle = neonColor;
... ... @@ -940,6 +1010,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D,
940 1010 barLeft + (barRight-barLeft)*progress, barTop + strokeWidth/2,
941 1011 neonColor, strokeWidth, false);
942 1012 }
  1013 + drawTickBar(context, options.ticksValue, barLeft, barTop, barRight - barLeft, strokeWidth,
  1014 + false, options.colorTicks, options.tickWidth);
943 1015 } else if (options.gaugeType === 'verticalBar') {
944 1016 if (options.neonGlowBrightness) {
945 1017 context.strokeStyle = neonColor;
... ... @@ -953,6 +1025,8 @@ function drawProgress(context: DigitalGaugeCanvasRenderingContext2D,
953 1025 baseX + width/2, barBottom - (barBottom-barTop)*progress,
954 1026 neonColor, strokeWidth, true);
955 1027 }
  1028 + drawTickBar(context, options.ticksValue, baseX + width / 2, barTop, barTop - barBottom, strokeWidth,
  1029 + true, options.colorTicks, options.tickWidth);
956 1030 }
957 1031
958 1032 }
... ...
... ... @@ -19,25 +19,27 @@ import { GaugeType } from '@home/components/widget/lib/canvas-digital-gauge';
19 19 import { AnimationRule } from '@home/components/widget/lib/analogue-gauge.models';
20 20 import { FontSettings } from '@home/components/widget/lib/settings.models';
21 21
22   -export interface colorLevelProperty {
  22 +export interface AttributeSourceProperty {
23 23 valueSource: string;
24 24 entityAlias?: string;
25 25 attribute?: string;
26 26 value?: number;
27 27 }
28 28
29   -export interface fixedLevelColors {
30   - from?: colorLevelProperty;
31   - to?: colorLevelProperty;
  29 +export interface FixedLevelColors {
  30 + from?: AttributeSourceProperty;
  31 + to?: AttributeSourceProperty;
32 32 color: string;
33 33 }
34 34
35   -export interface colorLevelSetting {
  35 +export interface ColorLevelSetting {
36 36 value: number;
37 37 color: string;
38 38 }
39 39
40   -export type colorLevel = Array<string | colorLevelSetting>;
  40 +export type colorLevel = Array<string | ColorLevelSetting>;
  41 +
  42 +export type attributesGaugeType = 'levelColors' | 'ticks';
41 43
42 44 export interface DigitalGaugeSettings {
43 45 minValue?: number;
... ... @@ -60,7 +62,7 @@ export interface DigitalGaugeSettings {
60 62 gaugeColor?: string;
61 63 useFixedLevelColor?: boolean;
62 64 levelColors?: colorLevel;
63   - fixedLevelColors?: fixedLevelColors[];
  65 + fixedLevelColors?: FixedLevelColors[];
64 66 animation?: boolean;
65 67 animationDuration?: number;
66 68 animationRule?: AnimationRule;
... ... @@ -72,6 +74,11 @@ export interface DigitalGaugeSettings {
72 74 units?: string;
73 75 hideValue?: boolean;
74 76 hideMinMax?: boolean;
  77 + showTicks?: boolean;
  78 + ticksValue?: AttributeSourceProperty[];
  79 + ticks?: number[];
  80 + colorTicks?: string;
  81 + tickWidth?: number;
75 82 }
76 83
77 84 export const digitalGaugeSettingsSchema: JsonSettingsSchema = {
... ... @@ -242,6 +249,48 @@ export const digitalGaugeSettingsSchema: JsonSettingsSchema = {
242 249 }
243 250 }
244 251 },
  252 + showTicks: {
  253 + title: 'Show ticks',
  254 + type: 'boolean',
  255 + default: false
  256 + },
  257 + tickWidth: {
  258 + title: 'Width ticks',
  259 + type: 'number',
  260 + default: 4
  261 + },
  262 + colorTicks: {
  263 + title: 'Color ticks',
  264 + type: 'string',
  265 + default: '#666'
  266 + },
  267 + ticksValue: {
  268 + title: 'The ticks predefined value',
  269 + type: 'array',
  270 + items: {
  271 + title: 'tickValue',
  272 + type: 'object',
  273 + properties: {
  274 + valueSource: {
  275 + title: 'Value source',
  276 + type: 'string',
  277 + default: 'predefinedValue'
  278 + },
  279 + entityAlias: {
  280 + title: 'Source entity alias',
  281 + type: 'string'
  282 + },
  283 + attribute: {
  284 + title: 'Source entity attribute',
  285 + type: 'string'
  286 + },
  287 + value: {
  288 + title: 'Value (if predefined value is selected)',
  289 + type: 'number'
  290 + }
  291 + }
  292 + }
  293 + },
245 294 animation: {
246 295 title: 'Enable animation',
247 296 type: 'boolean',
... ... @@ -487,6 +536,40 @@ export const digitalGaugeSettingsSchema: JsonSettingsSchema = {
487 536 }
488 537 ]
489 538 },
  539 + 'showTicks',
  540 + {
  541 + key: 'tickWidth',
  542 + condition: 'model.showTicks === true'
  543 + },
  544 + {
  545 + key: 'colorTicks',
  546 + condition: 'model.showTicks === true',
  547 + type: 'color'
  548 + },
  549 + {
  550 + key: 'ticksValue',
  551 + condition: 'model.showTicks === true',
  552 + items: [
  553 + {
  554 + key: 'ticksValue[].valueSource',
  555 + type: 'rc-select',
  556 + multiple: false,
  557 + items: [
  558 + {
  559 + value: 'predefinedValue',
  560 + label: 'Predefined value (Default)'
  561 + },
  562 + {
  563 + value: 'entityAttribute',
  564 + label: 'Value taken from entity attribute'
  565 + }
  566 + ]
  567 + },
  568 + 'ticksValue[].value',
  569 + 'ticksValue[].entityAlias',
  570 + 'ticksValue[].attribute'
  571 + ]
  572 + },
490 573 'animation',
491 574 'animationDuration',
492 575 {
... ...
... ... @@ -17,19 +17,30 @@
17 17 import * as CanvasGauges from 'canvas-gauges';
18 18 import { WidgetContext } from '@home/models/widget-component.models';
19 19 import {
20   - colorLevelSetting,
  20 + attributesGaugeType,
  21 + AttributeSourceProperty,
  22 + ColorLevelSetting,
21 23 DigitalGaugeSettings,
22   - digitalGaugeSettingsSchema
  24 + digitalGaugeSettingsSchema,
  25 + FixedLevelColors
23 26 } from '@home/components/widget/lib/digital-gauge.models';
24 27 import * as tinycolor_ from 'tinycolor2';
25 28 import { isDefined } from '@core/utils';
26 29 import { prepareFontSettings } from '@home/components/widget/lib/settings.models';
27 30 import { CanvasDigitalGauge, CanvasDigitalGaugeOptions } from '@home/components/widget/lib/canvas-digital-gauge';
28 31 import { DatePipe } from '@angular/common';
29   -import {DataKey, Datasource, DatasourceType, JsonSettingsSchema, widgetType} from '@shared/models/widget.models';
  32 +import {
  33 + DataKey,
  34 + Datasource,
  35 + DatasourceData,
  36 + DatasourceType,
  37 + JsonSettingsSchema,
  38 + widgetType
  39 +} from '@shared/models/widget.models';
  40 +import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
  41 +import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
  42 +import { EMPTY, Observable } from 'rxjs';
30 43 import GenericOptions = CanvasGauges.GenericOptions;
31   -import {IWidgetSubscription, WidgetSubscriptionOptions} from "@core/api/widget-api.models";
32   -import {DataKeyType} from "@shared/models/telemetry/telemetry.models";
33 44
34 45 const tinycolor = tinycolor_;
35 46
... ... @@ -37,11 +48,6 @@ const digitalGaugeSettingsSchemaValue = digitalGaugeSettingsSchema;
37 48
38 49 export class TbCanvasDigitalGauge {
39 50
40   - private localSettings: DigitalGaugeSettings;
41   - private levelColorsSourcesSubscription: IWidgetSubscription;
42   -
43   - private gauge: CanvasDigitalGauge;
44   -
45 51 static get settingsSchema(): JsonSettingsSchema {
46 52 return digitalGaugeSettingsSchemaValue;
47 53 }
... ... @@ -84,6 +90,12 @@ export class TbCanvasDigitalGauge {
84 90 this.localSettings.fixedLevelColors = settings.fixedLevelColors || [];
85 91 }
86 92
  93 + this.localSettings.showTicks = settings.showTicks || false;
  94 + this.localSettings.ticks = [];
  95 + this.localSettings.ticksValue = settings.ticksValue || [];
  96 + this.localSettings.tickWidth = settings.tickWidth || 4;
  97 + this.localSettings.colorTicks = settings.colorTicks || '#666';
  98 +
87 99 this.localSettings.decimals = isDefined(dataKey.decimals) ? dataKey.decimals :
88 100 ((isDefined(settings.decimals) && settings.decimals !== null)
89 101 ? settings.decimals : ctx.decimals);
... ... @@ -137,6 +149,10 @@ export class TbCanvasDigitalGauge {
137 149 gaugeColor: this.localSettings.gaugeColor,
138 150 levelColors: this.localSettings.levelColors,
139 151
  152 + colorTicks: this.localSettings.colorTicks,
  153 + tickWidth: this.localSettings.tickWidth,
  154 + ticks: this.localSettings.ticks,
  155 +
140 156 title: this.localSettings.title,
141 157
142 158 fontTitleSize: this.localSettings.titleFont.size,
... ... @@ -192,76 +208,92 @@ export class TbCanvasDigitalGauge {
192 208 this.init();
193 209 }
194 210
  211 + private localSettings: DigitalGaugeSettings;
  212 + private levelColorsSourcesSubscription: IWidgetSubscription;
  213 + private ticksSourcesSubscription: IWidgetSubscription;
  214 +
  215 + private gauge: CanvasDigitalGauge;
  216 +
  217 + static generateDatasource(ctx: WidgetContext, datasources: Datasource[], entityAlias: string,
  218 + attribute: string, settings: any): Datasource[]{
  219 + const entityAliasId = ctx.aliasController.getEntityAliasId(entityAlias);
  220 + if (!entityAliasId) {
  221 + throw new Error('Not valid entity aliase name ' + entityAlias);
  222 + }
  223 +
  224 + const datasource = datasources.find((datasourceIteration) => {
  225 + return datasourceIteration.entityAliasId === entityAliasId;
  226 + });
  227 +
  228 + const dataKey: DataKey = {
  229 + type: DataKeyType.attribute,
  230 + name: attribute,
  231 + label: attribute,
  232 + settings: [settings],
  233 + _hash: Math.random()
  234 + };
  235 +
  236 + if (datasource) {
  237 + const findDataKey = datasource.dataKeys.find((dataKeyIteration) => {
  238 + return dataKeyIteration.name === attribute;
  239 + });
  240 +
  241 + if (findDataKey) {
  242 + findDataKey.settings.push(settings);
  243 + } else {
  244 + datasource.dataKeys.push(dataKey)
  245 + }
  246 + } else {
  247 + const datasourceAttribute: Datasource = {
  248 + type: DatasourceType.entity,
  249 + name: entityAlias,
  250 + aliasName: entityAlias,
  251 + entityAliasId,
  252 + dataKeys: [dataKey]
  253 + };
  254 + datasources.push(datasourceAttribute);
  255 + }
  256 +
  257 + return datasources;
  258 + }
  259 +
195 260 init() {
196 261 if (this.localSettings.useFixedLevelColor) {
197 262 if (this.localSettings.fixedLevelColors && this.localSettings.fixedLevelColors.length > 0) {
198 263 this.localSettings.levelColors = this.settingLevelColorsSubscribe(this.localSettings.fixedLevelColors);
199   - this.updateLevelColors(this.localSettings.levelColors);
200 264 }
  265 +
  266 + if (this.localSettings.showTicks) {
  267 + if (this.localSettings.ticksValue && this.localSettings.ticksValue.length) {
  268 + this.localSettings.ticks = this.settingTicksSubscribe(this.localSettings.ticksValue);
  269 + }
  270 + }
  271 + this.updateSetting();
201 272 }
202 273 }
203 274
204   - settingLevelColorsSubscribe(options) {
  275 + settingLevelColorsSubscribe(options: FixedLevelColors[]): ColorLevelSetting[] {
205 276 let levelColorsDatasource: Datasource[] = [];
206   - let predefineLevelColors: colorLevelSetting[] = [];
  277 + const predefineLevelColors: ColorLevelSetting[] = [];
207 278
208   - function setLevelColor(levelSetting, color) {
  279 + function setLevelColor(levelSetting: AttributeSourceProperty, color: string) {
209 280 if (levelSetting.valueSource === 'predefinedValue' && isFinite(levelSetting.value)) {
210 281 predefineLevelColors.push({
211 282 value: levelSetting.value,
212   - color: color
  283 + color
213 284 })
214 285 } else if (levelSetting.entityAlias && levelSetting.attribute) {
215   - let entityAliasId = this.ctx.aliasController.getEntityAliasId(levelSetting.entityAlias);
216   - if (!entityAliasId) {
  286 + try {
  287 + levelColorsDatasource = TbCanvasDigitalGauge.generateDatasource(this.ctx, levelColorsDatasource,
  288 + levelSetting.entityAlias, levelSetting.attribute, {color, index: predefineLevelColors.length});
  289 + } catch (e) {
217 290 return;
218 291 }
219   -
220   - let datasource = levelColorsDatasource.find((datasource) => {
221   - return datasource.entityAliasId === entityAliasId;
222   - });
223   -
224   - let dataKey: DataKey = {
225   - type: DataKeyType.attribute,
226   - name: levelSetting.attribute,
227   - label: levelSetting.attribute,
228   - settings: [{
229   - color: color,
230   - index: predefineLevelColors.length
231   - }],
232   - _hash: Math.random()
233   - };
234   -
235   - if (datasource) {
236   - let findDataKey = datasource.dataKeys.find((dataKey) => {
237   - return dataKey.name === levelSetting.attribute;
238   - });
239   -
240   - if (findDataKey) {
241   - findDataKey.settings.push({
242   - color: color,
243   - index: predefineLevelColors.length
244   - });
245   - } else {
246   - datasource.dataKeys.push(dataKey)
247   - }
248   - } else {
249   - let datasource: Datasource = {
250   - type: DatasourceType.entity,
251   - name: levelSetting.entityAlias,
252   - aliasName: levelSetting.entityAlias,
253   - entityAliasId: entityAliasId,
254   - dataKeys: [dataKey]
255   - };
256   - levelColorsDatasource.push(datasource);
257   - }
258   -
259 292 predefineLevelColors.push(null);
260 293 }
261 294 }
262 295
263   - for (let i = 0; i < options.length; i++) {
264   - let levelColor = options[i];
  296 + for(const levelColor of options){
265 297 if (levelColor.from) {
266 298 setLevelColor.call(this, levelColor.from, levelColor.color);
267 299 }
... ... @@ -270,49 +302,86 @@ export class TbCanvasDigitalGauge {
270 302 }
271 303 }
272 304
273   - this.subscribeLevelColorsAttributes(levelColorsDatasource);
  305 + this.subscribeAttributes(levelColorsDatasource, 'levelColors').subscribe((subscription) => {
  306 + this.levelColorsSourcesSubscription = subscription;
  307 + });
274 308
275 309 return predefineLevelColors;
276 310 }
277 311
278   - updateLevelColors(levelColors) {
279   - (this.gauge.options as CanvasDigitalGaugeOptions).levelColors = levelColors;
280   - this.gauge.options = CanvasDigitalGauge.configure(this.gauge.options);
281   - this.gauge.update({} as CanvasDigitalGaugeOptions);
  312 + settingTicksSubscribe(options: AttributeSourceProperty[]): number[] {
  313 + let ticksDatasource: Datasource[] = [];
  314 + const predefineTicks: number[] = [];
  315 +
  316 + for(const tick of options){
  317 + if (tick.valueSource === 'predefinedValue' && isFinite(tick.value)) {
  318 + predefineTicks.push(tick.value)
  319 + } else if (tick.entityAlias && tick.attribute) {
  320 + try {
  321 + ticksDatasource = TbCanvasDigitalGauge
  322 + .generateDatasource(this.ctx, ticksDatasource, tick.entityAlias, tick.attribute, predefineTicks.length);
  323 + } catch (e) {
  324 + continue;
  325 + }
  326 + predefineTicks.push(null);
  327 + }
  328 + }
  329 +
  330 + this.subscribeAttributes(ticksDatasource, 'ticks').subscribe((subscription) => {
  331 + this.ticksSourcesSubscription = subscription;
  332 + });
  333 +
  334 + return predefineTicks;
282 335 }
283 336
284   - subscribeLevelColorsAttributes(datasources: Datasource[]) {
285   - let TbCanvasDigitalGauge = this;
286   - let levelColorsSourcesSubscriptionOptions: WidgetSubscriptionOptions = {
287   - datasources: datasources,
  337 + subscribeAttributes(datasource: Datasource[], typeAttributes: attributesGaugeType): Observable<IWidgetSubscription> {
  338 + if (!datasource.length) {
  339 + return EMPTY;
  340 + }
  341 +
  342 + const levelColorsSourcesSubscriptionOptions: WidgetSubscriptionOptions = {
  343 + datasources: datasource,
288 344 useDashboardTimewindow: false,
289 345 type: widgetType.latest,
290 346 callbacks: {
291 347 onDataUpdated: (subscription) => {
292   - for (let i = 0; i < subscription.data.length; i++) {
293   - let keyData = subscription.data[i];
294   - if (keyData && keyData.data && keyData.data[0]) {
295   - let attrValue = keyData.data[0][1];
296   - if (isFinite(attrValue)) {
297   - for (let i = 0; i < keyData.dataKey.settings.length; i++) {
298   - let setting = keyData.dataKey.settings[i];
299   - this.localSettings.levelColors[setting.index] = {
300   - value: attrValue,
301   - color: setting.color
302   - };
303   - }
304   - }
305   - }
306   - }
307   - this.updateLevelColors(this.localSettings.levelColors);
  348 + this.updateAttribute(subscription.data, typeAttributes);
308 349 }
309 350 }
310 351 };
311   - this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true).subscribe(
312   - (subscription) => {
313   - TbCanvasDigitalGauge.levelColorsSourcesSubscription = subscription;
  352 +
  353 + return this.ctx.subscriptionApi.createSubscription(levelColorsSourcesSubscriptionOptions, true);
  354 + }
  355 +
  356 + updateAttribute(data: Array<DatasourceData>, typeAttributes: attributesGaugeType) {
  357 + for (const keyData of data) {
  358 + if (keyData && keyData.data && keyData.data[0]) {
  359 + const attrValue = keyData.data[0][1];
  360 + if (isFinite(attrValue)) {
  361 + for (const setting of keyData.dataKey.settings) {
  362 + switch (typeAttributes) {
  363 + case 'levelColors':
  364 + this.localSettings.levelColors[setting.index] = {
  365 + value: attrValue,
  366 + color: setting.color
  367 + };
  368 + break;
  369 + case 'ticks':
  370 + this.localSettings.ticks[setting] = attrValue;
  371 + break;
  372 + }
  373 + }
  374 + }
314 375 }
315   - );
  376 + }
  377 + this.updateSetting();
  378 + }
  379 +
  380 + updateSetting() {
  381 + (this.gauge.options as CanvasDigitalGaugeOptions).ticks = this.localSettings.ticks;
  382 + (this.gauge.options as CanvasDigitalGaugeOptions).levelColors = this.localSettings.levelColors;
  383 + this.gauge.options = CanvasDigitalGauge.configure(this.gauge.options);
  384 + this.gauge.update({} as CanvasDigitalGaugeOptions);
316 385 }
317 386
318 387 update() {
... ...