Browse Source

Merge branch 'rc' of github.com:thingsboard/thingsboard into performance

pull/13510/head
IrynaMatveieva 1 year ago
parent
commit
6f5e375ae1
  1. 7
      application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java
  2. 2
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntry.java
  3. 2
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java
  4. 4
      application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java
  5. 7
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntryTest.java
  6. 2
      common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/CalculatedFieldConfiguration.java
  7. 9
      dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java
  8. 7
      ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts
  9. 6
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/knob.component.ts
  10. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/control/knob-control-widget-settings.component.ts
  11. 6
      ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts
  12. 2
      ui-ngx/src/app/shared/import-export/import-export.models.ts
  13. 2
      ui-ngx/src/app/shared/models/time/time.models.ts
  14. 4
      ui-ngx/src/app/shared/models/widget/rpc/knob.component.models.ts
  15. 6
      ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md
  16. 6
      ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md

7
application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java

@ -71,11 +71,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<CalculatedField> 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);

2
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntry.java

@ -107,7 +107,7 @@ public class SingleValueArgumentEntry implements ArgumentEntry {
@Override
public boolean updateEntry(ArgumentEntry entry) {
if (entry instanceof SingleValueArgumentEntry singleValueEntry) {
if (singleValueEntry.getTs() == this.ts) {
if (singleValueEntry.getTs() <= this.ts) {
return false;
}

2
application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/ResourceImportService.java

@ -66,7 +66,7 @@ public class ResourceImportService extends BaseEntityImportService<TbResourceId,
protected void cleanupForComparison(TbResource resource) {
super.cleanupForComparison(resource);
resource.setSearchText(null);
if (resource.getDescriptor().isNull()) {
if (resource.getDescriptor() != null && resource.getDescriptor().isNull()) {
resource.setDescriptor(null);
}
}

4
application/src/test/java/org/thingsboard/server/cf/CalculatedFieldIntegrationTest.java

@ -555,7 +555,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
});
long tsABeforeTsB = tsB - 300L;
doPost("/api/plugins/telemetry/DEVICE/" + testDevice.getUuidId() + "/timeseries/" + DataConstants.SERVER_SCOPE, JacksonUtil.toJsonNode(String.format("{\"ts\": %s, \"values\": {\"b\":10}}", tsABeforeTsB)));
doPost("/api/plugins/telemetry/DEVICE/" + testDevice.getUuidId() + "/timeseries/" + DataConstants.SERVER_SCOPE, JacksonUtil.toJsonNode(String.format("{\"ts\": %s, \"values\": {\"a\":10}}", tsABeforeTsB)));
await().alias("update telemetry with ts less than latest -> save result with latest ts").atMost(TIMEOUT, TimeUnit.SECONDS)
.pollInterval(POLL_INTERVAL, TimeUnit.SECONDS)
@ -563,7 +563,7 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
ObjectNode c = getLatestTelemetry(testDevice.getId(), "c");
assertThat(c).isNotNull();
assertThat(c.get("c").get(0).get("ts").asText()).isEqualTo(Long.toString(tsB));// also tsB, since this is the latest timestamp
assertThat(c.get("c").get(0).get("value").asText()).isEqualTo("11.0");
assertThat(c.get("c").get(0).get("value").asText()).isEqualTo("15.0");
});
}

7
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SingleValueArgumentEntryTest.java

@ -53,7 +53,7 @@ public class SingleValueArgumentEntryTest {
}
@Test
void testUpdateEntryWithThaSameTs() {
void testUpdateEntryWithTheSameTs() {
assertThat(entry.updateEntry(new SingleValueArgumentEntry(ts, new LongDataEntry("key", 13L), 363L))).isFalse();
}
@ -81,6 +81,11 @@ public class SingleValueArgumentEntryTest {
assertThat(entry.updateEntry(new SingleValueArgumentEntry(ts + 18, new LongDataEntry("key", 11L), 364L))).isTrue();
}
@Test
void testUpdateEntryWithOldTs() {
assertThat(entry.updateEntry(new SingleValueArgumentEntry(ts - 10, new LongDataEntry("key", 14L), 365L))).isFalse();
}
@Test
void testToTbelCfArgWhenJsonIsObject() {
entry = new SingleValueArgumentEntry(ts, new JsonDataEntry("key", "{\"test\": 10}"), 370L);

2
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

9
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));

7
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;

6
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;
}

2
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);
}

6
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;
}

2
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'
};

2
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;
}

4
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
},

6
ui-ngx/src/assets/help/en_US/rulenode/switch_node_script_fn.md

@ -91,11 +91,5 @@ return [];
{:copy-code}
```
<br>
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)
<br>
<br>

6
ui-ngx/src/assets/help/en_US/rulenode/tbel/switch_node_script_fn.md

@ -91,11 +91,5 @@ return [];
{:copy-code}
```
<br>
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)
<br>
<br>

Loading…
Cancel
Save