Merge branch 'rc'

This commit is contained in:
Igor Kulikov 2025-01-22 18:25:11 +02:00
commit f920010786
7 changed files with 29 additions and 16 deletions

View File

@ -66,7 +66,9 @@ import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
@ -78,6 +80,7 @@ import java.util.stream.Collectors;
@Slf4j
public class EdgeImitator {
private static final int MAX_DOWNLINK_FAILS = 2;
private final String routingKey;
private final String routingSecret;
@ -93,6 +96,7 @@ public class EdgeImitator {
private boolean randomFailuresOnTimeseriesDownlink = false;
@Setter
private double failureProbability = 0.0;
private final Map<Integer, Integer> downlinkFailureCountMap = new HashMap<>();
@Getter
private EdgeConfiguration configuration;
@ -244,8 +248,11 @@ public class EdgeImitator {
if (downlinkMsg.getEntityDataCount() > 0) {
for (EntityDataProto entityData : downlinkMsg.getEntityDataList()) {
if (randomFailuresOnTimeseriesDownlink) {
if (getRandomBoolean()) {
int downlinkMsgId = downlinkMsg.getDownlinkMsgId();
if (getRandomBoolean() && checkFailureThreshold(downlinkMsgId)) {
result.add(Futures.immediateFailedFuture(new RuntimeException("Random failure. This is expected error for edge test")));
downlinkFailureCountMap.put(downlinkMsgId, downlinkFailureCountMap.getOrDefault(downlinkMsgId, 0) + 1);
} else {
result.add(saveDownlinkMsg(entityData));
}
@ -354,6 +361,12 @@ public class EdgeImitator {
return Futures.allAsList(result);
}
private boolean checkFailureThreshold(int downlinkMsgId) {
return failureProbability == 100 ||
downlinkFailureCountMap.get(downlinkMsgId) == null ||
downlinkFailureCountMap.get(downlinkMsgId) < MAX_DOWNLINK_FAILS;
}
private boolean getRandomBoolean() {
double randomValue = ThreadLocalRandom.current().nextDouble() * 100;
return randomValue <= this.failureProbability;

View File

@ -109,7 +109,7 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C
if (offset !== 0 && isNumeric(value)) {
lowerLeft = api.coord([startTime, Number(value) >= 0 ? Number(value) + offset : offset]);
} else {
lowerLeft = api.coord([startTime, value]);
lowerLeft = api.coord([startTime, Number(value) >= 0 ? Number(value) : 0]);
}
const size = api.size([delta, value]);
const width = size[0];

View File

@ -260,7 +260,7 @@ export const parseWithTranslation = {
export function functionValueCalculator<T>(useFunction: boolean, func: CompiledTbFunction<GenericFunction>, params = [], defaultValue: T): T {
let res: T;
if (useFunction && isDefined(func) && isFunction(func)) {
if (useFunction && isDefinedAndNotNull(func)) {
try {
res = func.execute(...params);
if (!isDefinedAndNotNull(res) || res === '') {

View File

@ -357,7 +357,7 @@ export default abstract class LeafletMap {
this.map.pm.Toolbar.copyDrawControl('Circle', {
name: 'tbCircle',
afterClick: () => this.selectEntityWithoutLocation('tbCircle'),
disabled: true,
disabled: false,
actions
});
}

View File

@ -21,20 +21,20 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import {
CircleSettings,
CommonMapSettings,
defaultCircleSettings,
defaultCommonMapSettings,
defaultMapProviderSettings,
defaultMarkersSettings,
defaultPolygonSettings,
defaultTripAnimationCommonSettings,
defaultTripAnimationMarkersSettings,
defaultTripAnimationPathSettings,
defaultTripAnimationPointSettings,
defaultTripAnimationSettings,
MapProviderSettings,
MarkersSettings,
PointsSettings,
PolygonSettings,
PolylineSettings
PolylineSettings,
TripAnimationCommonSettings,
TripAnimationMarkerSettings
} from 'src/app/modules/home/components/widget/lib/maps/map-models';
import { extractType } from '@core/utils';
@ -76,8 +76,8 @@ export class TripAnimationWidgetSettingsComponent extends WidgetSettingsComponen
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const mapProviderSettings = extractType<MapProviderSettings>(settings, Object.keys(defaultMapProviderSettings) as (keyof MapProviderSettings)[]);
const commonMapSettings = extractType<CommonMapSettings>(settings, Object.keys(defaultCommonMapSettings) as (keyof CommonMapSettings)[]);
const markersSettings = extractType<MarkersSettings>(settings, Object.keys(defaultMarkersSettings) as (keyof MarkersSettings)[]);
const commonMapSettings = extractType<TripAnimationCommonSettings>(settings, Object.keys(defaultTripAnimationCommonSettings) as (keyof TripAnimationCommonSettings)[]);
const markersSettings = extractType<TripAnimationMarkerSettings>(settings, Object.keys(defaultTripAnimationMarkersSettings) as (keyof TripAnimationMarkerSettings)[]);
const pathSettings = extractType<PolylineSettings>(settings, Object.keys(defaultTripAnimationPathSettings) as (keyof PolylineSettings)[]);
const pointSettings = extractType<PointsSettings>(settings, Object.keys(defaultTripAnimationPointSettings) as (keyof PointsSettings)[]);
const polygonSettings = extractType<PolygonSettings>(settings, Object.keys(defaultPolygonSettings) as (keyof PolygonSettings)[]);

View File

@ -107,7 +107,7 @@
<mat-label translate>mobile.latest-version</mat-label>
<input matInput formControlName="latestVersion">
<mat-hint> </mat-hint>
<mat-error *ngIf="entityForm.get('versionInfo.minVersion').hasError('pattern')">
<mat-error *ngIf="entityForm.get('versionInfo.latestVersion').hasError('pattern')">
{{ 'mobile.invalid-version-pattern' | translate }}
</mat-error>
</mat-form-field>
@ -130,7 +130,7 @@
<mat-label>{{
(entityForm.get('platformType').value === PlatformType.ANDROID ? 'mobile.google-play-link' : 'mobile.app-store-link') | translate
}}</mat-label>
<input matInput [required]="entityForm.get('status').value === 'PUBLISHED'" formControlName="storeLink">
<input matInput [required]="entityForm.get('status').value === MobileAppStatus.PUBLISHED" formControlName="storeLink">
<tb-copy-button
matSuffix
miniButton="false"
@ -148,7 +148,7 @@
</mat-form-field>
<mat-form-field appearance="outline" *ngIf="entityForm.get('platformType').value === PlatformType.ANDROID">
<mat-label translate>mobile.sha256-certificate-fingerprints</mat-label>
<input matInput [required]="entityForm.get('status').value !== MobileAppStatus.DRAFT" formControlName="sha256CertFingerprints">
<input matInput [required]="entityForm.get('status').value === MobileAppStatus.PUBLISHED" formControlName="sha256CertFingerprints">
<tb-copy-button
matSuffix
miniButton="false"
@ -166,7 +166,7 @@
</mat-form-field>
<mat-form-field appearance="outline" *ngIf="entityForm.get('platformType').value === PlatformType.IOS">
<mat-label translate>mobile.app-id</mat-label>
<input matInput [required]="entityForm.get('status').value !== MobileAppStatus.DRAFT" formControlName="appId">
<input matInput [required]="entityForm.get('status').value === MobileAppStatus.PUBLISHED" formControlName="appId">
<tb-copy-button
matSuffix
miniButton="false"

View File

@ -101,7 +101,7 @@ export class MobileAppComponent extends EntityComponent<MobileApp> {
form.get('status').valueChanges.pipe(
takeUntilDestroyed()
).subscribe((value: MobileAppStatus) => {
if (value !== MobileAppStatus.DRAFT) {
if (value === MobileAppStatus.PUBLISHED) {
form.get('storeInfo.storeLink').addValidators(Validators.required);
form.get('storeInfo.sha256CertFingerprints')
.addValidators(Validators.required);