diff --git a/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java b/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java index 80192520ca..88a03f5fc8 100644 --- a/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java +++ b/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java @@ -103,13 +103,13 @@ public class NetworkReceive implements Receive { if (maxSize != UNLIMITED && receiveSize > maxSize) { throw new ThingsboardKafkaClientError("Invalid receive (size = " + receiveSize + " larger than " + maxSize + ")"); } - requestedBufferSize = receiveSize; //may be 0 for some payloads (SASL) + requestedBufferSize = receiveSize; // may be 0 for some payloads (SASL) if (receiveSize == 0) { buffer = EMPTY_BUFFER; } } } - if (buffer == null && requestedBufferSize != -1) { //we know the size we want but havent been able to allocate it yet + if (buffer == null && requestedBufferSize != -1) { // we know the size we want but haven't been able to allocate it yet if (requestedBufferSize > TB_LOG_REQUESTED_BUFFER_SIZE) { String stackTrace = Arrays.stream(Thread.currentThread().getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining("|")); log.error("Allocating buffer of size {} for source {}", requestedBufferSize, source); diff --git a/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java b/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java index ed35d96cb7..78042ffc0e 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java @@ -70,11 +70,12 @@ public class DefaultCalculatedFieldCache implements CalculatedFieldCache { @AfterStartUp(order = AfterStartUp.CF_READ_CF_SERVICE) public void init() { - //TODO: move to separate place to avoid circular references with the ActorSystemContext (@Lazy for tsSubService) PageDataIterable cfs = new PageDataIterable<>(calculatedFieldService::findAllCalculatedFields, initFetchPackSize); cfs.forEach(cf -> { - calculatedFields.putIfAbsent(cf.getId(), cf); - actorSystemContext.tell(new CalculatedFieldInitMsg(cf.getTenantId(), cf)); + if (cf != null) { + calculatedFields.putIfAbsent(cf.getId(), cf); + actorSystemContext.tell(new CalculatedFieldInitMsg(cf.getTenantId(), cf)); + } }); calculatedFields.values().forEach(cf -> { entityIdCalculatedFields.computeIfAbsent(cf.getEntityId(), id -> new CopyOnWriteArrayList<>()).add(cf); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/CalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/CalculatedFieldConfiguration.java index c53f1fe5f1..ad3d4373ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/CalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/CalculatedFieldConfiguration.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.data.cf.configuration; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.thingsboard.server.common.data.cf.CalculatedFieldLink; @@ -36,6 +37,7 @@ import java.util.Map; @JsonSubTypes.Type(value = SimpleCalculatedFieldConfiguration.class, name = "SIMPLE"), @JsonSubTypes.Type(value = ScriptCalculatedFieldConfiguration.class, name = "SCRIPT") }) +@JsonIgnoreProperties(ignoreUnknown = true) public interface CalculatedFieldConfiguration { @JsonIgnore diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java index e59ff3f4e6..bbce4e2721 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java @@ -79,7 +79,6 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF JsonNode configuration = JacksonUtil.toJsonNode((String) row.get("configuration")); long version = row.get("version") != null ? (long) row.get("version") : 0; String debugSettings = (String) row.get("debug_settings"); - Object externalIdObj = row.get("external_id"); CalculatedField calculatedField = new CalculatedField(); calculatedField.setId(new CalculatedFieldId(id)); @@ -89,7 +88,12 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF calculatedField.setType(type); calculatedField.setName(name); calculatedField.setConfigurationVersion(configurationVersion); - calculatedField.setConfiguration(JacksonUtil.treeToValue(configuration, CalculatedFieldConfiguration.class)); + try { + calculatedField.setConfiguration(JacksonUtil.treeToValue(configuration, CalculatedFieldConfiguration.class)); + } catch (Exception e) { + log.error("Invalid configuration for CalculatedField [{}]. Skipping.", id, e); + return null; + } calculatedField.setVersion(version); calculatedField.setDebugSettings(JacksonUtil.fromString(debugSettings, DebugSettings.class)); @@ -118,7 +122,6 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF EntityType entityType = EntityType.valueOf((String) row.get("entity_type")); UUID entityId = (UUID) row.get("entity_id"); UUID calculatedFieldId = (UUID) row.get("calculated_field_id"); - JsonNode configuration = JacksonUtil.toJsonNode((String) row.get("configuration")); CalculatedFieldLink calculatedFieldLink = new CalculatedFieldLink(); calculatedFieldLink.setId(new CalculatedFieldLinkId(id)); diff --git a/pom.xml b/pom.xml index 02f49f0677..05ca24f06f 100755 --- a/pom.xml +++ b/pom.xml @@ -42,19 +42,19 @@ 4.0.2 2.4.0-b180830.0359 4.0.5 - 10.1.40 + 10.1.42 2.5.2 3.2.12 3.2.12 3.2.12 - 6.1.15 + 6.1.21 6.2.11 - 6.3.8 + 6.3.9 5.1.5 0.12.5 - 2.0.13 - 2.23.1 - 1.5.5 + 2.0.17 + 2.24.3 + 1.5.18 0.10 4.17.0 4.2.25 @@ -83,7 +83,7 @@ 2.3.32 2.0.1 5.6.0 - 3.9.2 + 3.9.3 3.25.5 1.63.0 1.2.6 @@ -103,7 +103,7 @@ 1.19.0 1.78.1 2.0.1 - 42.7.5 + 42.7.7 org/thingsboard/server/gen/**/*, org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* @@ -113,7 +113,7 @@ - 3.7.2 + 3.9.1 8.10.1 3.5.3 2.2 @@ -158,7 +158,7 @@ 2.12.0 3.0.2 - 6.9.0.202403050737-r + 6.10.1.202505221210-r 0.4.8 1.0.0 @@ -1178,7 +1178,7 @@ org.springframework.boot - spring-boot-starter + spring-boot-starter ${spring-boot.version} diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts index 67497b0b6e..7d348662ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts @@ -30,7 +30,7 @@ import { getTimewindowConfig, setTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component'; -import { formatValue, isUndefined } from '@core/utils'; +import { formatValue, isDefined, isUndefined } from '@core/utils'; import { Component } from '@angular/core'; import { convertLevelColorsSettingsToColorProcessor, @@ -115,7 +115,7 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom minMaxColor: [settings.minMaxFont?.color, []], showValue: [settings.showValue, []], - decimals: [configData.config.decimals, []], + decimals: [isDefined(configData.config.decimals) ? configData.config.decimals : settings.decimals, []], units: [configData.config.units, []], valueFont: [settings.valueFont, []], valueColor: [settings.valueFont?.color, []], @@ -157,6 +157,9 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom this.widgetConfig.config.settings.showValue = config.showValue; this.widgetConfig.config.units = config.units; this.widgetConfig.config.decimals = config.decimals; + if (isDefined(this.widgetConfig.config.settings.decimals)) { + delete this.widgetConfig.config.settings.decimals; + } this.widgetConfig.config.settings.valueFont = config.valueFont; this.widgetConfig.config.settings.valueFont.color = config.valueColor; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts index 8c1fc3ab2a..f28b5e8f92 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts @@ -57,6 +57,7 @@ export class KnobComponent extends BasicActionWidgetComponent implements OnInit, maxValue: number; newValue = 0; + private decimals: number; private startDeg = -1; private currentDeg = 0; private rotation = 0; @@ -143,9 +144,10 @@ export class KnobComponent extends BasicActionWidgetComponent implements OnInit, actionLabel: this.ctx.translate.instant('widgets.slider.on-value-change')}; this.valueSetter = this.createValueSetter(valueChangeSettings); + this.decimals = isDefined(this.ctx.decimals) ? this.ctx.decimals : 0; this.valueFormat = ValueFormatProcessor.fromSettings(this.ctx.$injector, { units: this.ctx.units, - decimals: this.ctx.decimals, + decimals: this.decimals, showZeroDecimals: true }); @@ -299,7 +301,7 @@ export class KnobComponent extends BasicActionWidgetComponent implements OnInit, } private turn(ratio: number) { - this.newValue = Number((this.minValue + (this.maxValue - this.minValue) * ratio).toFixed(this.ctx.decimals)); + this.newValue = Number((this.minValue + (this.maxValue - this.minValue) * ratio).toFixed(this.decimals)); if (this.canvasBar.value !== this.newValue) { this.canvasBar.value = this.newValue; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts index e5c57474c2..26a5d6cd4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts @@ -57,7 +57,7 @@ export class KnobControlWidgetSettingsComponent extends WidgetSettingsComponent protected prepareInputSettings(settings: WidgetSettings): WidgetSettings { const knobSettings = prepareKnobSettings(deepClone(settings) as any) as WidgetSettings; - knobSettings.valueDecimals = this.widgetConfig?.config?.decimals ?? 2; + knobSettings.valueDecimals = this.widgetConfig?.config?.decimals; knobSettings.valueUnits = deepClone(this.widgetConfig?.config?.units); return super.prepareInputSettings(knobSettings); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts index 7276c0e27d..1f3ae36089 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts @@ -37,7 +37,7 @@ import { digitalGaugeLayoutTranslations, DigitalGaugeType } from '@home/components/widget/lib/digital-gauge.models'; -import { formatValue } from '@core/utils'; +import { formatValue, isDefined } from '@core/utils'; import { ColorSettings, ColorType, @@ -247,6 +247,10 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent settings.titleFont.color = this.digitalGaugeWidgetSettingsForm.get('titleColor').value; settings.labelFont.color = this.digitalGaugeWidgetSettingsForm.get('labelColor').value; + if (isDefined(settings.decimals)) { + delete settings.decimals; + } + return settings; } diff --git a/ui-ngx/src/app/shared/import-export/import-export.models.ts b/ui-ngx/src/app/shared/import-export/import-export.models.ts index 2f20a421c3..60df84c737 100644 --- a/ui-ngx/src/app/shared/import-export/import-export.models.ts +++ b/ui-ngx/src/app/shared/import-export/import-export.models.ts @@ -160,7 +160,7 @@ export const ZIP_TYPE: FileType = { }; export const CSV_TYPE: FileType = { - mimeType: 'attachament/csv', + mimeType: 'text/csv', extension: 'csv' }; diff --git a/ui-ngx/src/app/shared/models/time/time.models.ts b/ui-ngx/src/app/shared/models/time/time.models.ts index acb62d9d2a..c204cb6867 100644 --- a/ui-ngx/src/app/shared/models/time/time.models.ts +++ b/ui-ngx/src/app/shared/models/time/time.models.ts @@ -431,7 +431,7 @@ export const initModelFromDefaultTimewindow = (value: Timewindow, quickIntervalO if (isDefined(value.history.quickInterval)) { model.history.quickInterval = value.history.quickInterval; } - if (isDefined(value.history.fixedTimewindow)) { + if (isDefinedAndNotNull(value.history.fixedTimewindow)) { if (isDefined(value.history.fixedTimewindow.startTimeMs)) { model.history.fixedTimewindow.startTimeMs = value.history.fixedTimewindow.startTimeMs; } diff --git a/ui-ngx/src/app/shared/models/widget/rpc/knob.component.models.ts b/ui-ngx/src/app/shared/models/widget/rpc/knob.component.models.ts index 47b73f5a08..3ac15bf70c 100644 --- a/ui-ngx/src/app/shared/models/widget/rpc/knob.component.models.ts +++ b/ui-ngx/src/app/shared/models/widget/rpc/knob.component.models.ts @@ -45,7 +45,7 @@ export const knobWidgetDefaultSettings: KnobSettings = { defaultValue: 50, executeRpc: { method: 'getValue', - requestTimeout: 500, + requestTimeout: 5000, requestPersistent: false, persistentPollingInterval: 5000 }, @@ -70,7 +70,7 @@ export const knobWidgetDefaultSettings: KnobSettings = { action: SetValueAction.EXECUTE_RPC, executeRpc: { method: 'setValue', - requestTimeout: 500, + requestTimeout: 5000, requestPersistent: false, persistentPollingInterval: 5000 }, diff --git a/ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md b/ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md index c4092455fa..49f0dd0a2b 100644 --- a/ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md +++ b/ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md @@ -91,11 +91,5 @@ return []; {:copy-code} ``` -
- -You can see real life example, how to use this node in this tutorial: - -- [Data function based on telemetry from 2 devices{:target="_blank"}](${siteBaseUrl}/docs${docPlatformPrefix}/user-guide/rule-engine-2-0/tutorials/function-based-on-telemetry-from-two-devices#delta-temperature-rule-chain) -

diff --git a/ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md b/ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md index 2461f4cace..77da936c73 100644 --- a/ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md +++ b/ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md @@ -91,11 +91,5 @@ return []; {:copy-code} ``` -
- -You can see real life example, how to use this node in this tutorial: - -- [Data function based on telemetry from 2 devices{:target="_blank"}](${siteBaseUrl}/docs${docPlatformPrefix}/user-guide/rule-engine-2-0/tutorials/function-based-on-telemetry-from-two-devices#delta-temperature-rule-chain) -