|
|
@ -32,6 +32,8 @@ import org.thingsboard.server.common.data.ApiUsageRecordKey; |
|
|
import org.thingsboard.server.common.data.AttributeScope; |
|
|
import org.thingsboard.server.common.data.AttributeScope; |
|
|
import org.thingsboard.server.common.data.EntityType; |
|
|
import org.thingsboard.server.common.data.EntityType; |
|
|
import org.thingsboard.server.common.data.EntityView; |
|
|
import org.thingsboard.server.common.data.EntityView; |
|
|
|
|
|
import org.thingsboard.server.common.data.cf.CalculatedFieldLink; |
|
|
|
|
|
import org.thingsboard.server.common.data.id.CalculatedFieldId; |
|
|
import org.thingsboard.server.common.data.id.CustomerId; |
|
|
import org.thingsboard.server.common.data.id.CustomerId; |
|
|
import org.thingsboard.server.common.data.id.EntityId; |
|
|
import org.thingsboard.server.common.data.id.EntityId; |
|
|
import org.thingsboard.server.common.data.id.TenantId; |
|
|
import org.thingsboard.server.common.data.id.TenantId; |
|
|
@ -40,6 +42,7 @@ import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
|
|
import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.DeleteTsKvQuery; |
|
|
import org.thingsboard.server.common.data.kv.DeleteTsKvQuery; |
|
|
import org.thingsboard.server.common.data.kv.DoubleDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.DoubleDataEntry; |
|
|
|
|
|
import org.thingsboard.server.common.data.kv.KvEntry; |
|
|
import org.thingsboard.server.common.data.kv.LongDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.LongDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.StringDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.StringDataEntry; |
|
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
|
|
import org.thingsboard.server.common.data.kv.TsKvEntry; |
|
|
@ -47,9 +50,11 @@ import org.thingsboard.server.common.data.kv.TsKvLatestRemovingResult; |
|
|
import org.thingsboard.server.common.msg.queue.TbCallback; |
|
|
import org.thingsboard.server.common.msg.queue.TbCallback; |
|
|
import org.thingsboard.server.common.stats.TbApiUsageReportClient; |
|
|
import org.thingsboard.server.common.stats.TbApiUsageReportClient; |
|
|
import org.thingsboard.server.dao.attributes.AttributesService; |
|
|
import org.thingsboard.server.dao.attributes.AttributesService; |
|
|
|
|
|
import org.thingsboard.server.dao.cf.CalculatedFieldService; |
|
|
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
|
|
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
|
|
import org.thingsboard.server.dao.util.KvUtils; |
|
|
import org.thingsboard.server.dao.util.KvUtils; |
|
|
import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
|
|
import org.thingsboard.server.service.apiusage.TbApiUsageStateService; |
|
|
|
|
|
import org.thingsboard.server.service.cf.CalculatedFieldExecutionService; |
|
|
import org.thingsboard.server.service.entitiy.entityview.TbEntityViewService; |
|
|
import org.thingsboard.server.service.entitiy.entityview.TbEntityViewService; |
|
|
import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
|
|
import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
|
|
|
|
|
|
|
|
@ -77,6 +82,8 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
private final TbEntityViewService tbEntityViewService; |
|
|
private final TbEntityViewService tbEntityViewService; |
|
|
private final TbApiUsageReportClient apiUsageClient; |
|
|
private final TbApiUsageReportClient apiUsageClient; |
|
|
private final TbApiUsageStateService apiUsageStateService; |
|
|
private final TbApiUsageStateService apiUsageStateService; |
|
|
|
|
|
private final CalculatedFieldService calculatedFieldService; |
|
|
|
|
|
private final CalculatedFieldExecutionService calculatedFieldExecutionService; |
|
|
|
|
|
|
|
|
private ExecutorService tsCallBackExecutor; |
|
|
private ExecutorService tsCallBackExecutor; |
|
|
|
|
|
|
|
|
@ -87,12 +94,16 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
TimeseriesService tsService, |
|
|
TimeseriesService tsService, |
|
|
@Lazy TbEntityViewService tbEntityViewService, |
|
|
@Lazy TbEntityViewService tbEntityViewService, |
|
|
TbApiUsageReportClient apiUsageClient, |
|
|
TbApiUsageReportClient apiUsageClient, |
|
|
TbApiUsageStateService apiUsageStateService) { |
|
|
TbApiUsageStateService apiUsageStateService, |
|
|
|
|
|
CalculatedFieldService calculatedFieldService, |
|
|
|
|
|
CalculatedFieldExecutionService calculatedFieldExecutionService) { |
|
|
this.attrService = attrService; |
|
|
this.attrService = attrService; |
|
|
this.tsService = tsService; |
|
|
this.tsService = tsService; |
|
|
this.tbEntityViewService = tbEntityViewService; |
|
|
this.tbEntityViewService = tbEntityViewService; |
|
|
this.apiUsageClient = apiUsageClient; |
|
|
this.apiUsageClient = apiUsageClient; |
|
|
this.apiUsageStateService = apiUsageStateService; |
|
|
this.apiUsageStateService = apiUsageStateService; |
|
|
|
|
|
this.calculatedFieldService = calculatedFieldService; |
|
|
|
|
|
this.calculatedFieldExecutionService = calculatedFieldExecutionService; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@PostConstruct |
|
|
@PostConstruct |
|
|
@ -179,6 +190,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
addMainCallback(saveFuture, callback); |
|
|
addMainCallback(saveFuture, callback); |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
addEntityViewCallback(tenantId, entityId, ts); |
|
|
addEntityViewCallback(tenantId, entityId, ts); |
|
|
|
|
|
updateTelemetryInCalculatedFields(tenantId, entityId, ts); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void saveWithoutLatestAndNotifyInternal(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Integer> callback) { |
|
|
private void saveWithoutLatestAndNotifyInternal(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, long ttl, FutureCallback<Integer> callback) { |
|
|
@ -187,6 +199,49 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void updateTelemetryInCalculatedFields(TenantId tenantId, EntityId entityId, List<? extends KvEntry> telemetry) { |
|
|
|
|
|
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) { |
|
|
|
|
|
List<CalculatedFieldLink> cfLinks = calculatedFieldService.findAllCalculatedFieldLinksByEntityId(tenantId, entityId); |
|
|
|
|
|
if (!cfLinks.isEmpty()) { |
|
|
|
|
|
cfLinks.forEach(link -> { |
|
|
|
|
|
CalculatedFieldId calculatedFieldId = link.getCalculatedFieldId(); |
|
|
|
|
|
Map<String, String> attributes = link.getConfiguration().getAttributes(); |
|
|
|
|
|
Map<String, String> timeSeries = link.getConfiguration().getTimeSeries(); |
|
|
|
|
|
List<? extends KvEntry> filteredTelemetry = telemetry.stream() |
|
|
|
|
|
.filter(entry -> attributes.containsValue(entry.getKey()) || timeSeries.containsValue(entry.getKey())) |
|
|
|
|
|
.toList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, String> updatedTelemetry = new HashMap<>(); |
|
|
|
|
|
for (KvEntry telemetryEntry : filteredTelemetry) { |
|
|
|
|
|
String key = telemetryEntry.getKey(); |
|
|
|
|
|
if (telemetryEntry instanceof AttributeKvEntry) { |
|
|
|
|
|
for (Map.Entry<String, String> attribute : attributes.entrySet()) { |
|
|
|
|
|
if (telemetryEntry.getKey().equals(attribute.getValue())) { |
|
|
|
|
|
key = attribute.getKey(); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (telemetryEntry instanceof TsKvEntry) { |
|
|
|
|
|
for (Map.Entry<String, String> timeSeriesEntry : timeSeries.entrySet()) { |
|
|
|
|
|
if (telemetryEntry.getKey().equals(timeSeriesEntry.getValue())) { |
|
|
|
|
|
key = timeSeriesEntry.getKey(); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
updatedTelemetry.put(key, telemetryEntry.getValueAsString()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!updatedTelemetry.isEmpty()) { |
|
|
|
|
|
calculatedFieldExecutionService.onTelemetryUpdate(tenantId, calculatedFieldId, updatedTelemetry); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private void addEntityViewCallback(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts) { |
|
|
private void addEntityViewCallback(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts) { |
|
|
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) { |
|
|
if (EntityType.DEVICE.equals(entityId.getEntityType()) || EntityType.ASSET.equals(entityId.getEntityType())) { |
|
|
Futures.addCallback(this.tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId), |
|
|
Futures.addCallback(this.tbEntityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId), |
|
|
@ -263,6 +318,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
ListenableFuture<List<Long>> saveFuture = attrService.save(tenantId, entityId, scope, attributes); |
|
|
ListenableFuture<List<Long>> saveFuture = attrService.save(tenantId, entityId, scope, attributes); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addWsCallback(saveFuture, success -> onAttributesUpdate(tenantId, entityId, scope, attributes, notifyDevice)); |
|
|
addWsCallback(saveFuture, success -> onAttributesUpdate(tenantId, entityId, scope, attributes, notifyDevice)); |
|
|
|
|
|
updateTelemetryInCalculatedFields(tenantId, entityId, attributes); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@ -270,6 +326,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
ListenableFuture<List<Long>> saveFuture = attrService.save(tenantId, entityId, scope, attributes); |
|
|
ListenableFuture<List<Long>> saveFuture = attrService.save(tenantId, entityId, scope, attributes); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addWsCallback(saveFuture, success -> onAttributesUpdate(tenantId, entityId, scope.name(), attributes, notifyDevice)); |
|
|
addWsCallback(saveFuture, success -> onAttributesUpdate(tenantId, entityId, scope.name(), attributes, notifyDevice)); |
|
|
|
|
|
updateTelemetryInCalculatedFields(tenantId, entityId, attributes); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@ -283,6 +340,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer |
|
|
ListenableFuture<List<Long>> saveFuture = tsService.saveLatest(tenantId, entityId, ts); |
|
|
ListenableFuture<List<Long>> saveFuture = tsService.saveLatest(tenantId, entityId, ts); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addVoidCallback(saveFuture, callback); |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
addWsCallback(saveFuture, success -> onTimeSeriesUpdate(tenantId, entityId, ts)); |
|
|
|
|
|
updateTelemetryInCalculatedFields(tenantId, entityId, ts); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
|