Merge pull request #7982 from volodymyr-babak/edge/processors-refactoring
[3.5] Edge processors refactoring - move common part of edge / server to base classes
This commit is contained in:
commit
45e93cfc79
@ -41,22 +41,22 @@ import org.thingsboard.server.dao.edge.EdgeEventService;
|
|||||||
import org.thingsboard.server.dao.edge.EdgeService;
|
import org.thingsboard.server.dao.edge.EdgeService;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AlarmEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AssetEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AssetProfileEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetProfileEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.CustomerEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.customer.CustomerEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DashboardEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DeviceEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DeviceProfileEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceProfileEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.EdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.EntityViewEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.OtaPackageEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.QueueEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.RuleChainEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.rule.RuleChainEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.UserEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.user.UserEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.WidgetBundleEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetBundleEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.WidgetTypeEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetTypeEdgeProcessor;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|||||||
@ -40,24 +40,24 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
|||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings;
|
import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings;
|
||||||
import org.thingsboard.server.service.edge.rpc.constructor.EdgeMsgConstructor;
|
import org.thingsboard.server.service.edge.rpc.constructor.EdgeMsgConstructor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AdminSettingsEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.settings.AdminSettingsEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AlarmEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AssetEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.AssetProfileEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetProfileEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.CustomerEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.customer.CustomerEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DashboardEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DeviceEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.DeviceProfileEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceProfileEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.EdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.EntityViewEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.OtaPackageEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.QueueEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.RuleChainEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.rule.RuleChainEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.TelemetryEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.telemetry.TelemetryEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.UserEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.user.UserEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.WidgetBundleEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetBundleEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.processor.WidgetTypeEdgeProcessor;
|
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetTypeEdgeProcessor;
|
||||||
import org.thingsboard.server.service.edge.rpc.sync.EdgeRequestsService;
|
import org.thingsboard.server.service.edge.rpc.sync.EdgeRequestsService;
|
||||||
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
||||||
import org.thingsboard.server.service.executors.GrpcCallbackExecutorService;
|
import org.thingsboard.server.service.executors.GrpcCallbackExecutorService;
|
||||||
|
|||||||
@ -457,7 +457,6 @@ public final class EdgeGrpcSession implements Closeable {
|
|||||||
case ASSIGNED_TO_CUSTOMER:
|
case ASSIGNED_TO_CUSTOMER:
|
||||||
case UNASSIGNED_FROM_CUSTOMER:
|
case UNASSIGNED_FROM_CUSTOMER:
|
||||||
case CREDENTIALS_REQUEST:
|
case CREDENTIALS_REQUEST:
|
||||||
case ENTITY_MERGE_REQUEST:
|
|
||||||
case RPC_CALL:
|
case RPC_CALL:
|
||||||
downlinkMsg = convertEntityEventToDownlink(edgeEvent);
|
downlinkMsg = convertEntityEventToDownlink(edgeEvent);
|
||||||
log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg);
|
log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg);
|
||||||
@ -556,27 +555,27 @@ public final class EdgeGrpcSession implements Closeable {
|
|||||||
try {
|
try {
|
||||||
if (uplinkMsg.getEntityDataCount() > 0) {
|
if (uplinkMsg.getEntityDataCount() > 0) {
|
||||||
for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) {
|
for (EntityDataProto entityData : uplinkMsg.getEntityDataList()) {
|
||||||
result.addAll(ctx.getTelemetryProcessor().processTelemetryFromEdge(edge.getTenantId(), entityData));
|
result.addAll(ctx.getTelemetryProcessor().processTelemetryMsg(edge.getTenantId(), entityData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uplinkMsg.getDeviceUpdateMsgCount() > 0) {
|
if (uplinkMsg.getDeviceUpdateMsgCount() > 0) {
|
||||||
for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) {
|
for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) {
|
||||||
result.add(ctx.getDeviceProcessor().processDeviceFromEdge(edge.getTenantId(), edge, deviceUpdateMsg));
|
result.add(ctx.getDeviceProcessor().processDeviceMsgFromEdge(edge.getTenantId(), edge, deviceUpdateMsg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) {
|
if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) {
|
||||||
for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) {
|
for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) {
|
||||||
result.add(ctx.getDeviceProcessor().processDeviceCredentialsFromEdge(edge.getTenantId(), deviceCredentialsUpdateMsg));
|
result.add(ctx.getDeviceProcessor().processDeviceCredentialsMsg(edge.getTenantId(), deviceCredentialsUpdateMsg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uplinkMsg.getAlarmUpdateMsgCount() > 0) {
|
if (uplinkMsg.getAlarmUpdateMsgCount() > 0) {
|
||||||
for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) {
|
for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) {
|
||||||
result.add(ctx.getAlarmProcessor().processAlarmFromEdge(edge.getTenantId(), alarmUpdateMsg));
|
result.add(ctx.getAlarmProcessor().processAlarmMsg(edge.getTenantId(), alarmUpdateMsg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uplinkMsg.getRelationUpdateMsgCount() > 0) {
|
if (uplinkMsg.getRelationUpdateMsgCount() > 0) {
|
||||||
for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) {
|
for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) {
|
||||||
result.add(ctx.getRelationProcessor().processRelationFromEdge(edge.getTenantId(), relationUpdateMsg));
|
result.add(ctx.getRelationProcessor().processRelationMsg(edge.getTenantId(), relationUpdateMsg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) {
|
if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) {
|
||||||
|
|||||||
@ -41,7 +41,7 @@ public class DeviceMsgConstructor {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DataDecodingEncodingService dataDecodingEncodingService;
|
private DataDecodingEncodingService dataDecodingEncodingService;
|
||||||
|
|
||||||
public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, String conflictName) {
|
public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) {
|
||||||
DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
|
DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
|
||||||
.setMsgType(msgType)
|
.setMsgType(msgType)
|
||||||
.setIdMSB(device.getId().getId().getMostSignificantBits())
|
.setIdMSB(device.getId().getId().getMostSignificantBits())
|
||||||
@ -70,9 +70,6 @@ public class DeviceMsgConstructor {
|
|||||||
builder.setSoftwareIdMSB(device.getSoftwareId().getId().getMostSignificantBits())
|
builder.setSoftwareIdMSB(device.getSoftwareId().getId().getMostSignificantBits())
|
||||||
.setSoftwareIdLSB(device.getSoftwareId().getId().getLeastSignificantBits());
|
.setSoftwareIdLSB(device.getSoftwareId().getId().getLeastSignificantBits());
|
||||||
}
|
}
|
||||||
if (conflictName != null) {
|
|
||||||
builder.setConflictName(conflictName);
|
|
||||||
}
|
|
||||||
if (device.getDeviceData() != null) {
|
if (device.getDeviceData() != null) {
|
||||||
builder.setDeviceDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(device.getDeviceData())));
|
builder.setDeviceDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(device.getDeviceData())));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,195 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright © 2016-2022 The Thingsboard Authors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
|
||||||
import org.thingsboard.server.common.data.EdgeUtils;
|
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
|
||||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
|
||||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
|
||||||
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
|
||||||
import org.thingsboard.server.common.data.id.AlarmId;
|
|
||||||
import org.thingsboard.server.common.data.id.EdgeId;
|
|
||||||
import org.thingsboard.server.common.data.id.EntityId;
|
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
|
||||||
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
|
|
||||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|
||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
@TbCoreComponent
|
|
||||||
public class AlarmEdgeProcessor extends BaseEdgeProcessor {
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processAlarmFromEdge(TenantId tenantId, AlarmUpdateMsg alarmUpdateMsg) {
|
|
||||||
log.trace("[{}] processAlarmFromEdge [{}]", tenantId, alarmUpdateMsg);
|
|
||||||
EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(),
|
|
||||||
EntityType.valueOf(alarmUpdateMsg.getOriginatorType()));
|
|
||||||
if (originatorId == null) {
|
|
||||||
log.warn("Originator not found for the alarm msg {}", alarmUpdateMsg);
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Alarm existentAlarm = alarmService.findLatestByOriginatorAndType(tenantId, originatorId, alarmUpdateMsg.getType()).get();
|
|
||||||
switch (alarmUpdateMsg.getMsgType()) {
|
|
||||||
case ENTITY_CREATED_RPC_MESSAGE:
|
|
||||||
case ENTITY_UPDATED_RPC_MESSAGE:
|
|
||||||
if (existentAlarm == null || existentAlarm.getStatus().isCleared()) {
|
|
||||||
existentAlarm = new Alarm();
|
|
||||||
existentAlarm.setTenantId(tenantId);
|
|
||||||
existentAlarm.setType(alarmUpdateMsg.getName());
|
|
||||||
existentAlarm.setOriginator(originatorId);
|
|
||||||
existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity()));
|
|
||||||
existentAlarm.setStartTs(alarmUpdateMsg.getStartTs());
|
|
||||||
existentAlarm.setClearTs(alarmUpdateMsg.getClearTs());
|
|
||||||
existentAlarm.setPropagate(alarmUpdateMsg.getPropagate());
|
|
||||||
}
|
|
||||||
existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus()));
|
|
||||||
existentAlarm.setAckTs(alarmUpdateMsg.getAckTs());
|
|
||||||
existentAlarm.setEndTs(alarmUpdateMsg.getEndTs());
|
|
||||||
existentAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()));
|
|
||||||
alarmService.createOrUpdateAlarm(existentAlarm);
|
|
||||||
break;
|
|
||||||
case ALARM_ACK_RPC_MESSAGE:
|
|
||||||
if (existentAlarm != null) {
|
|
||||||
alarmService.ackAlarm(tenantId, existentAlarm.getId(), alarmUpdateMsg.getAckTs());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ALARM_CLEAR_RPC_MESSAGE:
|
|
||||||
if (existentAlarm != null) {
|
|
||||||
alarmService.clearAlarm(tenantId, existentAlarm.getId(),
|
|
||||||
JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ENTITY_DELETED_RPC_MESSAGE:
|
|
||||||
if (existentAlarm != null) {
|
|
||||||
alarmService.deleteAlarm(tenantId, existentAlarm.getId());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to process alarm update msg [{}]", alarmUpdateMsg, e);
|
|
||||||
return Futures.immediateFailedFuture(new RuntimeException("Failed to process alarm update msg", e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private EntityId getAlarmOriginator(TenantId tenantId, String entityName, EntityType entityType) {
|
|
||||||
switch (entityType) {
|
|
||||||
case DEVICE:
|
|
||||||
return deviceService.findDeviceByTenantIdAndName(tenantId, entityName).getId();
|
|
||||||
case ASSET:
|
|
||||||
return assetService.findAssetByTenantIdAndName(tenantId, entityName).getId();
|
|
||||||
case ENTITY_VIEW:
|
|
||||||
return entityViewService.findEntityViewByTenantIdAndName(tenantId, entityName).getId();
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownlinkMsg convertAlarmEventToDownlink(EdgeEvent edgeEvent) {
|
|
||||||
AlarmId alarmId = new AlarmId(edgeEvent.getEntityId());
|
|
||||||
DownlinkMsg downlinkMsg = null;
|
|
||||||
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
|
|
||||||
switch (edgeEvent.getAction()) {
|
|
||||||
case ADDED:
|
|
||||||
case UPDATED:
|
|
||||||
case ALARM_ACK:
|
|
||||||
case ALARM_CLEAR:
|
|
||||||
try {
|
|
||||||
Alarm alarm = alarmService.findAlarmByIdAsync(edgeEvent.getTenantId(), alarmId).get();
|
|
||||||
if (alarm != null) {
|
|
||||||
downlinkMsg = DownlinkMsg.newBuilder()
|
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
|
||||||
.addAlarmUpdateMsg(alarmMsgConstructor.constructAlarmUpdatedMsg(edgeEvent.getTenantId(), msgType, alarm))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Can't process alarm msg [{}] [{}]", edgeEvent, msgType, e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DELETED:
|
|
||||||
Alarm alarm = JacksonUtil.OBJECT_MAPPER.convertValue(edgeEvent.getBody(), Alarm.class);
|
|
||||||
AlarmUpdateMsg alarmUpdateMsg =
|
|
||||||
alarmMsgConstructor.constructAlarmUpdatedMsg(edgeEvent.getTenantId(), msgType, alarm);
|
|
||||||
downlinkMsg = DownlinkMsg.newBuilder()
|
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
|
||||||
.addAlarmUpdateMsg(alarmUpdateMsg)
|
|
||||||
.build();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return downlinkMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
|
|
||||||
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
|
|
||||||
AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
|
|
||||||
switch (actionType) {
|
|
||||||
case DELETED:
|
|
||||||
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
|
|
||||||
Alarm deletedAlarm = JacksonUtil.OBJECT_MAPPER.readValue(edgeNotificationMsg.getBody(), Alarm.class);
|
|
||||||
return saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, JacksonUtil.OBJECT_MAPPER.valueToTree(deletedAlarm));
|
|
||||||
default:
|
|
||||||
ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId);
|
|
||||||
return Futures.transformAsync(alarmFuture, alarm -> {
|
|
||||||
if (alarm == null) {
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType());
|
|
||||||
if (type == null) {
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
|
||||||
PageData<EdgeId> pageData;
|
|
||||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
|
||||||
do {
|
|
||||||
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink);
|
|
||||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
|
||||||
for (EdgeId relatedEdgeId : pageData.getData()) {
|
|
||||||
futures.add(saveEdgeEvent(tenantId,
|
|
||||||
relatedEdgeId,
|
|
||||||
EdgeEventType.ALARM,
|
|
||||||
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
|
|
||||||
alarmId,
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
if (pageData.hasNext()) {
|
|
||||||
pageLink = pageLink.nextPageLink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (pageData != null && pageData.hasNext());
|
|
||||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
|
||||||
}, dbCallbackExecutorService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -97,10 +97,14 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class BaseEdgeProcessor {
|
public abstract class BaseEdgeProcessor {
|
||||||
|
|
||||||
|
protected static final Lock deviceCreationLock = new ReentrantLock();
|
||||||
|
|
||||||
protected static final int DEFAULT_PAGE_SIZE = 100;
|
protected static final int DEFAULT_PAGE_SIZE = 100;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -468,4 +472,17 @@ public abstract class BaseEdgeProcessor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected UUID safeGetUUID(long mSB, long lSB) {
|
||||||
|
return mSB != 0 && lSB != 0 ? new UUID(mSB, lSB) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CustomerId safeGetCustomerId(long mSB, long lSB) {
|
||||||
|
CustomerId customerId = null;
|
||||||
|
UUID customerUUID = safeGetUUID(mSB, lSB);
|
||||||
|
if (customerUUID != null) {
|
||||||
|
customerId = new CustomerId(customerUUID);
|
||||||
|
}
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.edge.rpc.processor.alarm;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.server.common.data.EdgeUtils;
|
||||||
|
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||||
|
import org.thingsboard.server.common.data.id.AlarmId;
|
||||||
|
import org.thingsboard.server.common.data.id.EdgeId;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
|
import org.thingsboard.server.common.data.page.PageLink;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@TbCoreComponent
|
||||||
|
public class AlarmEdgeProcessor extends BaseAlarmProcessor {
|
||||||
|
|
||||||
|
public DownlinkMsg convertAlarmEventToDownlink(EdgeEvent edgeEvent) {
|
||||||
|
AlarmUpdateMsg alarmUpdateMsg =
|
||||||
|
convertAlarmEventToAlarmMsg(edgeEvent.getTenantId(), edgeEvent.getEntityId(), edgeEvent.getAction(), edgeEvent.getBody());
|
||||||
|
if (alarmUpdateMsg != null) {
|
||||||
|
return DownlinkMsg.newBuilder()
|
||||||
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
||||||
|
.addAlarmUpdateMsg(alarmUpdateMsg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Void> processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
|
||||||
|
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
|
||||||
|
AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
|
||||||
|
switch (actionType) {
|
||||||
|
case DELETED:
|
||||||
|
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
|
||||||
|
Alarm deletedAlarm = JacksonUtil.OBJECT_MAPPER.readValue(edgeNotificationMsg.getBody(), Alarm.class);
|
||||||
|
return saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, JacksonUtil.OBJECT_MAPPER.valueToTree(deletedAlarm));
|
||||||
|
default:
|
||||||
|
ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId);
|
||||||
|
return Futures.transformAsync(alarmFuture, alarm -> {
|
||||||
|
if (alarm == null) {
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType());
|
||||||
|
if (type == null) {
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
||||||
|
PageData<EdgeId> pageData;
|
||||||
|
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||||
|
do {
|
||||||
|
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink);
|
||||||
|
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
||||||
|
for (EdgeId relatedEdgeId : pageData.getData()) {
|
||||||
|
futures.add(saveEdgeEvent(tenantId,
|
||||||
|
relatedEdgeId,
|
||||||
|
EdgeEventType.ALARM,
|
||||||
|
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
|
||||||
|
alarmId,
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
if (pageData.hasNext()) {
|
||||||
|
pageLink = pageLink.nextPageLink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (pageData != null && pageData.hasNext());
|
||||||
|
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
||||||
|
}, dbCallbackExecutorService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.edge.rpc.processor.alarm;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||||
|
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||||
|
import org.thingsboard.server.common.data.alarm.AlarmStatus;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
|
import org.thingsboard.server.common.data.id.AlarmId;
|
||||||
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class BaseAlarmProcessor extends BaseEdgeProcessor {
|
||||||
|
|
||||||
|
public ListenableFuture<Void> processAlarmMsg(TenantId tenantId, AlarmUpdateMsg alarmUpdateMsg) {
|
||||||
|
log.trace("[{}] processAlarmMsg [{}]", tenantId, alarmUpdateMsg);
|
||||||
|
EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(),
|
||||||
|
EntityType.valueOf(alarmUpdateMsg.getOriginatorType()));
|
||||||
|
if (originatorId == null) {
|
||||||
|
log.warn("Originator not found for the alarm msg {}", alarmUpdateMsg);
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Alarm existentAlarm = alarmService.findLatestByOriginatorAndType(tenantId, originatorId, alarmUpdateMsg.getType()).get();
|
||||||
|
switch (alarmUpdateMsg.getMsgType()) {
|
||||||
|
case ENTITY_CREATED_RPC_MESSAGE:
|
||||||
|
case ENTITY_UPDATED_RPC_MESSAGE:
|
||||||
|
if (existentAlarm == null || existentAlarm.getStatus().isCleared()) {
|
||||||
|
existentAlarm = new Alarm();
|
||||||
|
existentAlarm.setTenantId(tenantId);
|
||||||
|
existentAlarm.setType(alarmUpdateMsg.getName());
|
||||||
|
existentAlarm.setOriginator(originatorId);
|
||||||
|
existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity()));
|
||||||
|
existentAlarm.setStartTs(alarmUpdateMsg.getStartTs());
|
||||||
|
existentAlarm.setClearTs(alarmUpdateMsg.getClearTs());
|
||||||
|
existentAlarm.setPropagate(alarmUpdateMsg.getPropagate());
|
||||||
|
}
|
||||||
|
existentAlarm.setStatus(AlarmStatus.valueOf(alarmUpdateMsg.getStatus()));
|
||||||
|
existentAlarm.setAckTs(alarmUpdateMsg.getAckTs());
|
||||||
|
existentAlarm.setEndTs(alarmUpdateMsg.getEndTs());
|
||||||
|
existentAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()));
|
||||||
|
alarmService.createOrUpdateAlarm(existentAlarm);
|
||||||
|
break;
|
||||||
|
case ALARM_ACK_RPC_MESSAGE:
|
||||||
|
if (existentAlarm != null) {
|
||||||
|
alarmService.ackAlarm(tenantId, existentAlarm.getId(), alarmUpdateMsg.getAckTs());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALARM_CLEAR_RPC_MESSAGE:
|
||||||
|
if (existentAlarm != null) {
|
||||||
|
alarmService.clearAlarm(tenantId, existentAlarm.getId(),
|
||||||
|
JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()), alarmUpdateMsg.getAckTs());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ENTITY_DELETED_RPC_MESSAGE:
|
||||||
|
if (existentAlarm != null) {
|
||||||
|
alarmService.deleteAlarm(tenantId, existentAlarm.getId());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[{}] Failed to process alarm update msg [{}]", tenantId, alarmUpdateMsg, e);
|
||||||
|
return Futures.immediateFailedFuture(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityId getAlarmOriginator(TenantId tenantId, String entityName, EntityType entityType) {
|
||||||
|
switch (entityType) {
|
||||||
|
case DEVICE:
|
||||||
|
return deviceService.findDeviceByTenantIdAndName(tenantId, entityName).getId();
|
||||||
|
case ASSET:
|
||||||
|
return assetService.findAssetByTenantIdAndName(tenantId, entityName).getId();
|
||||||
|
case ENTITY_VIEW:
|
||||||
|
return entityViewService.findEntityViewByTenantIdAndName(tenantId, entityName).getId();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlarmUpdateMsg convertAlarmEventToAlarmMsg(TenantId tenantId, UUID entityId, EdgeEventActionType actionType, JsonNode body) {
|
||||||
|
AlarmId alarmId = new AlarmId(entityId);
|
||||||
|
UpdateMsgType msgType = getUpdateMsgType(actionType);
|
||||||
|
switch (actionType) {
|
||||||
|
case ADDED:
|
||||||
|
case UPDATED:
|
||||||
|
case ALARM_ACK:
|
||||||
|
case ALARM_CLEAR:
|
||||||
|
Alarm alarm = alarmService.findAlarmById(tenantId, alarmId);
|
||||||
|
if (alarm != null) {
|
||||||
|
return alarmMsgConstructor.constructAlarmUpdatedMsg(tenantId, msgType, alarm);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DELETED:
|
||||||
|
Alarm deletedAlarm = JacksonUtil.OBJECT_MAPPER.convertValue(body, Alarm.class);
|
||||||
|
return alarmMsgConstructor.constructAlarmUpdatedMsg(tenantId, msgType, deletedAlarm);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.asset;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -30,6 +30,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.asset;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.customer;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@ -36,6 +36,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.dashboard;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.edge.rpc.processor.device;
|
||||||
|
|
||||||
|
import com.datastax.oss.driver.api.core.uuid.Uuids;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.server.common.data.Device;
|
||||||
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
|
import org.thingsboard.server.common.data.device.data.DeviceData;
|
||||||
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
|
import org.thingsboard.server.common.data.id.OtaPackageId;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||||
|
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
|
||||||
|
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class BaseDeviceProcessor extends BaseEdgeProcessor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected DataDecodingEncodingService dataDecodingEncodingService;
|
||||||
|
|
||||||
|
protected Pair<Boolean, Boolean> saveOrUpdateDevice(TenantId tenantId, DeviceId deviceId, DeviceUpdateMsg deviceUpdateMsg, CustomerId customerId) {
|
||||||
|
boolean created = false;
|
||||||
|
boolean deviceNameUpdated = false;
|
||||||
|
deviceCreationLock.lock();
|
||||||
|
try {
|
||||||
|
Device device = deviceService.findDeviceById(tenantId, deviceId);
|
||||||
|
String deviceName = deviceUpdateMsg.getName();
|
||||||
|
if (device == null) {
|
||||||
|
created = true;
|
||||||
|
device = new Device();
|
||||||
|
device.setTenantId(tenantId);
|
||||||
|
device.setCreatedTime(Uuids.unixTimestamp(deviceId.getId()));
|
||||||
|
Device deviceByName = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);
|
||||||
|
if (deviceByName != null) {
|
||||||
|
deviceName = deviceName + "_" + StringUtils.randomAlphabetic(15);
|
||||||
|
log.warn("Device with name {} already exists. Renaming device name to {}",
|
||||||
|
deviceUpdateMsg.getName(), deviceName);
|
||||||
|
deviceNameUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device.setName(deviceName);
|
||||||
|
device.setType(deviceUpdateMsg.getType());
|
||||||
|
device.setLabel(deviceUpdateMsg.hasLabel() ? deviceUpdateMsg.getLabel() : null);
|
||||||
|
device.setAdditionalInfo(deviceUpdateMsg.hasAdditionalInfo()
|
||||||
|
? JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()) : null);
|
||||||
|
|
||||||
|
UUID deviceProfileUUID = safeGetUUID(deviceUpdateMsg.getDeviceProfileIdMSB(), deviceUpdateMsg.getDeviceProfileIdLSB());
|
||||||
|
device.setDeviceProfileId(deviceProfileUUID != null ? new DeviceProfileId(deviceProfileUUID) : null);
|
||||||
|
|
||||||
|
device.setCustomerId(customerId);
|
||||||
|
|
||||||
|
Optional<DeviceData> deviceDataOpt =
|
||||||
|
dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
|
||||||
|
device.setDeviceData(deviceDataOpt.orElse(null));
|
||||||
|
|
||||||
|
UUID firmwareUUID = safeGetUUID(deviceUpdateMsg.getFirmwareIdMSB(), deviceUpdateMsg.getFirmwareIdLSB());
|
||||||
|
device.setFirmwareId(firmwareUUID != null ? new OtaPackageId(firmwareUUID) : null);
|
||||||
|
|
||||||
|
UUID softwareUUID = safeGetUUID(deviceUpdateMsg.getSoftwareIdMSB(), deviceUpdateMsg.getSoftwareIdLSB());
|
||||||
|
device.setSoftwareId(softwareUUID != null ? new OtaPackageId(softwareUUID) : null);
|
||||||
|
deviceValidator.validate(device, Device::getTenantId);
|
||||||
|
if (created) {
|
||||||
|
device.setId(deviceId);
|
||||||
|
}
|
||||||
|
Device savedDevice = deviceService.saveDevice(device, false);
|
||||||
|
if (created) {
|
||||||
|
DeviceCredentials deviceCredentials = new DeviceCredentials();
|
||||||
|
deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId()));
|
||||||
|
deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
|
||||||
|
deviceCredentials.setCredentialsId(StringUtils.randomAlphanumeric(20));
|
||||||
|
deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
|
||||||
|
}
|
||||||
|
tbClusterService.onDeviceUpdated(savedDevice, created ? null : device, false);
|
||||||
|
} finally {
|
||||||
|
deviceCreationLock.unlock();
|
||||||
|
}
|
||||||
|
return Pair.of(created, deviceNameUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Void> processDeviceCredentialsMsg(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) {
|
||||||
|
log.debug("[{}] Executing processDeviceCredentialsMsg, deviceCredentialsUpdateMsg [{}]", tenantId, deviceCredentialsUpdateMsg);
|
||||||
|
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB()));
|
||||||
|
ListenableFuture<Device> deviceFuture = deviceService.findDeviceByIdAsync(tenantId, deviceId);
|
||||||
|
return Futures.transform(deviceFuture, device -> {
|
||||||
|
if (device != null) {
|
||||||
|
log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",
|
||||||
|
device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue());
|
||||||
|
try {
|
||||||
|
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, device.getId());
|
||||||
|
deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType()));
|
||||||
|
deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId());
|
||||||
|
deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.hasCredentialsValue()
|
||||||
|
? deviceCredentialsUpdateMsg.getCredentialsValue() : null);
|
||||||
|
deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]",
|
||||||
|
device.getName(), deviceCredentialsUpdateMsg, e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("Can't find device by id [{}], deviceCredentialsUpdateMsg [{}]", deviceId, deviceCredentialsUpdateMsg);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, dbCallbackExecutorService);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,16 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.device;
|
||||||
|
|
||||||
import com.datastax.oss.driver.api.core.uuid.Uuids;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.util.Pair;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.common.data.DataConstants;
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
@ -30,24 +29,19 @@ import org.thingsboard.server.common.data.Device;
|
|||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.EdgeUtils;
|
import org.thingsboard.server.common.data.EdgeUtils;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
import org.thingsboard.server.common.data.device.data.DeviceData;
|
|
||||||
import org.thingsboard.server.common.data.edge.Edge;
|
import org.thingsboard.server.common.data.edge.Edge;
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
|
||||||
import org.thingsboard.server.common.data.id.EdgeId;
|
import org.thingsboard.server.common.data.id.EdgeId;
|
||||||
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;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
|
||||||
import org.thingsboard.server.common.data.page.PageLink;
|
|
||||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||||
import org.thingsboard.server.common.data.rpc.RpcError;
|
import org.thingsboard.server.common.data.rpc.RpcError;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
|
|
||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
import org.thingsboard.server.common.msg.TbMsgDataType;
|
import org.thingsboard.server.common.msg.TbMsgDataType;
|
||||||
import org.thingsboard.server.common.msg.TbMsgMetaData;
|
import org.thingsboard.server.common.msg.TbMsgMetaData;
|
||||||
@ -63,68 +57,26 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
|||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.TbQueueCallback;
|
import org.thingsboard.server.queue.TbQueueCallback;
|
||||||
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
||||||
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg;
|
import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@TbCoreComponent
|
@TbCoreComponent
|
||||||
public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
public class DeviceEdgeProcessor extends BaseDeviceProcessor {
|
||||||
|
|
||||||
@Autowired
|
public ListenableFuture<Void> processDeviceMsgFromEdge(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
|
||||||
private DataDecodingEncodingService dataDecodingEncodingService;
|
log.trace("[{}] executing processDeviceMsgFromEdge [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
|
||||||
|
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
|
||||||
private static final ReentrantLock deviceCreationLock = new ReentrantLock();
|
try {
|
||||||
|
|
||||||
public ListenableFuture<Void> processDeviceFromEdge(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
|
|
||||||
log.trace("[{}] processDeviceFromEdge [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
|
|
||||||
switch (deviceUpdateMsg.getMsgType()) {
|
switch (deviceUpdateMsg.getMsgType()) {
|
||||||
case ENTITY_CREATED_RPC_MESSAGE:
|
case ENTITY_CREATED_RPC_MESSAGE:
|
||||||
String deviceName = deviceUpdateMsg.getName();
|
|
||||||
Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);
|
|
||||||
if (device != null) {
|
|
||||||
boolean deviceAlreadyExistsForThisEdge = isDeviceAlreadyExistsOnCloudForThisEdge(tenantId, edge, device);
|
|
||||||
if (deviceAlreadyExistsForThisEdge) {
|
|
||||||
log.info("[{}] Device with name '{}' already exists on the cloud, and related to this edge [{}]. " +
|
|
||||||
"deviceUpdateMsg [{}], Updating device", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
|
|
||||||
return updateDevice(tenantId, edge, deviceUpdateMsg);
|
|
||||||
} else {
|
|
||||||
log.info("[{}] Device with name '{}' already exists on the cloud, but not related to this edge [{}]. deviceUpdateMsg [{}]." +
|
|
||||||
"Creating a new device with random prefix and relate to this edge", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
|
|
||||||
String newDeviceName = deviceUpdateMsg.getName() + "_" + StringUtils.randomAlphabetic(15);
|
|
||||||
Device newDevice;
|
|
||||||
try {
|
|
||||||
newDevice = createDevice(tenantId, edge, deviceUpdateMsg, newDeviceName);
|
|
||||||
} catch (DataValidationException e) {
|
|
||||||
log.error("[{}] Device update msg can't be processed due to data validation [{}]", tenantId, deviceUpdateMsg, e);
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
ObjectNode body = JacksonUtil.OBJECT_MAPPER.createObjectNode();
|
|
||||||
body.put("conflictName", deviceName);
|
|
||||||
ListenableFuture<Void> input = saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, newDevice.getId(), body);
|
|
||||||
return Futures.transformAsync(input, unused ->
|
|
||||||
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, newDevice.getId(), null),
|
|
||||||
dbCallbackExecutorService);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.info("[{}] Creating new device on the cloud [{}]", tenantId, deviceUpdateMsg);
|
|
||||||
try {
|
|
||||||
device = createDevice(tenantId, edge, deviceUpdateMsg, deviceUpdateMsg.getName());
|
|
||||||
} catch (DataValidationException e) {
|
|
||||||
log.error("[{}] Device update msg can't be processed due to data validation [{}]", tenantId, deviceUpdateMsg, e);
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, device.getId(), null);
|
|
||||||
}
|
|
||||||
case ENTITY_UPDATED_RPC_MESSAGE:
|
case ENTITY_UPDATED_RPC_MESSAGE:
|
||||||
return updateDevice(tenantId, edge, deviceUpdateMsg);
|
saveOrUpdateDevice(tenantId, deviceId, deviceUpdateMsg, edge);
|
||||||
|
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
|
||||||
case ENTITY_DELETED_RPC_MESSAGE:
|
case ENTITY_DELETED_RPC_MESSAGE:
|
||||||
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
|
|
||||||
Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId);
|
Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId);
|
||||||
if (deviceToDelete != null) {
|
if (deviceToDelete != null) {
|
||||||
deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId());
|
deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId());
|
||||||
@ -134,144 +86,28 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
default:
|
default:
|
||||||
return handleUnsupportedMsgType(deviceUpdateMsg.getMsgType());
|
return handleUnsupportedMsgType(deviceUpdateMsg.getMsgType());
|
||||||
}
|
}
|
||||||
}
|
} catch (DataValidationException e) {
|
||||||
|
if (e.getMessage().contains("Can't create more then")) {
|
||||||
private boolean isDeviceAlreadyExistsOnCloudForThisEdge(TenantId tenantId, Edge edge, Device device) {
|
log.warn("[{}] Number of allowed devices violated {}", tenantId, deviceUpdateMsg, e);
|
||||||
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
|
return Futures.immediateFuture(null);
|
||||||
PageData<EdgeId> pageData;
|
|
||||||
do {
|
|
||||||
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, device.getId(), pageLink);
|
|
||||||
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
|
|
||||||
if (pageData.getData().contains(edge.getId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (pageData.hasNext()) {
|
|
||||||
pageLink = pageLink.nextPageLink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (pageData != null && pageData.hasNext());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processDeviceCredentialsFromEdge(TenantId tenantId, DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg) {
|
|
||||||
log.debug("[{}] Executing processDeviceCredentialsFromEdge, deviceCredentialsUpdateMsg [{}]", tenantId, deviceCredentialsUpdateMsg);
|
|
||||||
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsUpdateMsg.getDeviceIdMSB(), deviceCredentialsUpdateMsg.getDeviceIdLSB()));
|
|
||||||
ListenableFuture<Device> deviceFuture = deviceService.findDeviceByIdAsync(tenantId, deviceId);
|
|
||||||
return Futures.transform(deviceFuture, device -> {
|
|
||||||
if (device != null) {
|
|
||||||
log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",
|
|
||||||
device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue());
|
|
||||||
try {
|
|
||||||
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, device.getId());
|
|
||||||
deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType()));
|
|
||||||
deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId());
|
|
||||||
if (deviceCredentialsUpdateMsg.hasCredentialsValue()) {
|
|
||||||
deviceCredentials.setCredentialsValue(deviceCredentialsUpdateMsg.getCredentialsValue());
|
|
||||||
}
|
|
||||||
deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]", device.getName(), deviceCredentialsUpdateMsg, e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}, dbCallbackExecutorService);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private ListenableFuture<Void> updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
|
|
||||||
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
|
|
||||||
Device device = deviceService.findDeviceById(tenantId, deviceId);
|
|
||||||
if (device != null) {
|
|
||||||
device.setName(deviceUpdateMsg.getName());
|
|
||||||
device.setType(deviceUpdateMsg.getType());
|
|
||||||
if (deviceUpdateMsg.hasLabel()) {
|
|
||||||
device.setLabel(deviceUpdateMsg.getLabel());
|
|
||||||
}
|
|
||||||
if (deviceUpdateMsg.hasAdditionalInfo()) {
|
|
||||||
device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
|
|
||||||
}
|
|
||||||
if (deviceUpdateMsg.hasDeviceProfileIdMSB() && deviceUpdateMsg.hasDeviceProfileIdLSB()) {
|
|
||||||
DeviceProfileId deviceProfileId = new DeviceProfileId(
|
|
||||||
new UUID(deviceUpdateMsg.getDeviceProfileIdMSB(),
|
|
||||||
deviceUpdateMsg.getDeviceProfileIdLSB()));
|
|
||||||
device.setDeviceProfileId(deviceProfileId);
|
|
||||||
}
|
|
||||||
device.setCustomerId(getCustomerId(deviceUpdateMsg));
|
|
||||||
Optional<DeviceData> deviceDataOpt =
|
|
||||||
dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
|
|
||||||
deviceDataOpt.ifPresent(device::setDeviceData);
|
|
||||||
Device savedDevice = deviceService.saveDevice(device);
|
|
||||||
tbClusterService.onDeviceUpdated(savedDevice, device, false);
|
|
||||||
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
|
|
||||||
} else {
|
} else {
|
||||||
String errMsg = String.format("[%s] can't find device [%s], edge [%s]", tenantId, deviceUpdateMsg, edge.getId());
|
return Futures.immediateFailedFuture(e);
|
||||||
log.warn(errMsg);
|
}
|
||||||
return Futures.immediateFailedFuture(new RuntimeException(errMsg));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Device createDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg, String deviceName) {
|
private void saveOrUpdateDevice(TenantId tenantId, DeviceId deviceId, DeviceUpdateMsg deviceUpdateMsg, Edge edge) {
|
||||||
Device device;
|
CustomerId customerId = safeGetCustomerId(deviceUpdateMsg.getCustomerIdMSB(), deviceUpdateMsg.getCustomerIdLSB());
|
||||||
deviceCreationLock.lock();
|
Pair<Boolean, Boolean> resultPair = super.saveOrUpdateDevice(tenantId, deviceId, deviceUpdateMsg, customerId);
|
||||||
try {
|
Boolean created = resultPair.getFirst();
|
||||||
log.debug("[{}] Creating device entity [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
|
|
||||||
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
|
|
||||||
device = deviceService.findDeviceById(tenantId, deviceId);
|
|
||||||
boolean created = false;
|
|
||||||
if (device == null) {
|
|
||||||
device = new Device();
|
|
||||||
device.setTenantId(tenantId);
|
|
||||||
device.setCreatedTime(Uuids.unixTimestamp(deviceId.getId()));
|
|
||||||
created = true;
|
|
||||||
}
|
|
||||||
device.setName(deviceName);
|
|
||||||
device.setType(deviceUpdateMsg.getType());
|
|
||||||
if (deviceUpdateMsg.hasLabel()) {
|
|
||||||
device.setLabel(deviceUpdateMsg.getLabel());
|
|
||||||
}
|
|
||||||
if (deviceUpdateMsg.hasAdditionalInfo()) {
|
|
||||||
device.setAdditionalInfo(JacksonUtil.toJsonNode(deviceUpdateMsg.getAdditionalInfo()));
|
|
||||||
}
|
|
||||||
if (deviceUpdateMsg.hasDeviceProfileIdMSB() && deviceUpdateMsg.hasDeviceProfileIdLSB()) {
|
|
||||||
DeviceProfileId deviceProfileId = new DeviceProfileId(
|
|
||||||
new UUID(deviceUpdateMsg.getDeviceProfileIdMSB(),
|
|
||||||
deviceUpdateMsg.getDeviceProfileIdLSB()));
|
|
||||||
device.setDeviceProfileId(deviceProfileId);
|
|
||||||
}
|
|
||||||
device.setCustomerId(getCustomerId(deviceUpdateMsg));
|
|
||||||
Optional<DeviceData> deviceDataOpt =
|
|
||||||
dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
|
|
||||||
if (deviceDataOpt.isPresent()) {
|
|
||||||
device.setDeviceData(deviceDataOpt.get());
|
|
||||||
}
|
|
||||||
deviceValidator.validate(device, Device::getTenantId);
|
|
||||||
if (created) {
|
if (created) {
|
||||||
device.setId(deviceId);
|
createRelationFromEdge(tenantId, edge.getId(), deviceId);
|
||||||
|
pushDeviceCreatedEventToRuleEngine(tenantId, edge, deviceId);
|
||||||
|
deviceService.assignDeviceToEdge(tenantId, deviceId, edge.getId());
|
||||||
}
|
}
|
||||||
Device savedDevice = deviceService.saveDevice(device, false);
|
Boolean deviceNameUpdated = resultPair.getSecond();
|
||||||
tbClusterService.onDeviceUpdated(savedDevice, created ? null : device, false);
|
if (deviceNameUpdated) {
|
||||||
if (created) {
|
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.UPDATED, deviceId, null);
|
||||||
DeviceCredentials deviceCredentials = new DeviceCredentials();
|
|
||||||
deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId()));
|
|
||||||
deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
|
|
||||||
deviceCredentials.setCredentialsId(StringUtils.randomAlphanumeric(20));
|
|
||||||
deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
|
|
||||||
}
|
|
||||||
createRelationFromEdge(tenantId, edge.getId(), device.getId());
|
|
||||||
pushDeviceCreatedEventToRuleEngine(tenantId, edge, device);
|
|
||||||
deviceService.assignDeviceToEdge(edge.getTenantId(), device.getId(), edge.getId());
|
|
||||||
} finally {
|
|
||||||
deviceCreationLock.unlock();
|
|
||||||
}
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CustomerId getCustomerId(DeviceUpdateMsg deviceUpdateMsg) {
|
|
||||||
if (deviceUpdateMsg.hasCustomerIdMSB() && deviceUpdateMsg.hasCustomerIdLSB()) {
|
|
||||||
return new CustomerId(new UUID(deviceUpdateMsg.getCustomerIdMSB(), deviceUpdateMsg.getCustomerIdLSB()));
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,9 +120,9 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
relationService.saveRelation(tenantId, relation);
|
relationService.saveRelation(tenantId, relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, Device device) {
|
private void pushDeviceCreatedEventToRuleEngine(TenantId tenantId, Edge edge, DeviceId deviceId) {
|
||||||
try {
|
try {
|
||||||
DeviceId deviceId = device.getId();
|
Device device = deviceService.findDeviceById(tenantId, deviceId);
|
||||||
ObjectNode entityNode = JacksonUtil.OBJECT_MAPPER.valueToTree(device);
|
ObjectNode entityNode = JacksonUtil.OBJECT_MAPPER.valueToTree(device);
|
||||||
TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, device.getCustomerId(),
|
TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, device.getCustomerId(),
|
||||||
getActionTbMsgMetaData(edge, device.getCustomerId()), TbMsgDataType.JSON, JacksonUtil.OBJECT_MAPPER.writeValueAsString(entityNode));
|
getActionTbMsgMetaData(edge, device.getCustomerId()), TbMsgDataType.JSON, JacksonUtil.OBJECT_MAPPER.writeValueAsString(entityNode));
|
||||||
@ -302,7 +138,7 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (JsonProcessingException | IllegalArgumentException e) {
|
} catch (JsonProcessingException | IllegalArgumentException e) {
|
||||||
log.warn("[{}] Failed to push device action to rule engine: {}", device.getId(), DataConstants.ENTITY_CREATED, e);
|
log.warn("[{}] Failed to push device action to rule engine: {}", deviceId, DataConstants.ENTITY_CREATED, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +251,7 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
if (device != null) {
|
if (device != null) {
|
||||||
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
|
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
|
||||||
DeviceUpdateMsg deviceUpdateMsg =
|
DeviceUpdateMsg deviceUpdateMsg =
|
||||||
deviceMsgConstructor.constructDeviceUpdatedMsg(msgType, device, null);
|
deviceMsgConstructor.constructDeviceUpdatedMsg(msgType, device);
|
||||||
DownlinkMsg.Builder builder = DownlinkMsg.newBuilder()
|
DownlinkMsg.Builder builder = DownlinkMsg.newBuilder()
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
||||||
.addDeviceUpdateMsg(deviceUpdateMsg);
|
.addDeviceUpdateMsg(deviceUpdateMsg);
|
||||||
@ -450,8 +286,6 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
return convertRpcCallEventToDownlink(edgeEvent);
|
return convertRpcCallEventToDownlink(edgeEvent);
|
||||||
case CREDENTIALS_REQUEST:
|
case CREDENTIALS_REQUEST:
|
||||||
return convertCredentialsRequestEventToDownlink(edgeEvent);
|
return convertCredentialsRequestEventToDownlink(edgeEvent);
|
||||||
case ENTITY_MERGE_REQUEST:
|
|
||||||
return convertEntityMergeRequestEventToDownlink(edgeEvent);
|
|
||||||
}
|
}
|
||||||
return downlinkMsg;
|
return downlinkMsg;
|
||||||
}
|
}
|
||||||
@ -475,21 +309,6 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownlinkMsg convertEntityMergeRequestEventToDownlink(EdgeEvent edgeEvent) {
|
|
||||||
DeviceId deviceId = new DeviceId(edgeEvent.getEntityId());
|
|
||||||
Device device = deviceService.findDeviceById(edgeEvent.getTenantId(), deviceId);
|
|
||||||
String conflictName = null;
|
|
||||||
if(edgeEvent.getBody() != null) {
|
|
||||||
conflictName = edgeEvent.getBody().get("conflictName").asText();
|
|
||||||
}
|
|
||||||
DeviceUpdateMsg deviceUpdateMsg = deviceMsgConstructor
|
|
||||||
.constructDeviceUpdatedMsg(UpdateMsgType.ENTITY_MERGE_RPC_MESSAGE, device, conflictName);
|
|
||||||
return DownlinkMsg.newBuilder()
|
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
|
||||||
.addDeviceUpdateMsg(deviceUpdateMsg)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processDeviceNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
|
public ListenableFuture<Void> processDeviceNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
|
||||||
return processEntityNotification(tenantId, edgeNotificationMsg);
|
return processEntityNotification(tenantId, edgeNotificationMsg);
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.device;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.edge;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@ -35,6 +35,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
|
import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.entityview;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.ota;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.queue;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,21 +13,13 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.relation;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.common.data.EdgeUtils;
|
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
|
||||||
import org.thingsboard.server.common.data.id.AssetId;
|
import org.thingsboard.server.common.data.id.AssetId;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
import org.thingsboard.server.common.data.id.DashboardId;
|
import org.thingsboard.server.common.data.id.DashboardId;
|
||||||
@ -40,24 +32,15 @@ import org.thingsboard.server.common.data.id.TenantId;
|
|||||||
import org.thingsboard.server.common.data.id.UserId;
|
import org.thingsboard.server.common.data.id.UserId;
|
||||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|
||||||
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@TbCoreComponent
|
public abstract class BaseRelationProcessor extends BaseEdgeProcessor {
|
||||||
public class RelationEdgeProcessor extends BaseEdgeProcessor {
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processRelationFromEdge(TenantId tenantId, RelationUpdateMsg relationUpdateMsg) {
|
public ListenableFuture<Void> processRelationMsg(TenantId tenantId, RelationUpdateMsg relationUpdateMsg) {
|
||||||
log.trace("[{}] processRelationFromEdge [{}]", tenantId, relationUpdateMsg);
|
log.trace("[{}] processRelationFromEdge [{}]", tenantId, relationUpdateMsg);
|
||||||
try {
|
try {
|
||||||
EntityRelation entityRelation = new EntityRelation();
|
EntityRelation entityRelation = new EntityRelation();
|
||||||
@ -71,10 +54,9 @@ public class RelationEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
entityRelation.setTo(toId);
|
entityRelation.setTo(toId);
|
||||||
|
|
||||||
entityRelation.setType(relationUpdateMsg.getType());
|
entityRelation.setType(relationUpdateMsg.getType());
|
||||||
if (relationUpdateMsg.hasTypeGroup()) {
|
entityRelation.setTypeGroup(relationUpdateMsg.hasTypeGroup()
|
||||||
entityRelation.setTypeGroup(RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup()));
|
? RelationTypeGroup.valueOf(relationUpdateMsg.getTypeGroup()) : RelationTypeGroup.COMMON);
|
||||||
}
|
entityRelation.setAdditionalInfo(JacksonUtil.toJsonNode(relationUpdateMsg.getAdditionalInfo()));
|
||||||
entityRelation.setAdditionalInfo(JacksonUtil.OBJECT_MAPPER.readTree(relationUpdateMsg.getAdditionalInfo()));
|
|
||||||
switch (relationUpdateMsg.getMsgType()) {
|
switch (relationUpdateMsg.getMsgType()) {
|
||||||
case ENTITY_CREATED_RPC_MESSAGE:
|
case ENTITY_CREATED_RPC_MESSAGE:
|
||||||
case ENTITY_UPDATED_RPC_MESSAGE:
|
case ENTITY_UPDATED_RPC_MESSAGE:
|
||||||
@ -94,12 +76,12 @@ public class RelationEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
return handleUnsupportedMsgType(relationUpdateMsg.getMsgType());
|
return handleUnsupportedMsgType(relationUpdateMsg.getMsgType());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to process relation update msg [{}]", relationUpdateMsg, e);
|
log.error("[{}] Failed to process relation update msg [{}]", tenantId, relationUpdateMsg, e);
|
||||||
return Futures.immediateFailedFuture(new RuntimeException("Failed to process relation update msg", e));
|
return Futures.immediateFailedFuture(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEntityExists(TenantId tenantId, EntityId entityId) throws ThingsboardException {
|
private boolean isEntityExists(TenantId tenantId, EntityId entityId) {
|
||||||
switch (entityId.getEntityType()) {
|
switch (entityId.getEntityType()) {
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
return deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())) != null;
|
return deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())) != null;
|
||||||
@ -113,43 +95,10 @@ public class RelationEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
return userService.findUserById(tenantId, new UserId(entityId.getId())) != null;
|
return userService.findUserById(tenantId, new UserId(entityId.getId())) != null;
|
||||||
case DASHBOARD:
|
case DASHBOARD:
|
||||||
return dashboardService.findDashboardById(tenantId, new DashboardId(entityId.getId())) != null;
|
return dashboardService.findDashboardById(tenantId, new DashboardId(entityId.getId())) != null;
|
||||||
|
case EDGE:
|
||||||
|
return edgeService.findEdgeById(tenantId, new EdgeId(entityId.getId())) != null;
|
||||||
default:
|
default:
|
||||||
throw new ThingsboardException("Unsupported entity type " + entityId.getEntityType(), ThingsboardErrorCode.INVALID_ARGUMENTS);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownlinkMsg convertRelationEventToDownlink(EdgeEvent edgeEvent) {
|
|
||||||
EntityRelation entityRelation = JacksonUtil.OBJECT_MAPPER.convertValue(edgeEvent.getBody(), EntityRelation.class);
|
|
||||||
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
|
|
||||||
RelationUpdateMsg relationUpdateMsg = relationMsgConstructor.constructRelationUpdatedMsg(msgType, entityRelation);
|
|
||||||
return DownlinkMsg.newBuilder()
|
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
|
||||||
.addRelationUpdateMsg(relationUpdateMsg)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListenableFuture<Void> processRelationNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
|
|
||||||
EntityRelation relation = JacksonUtil.OBJECT_MAPPER.readValue(edgeNotificationMsg.getBody(), EntityRelation.class);
|
|
||||||
if (relation.getFrom().getEntityType().equals(EntityType.EDGE) ||
|
|
||||||
relation.getTo().getEntityType().equals(EntityType.EDGE)) {
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<EdgeId> uniqueEdgeIds = new HashSet<>();
|
|
||||||
uniqueEdgeIds.addAll(edgeService.findAllRelatedEdgeIds(tenantId, relation.getTo()));
|
|
||||||
uniqueEdgeIds.addAll(edgeService.findAllRelatedEdgeIds(tenantId, relation.getFrom()));
|
|
||||||
if (uniqueEdgeIds.isEmpty()) {
|
|
||||||
return Futures.immediateFuture(null);
|
|
||||||
}
|
|
||||||
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
|
||||||
for (EdgeId edgeId : uniqueEdgeIds) {
|
|
||||||
futures.add(saveEdgeEvent(tenantId,
|
|
||||||
edgeId,
|
|
||||||
EdgeEventType.RELATION,
|
|
||||||
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
|
|
||||||
null,
|
|
||||||
JacksonUtil.OBJECT_MAPPER.valueToTree(relation)));
|
|
||||||
}
|
|
||||||
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.edge.rpc.processor.relation;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.server.common.data.EdgeUtils;
|
||||||
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEventType;
|
||||||
|
import org.thingsboard.server.common.data.id.EdgeId;
|
||||||
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@TbCoreComponent
|
||||||
|
public class RelationEdgeProcessor extends BaseRelationProcessor {
|
||||||
|
|
||||||
|
public DownlinkMsg convertRelationEventToDownlink(EdgeEvent edgeEvent) {
|
||||||
|
EntityRelation entityRelation = JacksonUtil.OBJECT_MAPPER.convertValue(edgeEvent.getBody(), EntityRelation.class);
|
||||||
|
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
|
||||||
|
RelationUpdateMsg relationUpdateMsg = relationMsgConstructor.constructRelationUpdatedMsg(msgType, entityRelation);
|
||||||
|
return DownlinkMsg.newBuilder()
|
||||||
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
||||||
|
.addRelationUpdateMsg(relationUpdateMsg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<Void> processRelationNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
|
||||||
|
EntityRelation relation = JacksonUtil.OBJECT_MAPPER.readValue(edgeNotificationMsg.getBody(), EntityRelation.class);
|
||||||
|
if (relation.getFrom().getEntityType().equals(EntityType.EDGE) ||
|
||||||
|
relation.getTo().getEntityType().equals(EntityType.EDGE)) {
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<EdgeId> uniqueEdgeIds = new HashSet<>();
|
||||||
|
uniqueEdgeIds.addAll(edgeService.findAllRelatedEdgeIds(tenantId, relation.getTo()));
|
||||||
|
uniqueEdgeIds.addAll(edgeService.findAllRelatedEdgeIds(tenantId, relation.getFrom()));
|
||||||
|
if (uniqueEdgeIds.isEmpty()) {
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
List<ListenableFuture<Void>> futures = new ArrayList<>();
|
||||||
|
for (EdgeId edgeId : uniqueEdgeIds) {
|
||||||
|
futures.add(saveEdgeEvent(tenantId,
|
||||||
|
edgeId,
|
||||||
|
EdgeEventType.RELATION,
|
||||||
|
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
|
||||||
|
null,
|
||||||
|
JacksonUtil.OBJECT_MAPPER.valueToTree(relation)));
|
||||||
|
}
|
||||||
|
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.rule;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -31,6 +31,7 @@ import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY;
|
import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.settings;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.edge.EdgeEvent;
|
|||||||
import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,9 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.telemetry;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
@ -26,19 +27,16 @@ import com.google.gson.JsonParser;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
|
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
|
||||||
import org.thingsboard.server.common.data.DataConstants;
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.EdgeUtils;
|
|
||||||
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.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.asset.AssetProfile;
|
import org.thingsboard.server.common.data.asset.AssetProfile;
|
||||||
import org.thingsboard.server.common.data.edge.Edge;
|
import org.thingsboard.server.common.data.edge.Edge;
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
|
||||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
|
||||||
import org.thingsboard.server.common.data.id.AssetId;
|
import org.thingsboard.server.common.data.id.AssetId;
|
||||||
import org.thingsboard.server.common.data.id.CustomerId;
|
import org.thingsboard.server.common.data.id.CustomerId;
|
||||||
@ -60,24 +58,22 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter;
|
|||||||
import org.thingsboard.server.common.transport.util.JsonUtils;
|
import org.thingsboard.server.common.transport.util.JsonUtils;
|
||||||
import org.thingsboard.server.dao.model.ModelConstants;
|
import org.thingsboard.server.dao.model.ModelConstants;
|
||||||
import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg;
|
import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
|
||||||
import org.thingsboard.server.gen.edge.v1.EntityDataProto;
|
import org.thingsboard.server.gen.edge.v1.EntityDataProto;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.TbQueueCallback;
|
import org.thingsboard.server.queue.TbQueueCallback;
|
||||||
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
||||||
import org.thingsboard.server.queue.TbQueueProducer;
|
import org.thingsboard.server.queue.TbQueueProducer;
|
||||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@TbCoreComponent
|
public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
|
||||||
public class TelemetryEdgeProcessor extends BaseEdgeProcessor {
|
|
||||||
|
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson = new Gson();
|
||||||
|
|
||||||
@ -88,15 +84,17 @@ public class TelemetryEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer();
|
tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ListenableFuture<Void>> processTelemetryFromEdge(TenantId tenantId, EntityDataProto entityData) {
|
abstract protected String getMsgSourceKey();
|
||||||
log.trace("[{}] processTelemetryFromEdge [{}]", tenantId, entityData);
|
|
||||||
|
public List<ListenableFuture<Void>> processTelemetryMsg(TenantId tenantId, EntityDataProto entityData) {
|
||||||
|
log.trace("[{}] processTelemetryMsg [{}]", tenantId, entityData);
|
||||||
List<ListenableFuture<Void>> result = new ArrayList<>();
|
List<ListenableFuture<Void>> result = new ArrayList<>();
|
||||||
EntityId entityId = constructEntityId(entityData.getEntityType(), entityData.getEntityIdMSB(), entityData.getEntityIdLSB());
|
EntityId entityId = constructEntityId(entityData.getEntityType(), entityData.getEntityIdMSB(), entityData.getEntityIdLSB());
|
||||||
if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdatedMsg()) && entityId != null) {
|
if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdatedMsg()) && entityId != null) {
|
||||||
Pair<TbMsgMetaData, CustomerId> pair = getBaseMsgMetadataAndCustomerId(tenantId, entityId);
|
Pair<TbMsgMetaData, CustomerId> pair = getBaseMsgMetadataAndCustomerId(tenantId, entityId);
|
||||||
TbMsgMetaData metaData = pair.getKey();
|
TbMsgMetaData metaData = pair.getKey();
|
||||||
CustomerId customerId = pair.getValue();
|
CustomerId customerId = pair.getValue();
|
||||||
metaData.putValue(DataConstants.MSG_SOURCE_KEY, DataConstants.EDGE_MSG_SOURCE);
|
metaData.putValue(DataConstants.MSG_SOURCE_KEY, getMsgSourceKey());
|
||||||
if (entityData.hasPostAttributesMsg()) {
|
if (entityData.hasPostAttributesMsg()) {
|
||||||
result.add(processPostAttributes(tenantId, customerId, entityId, entityData.getPostAttributesMsg(), metaData));
|
result.add(processPostAttributes(tenantId, customerId, entityId, entityData.getPostAttributesMsg(), metaData));
|
||||||
}
|
}
|
||||||
@ -283,11 +281,11 @@ public class TelemetryEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
String entityType) {
|
String entityType) {
|
||||||
SettableFuture<Void> futureToSet = SettableFuture.create();
|
SettableFuture<Void> futureToSet = SettableFuture.create();
|
||||||
String scope = attributeDeleteMsg.getScope();
|
String scope = attributeDeleteMsg.getScope();
|
||||||
List<String> attributeNames = attributeDeleteMsg.getAttributeNamesList();
|
List<String> attributeKeys = attributeDeleteMsg.getAttributeNamesList();
|
||||||
attributesService.removeAll(tenantId, entityId, scope, attributeNames);
|
attributesService.removeAll(tenantId, entityId, scope, attributeKeys);
|
||||||
if (EntityType.DEVICE.name().equals(entityType)) {
|
if (EntityType.DEVICE.name().equals(entityType)) {
|
||||||
tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(
|
tbClusterService.pushMsgToCore(DeviceAttributesEventNotificationMsg.onDelete(
|
||||||
tenantId, (DeviceId) entityId, scope, attributeNames), new TbQueueCallback() {
|
tenantId, (DeviceId) entityId, scope, attributeKeys), new TbQueueCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(TbQueueMsgMetadata metadata) {
|
public void onSuccess(TbQueueMsgMetadata metadata) {
|
||||||
futureToSet.set(null);
|
futureToSet.set(null);
|
||||||
@ -303,47 +301,42 @@ public class TelemetryEdgeProcessor extends BaseEdgeProcessor {
|
|||||||
return futureToSet;
|
return futureToSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownlinkMsg convertTelemetryEventToDownlink(EdgeEvent edgeEvent) throws JsonProcessingException {
|
public EntityDataProto convertTelemetryEventToEntityDataProto(EntityType entityType,
|
||||||
|
UUID entityUUID,
|
||||||
|
EdgeEventActionType actionType,
|
||||||
|
JsonNode body) throws JsonProcessingException {
|
||||||
EntityId entityId;
|
EntityId entityId;
|
||||||
switch (edgeEvent.getType()) {
|
switch (entityType) {
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
entityId = new DeviceId(edgeEvent.getEntityId());
|
entityId = new DeviceId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case ASSET:
|
case ASSET:
|
||||||
entityId = new AssetId(edgeEvent.getEntityId());
|
entityId = new AssetId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case ENTITY_VIEW:
|
case ENTITY_VIEW:
|
||||||
entityId = new EntityViewId(edgeEvent.getEntityId());
|
entityId = new EntityViewId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case DASHBOARD:
|
case DASHBOARD:
|
||||||
entityId = new DashboardId(edgeEvent.getEntityId());
|
entityId = new DashboardId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case TENANT:
|
case TENANT:
|
||||||
entityId = TenantId.fromUUID(edgeEvent.getEntityId());
|
entityId = TenantId.fromUUID(entityUUID);
|
||||||
break;
|
break;
|
||||||
case CUSTOMER:
|
case CUSTOMER:
|
||||||
entityId = new CustomerId(edgeEvent.getEntityId());
|
entityId = new CustomerId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case USER:
|
case USER:
|
||||||
entityId = new UserId(edgeEvent.getEntityId());
|
entityId = new UserId(entityUUID);
|
||||||
break;
|
break;
|
||||||
case EDGE:
|
case EDGE:
|
||||||
entityId = new EdgeId(edgeEvent.getEntityId());
|
entityId = new EdgeId(entityUUID);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.warn("Unsupported edge event type [{}]", edgeEvent);
|
log.warn("Unsupported edge event type [{}]", entityType);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return constructEntityDataProtoMsg(entityId, edgeEvent.getAction(),
|
JsonElement entityData = JsonParser.parseString(JacksonUtil.OBJECT_MAPPER.writeValueAsString(body));
|
||||||
JsonParser.parseString(JacksonUtil.OBJECT_MAPPER.writeValueAsString(edgeEvent.getBody())));
|
return entityDataMsgConstructor.constructEntityDataMsg(entityId, actionType, entityData);
|
||||||
}
|
|
||||||
|
|
||||||
private DownlinkMsg constructEntityDataProtoMsg(EntityId entityId, EdgeEventActionType actionType, JsonElement entityData) {
|
|
||||||
EntityDataProto entityDataProto = entityDataMsgConstructor.constructEntityDataMsg(entityId, actionType, entityData);
|
|
||||||
return DownlinkMsg.newBuilder()
|
|
||||||
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
|
||||||
.addEntityData(entityDataProto)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.edge.rpc.processor.telemetry;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.thingsboard.server.common.data.DataConstants;
|
||||||
|
import org.thingsboard.server.common.data.EdgeUtils;
|
||||||
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
|
import org.thingsboard.server.common.data.edge.EdgeEvent;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
|
||||||
|
import org.thingsboard.server.gen.edge.v1.EntityDataProto;
|
||||||
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@TbCoreComponent
|
||||||
|
public class TelemetryEdgeProcessor extends BaseTelemetryProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getMsgSourceKey() {
|
||||||
|
return DataConstants.EDGE_MSG_SOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownlinkMsg convertTelemetryEventToDownlink(EdgeEvent edgeEvent) throws JsonProcessingException {
|
||||||
|
EntityType entityType = EntityType.valueOf(edgeEvent.getType().name());
|
||||||
|
EntityDataProto entityDataProto = convertTelemetryEventToEntityDataProto(entityType, edgeEvent.getEntityId(),
|
||||||
|
edgeEvent.getAction(), edgeEvent.getBody());
|
||||||
|
return DownlinkMsg.newBuilder()
|
||||||
|
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
|
||||||
|
.addEntityData(entityDataProto)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.user;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -29,6 +29,7 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.widget;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
|||||||
import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.edge.rpc.processor;
|
package org.thingsboard.server.service.edge.rpc.processor.widget;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -28,6 +28,7 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
|
|||||||
import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
|
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -17,6 +17,10 @@ package org.thingsboard.server.controller;
|
|||||||
|
|
||||||
import com.datastax.oss.driver.api.core.uuid.Uuids;
|
import com.datastax.oss.driver.api.core.uuid.Uuids;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -28,6 +32,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.TestPropertySource;
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
import org.thingsboard.common.util.ThingsBoardExecutors;
|
||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.EntitySubtype;
|
import org.thingsboard.server.common.data.EntitySubtype;
|
||||||
@ -58,13 +63,10 @@ import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
|
|||||||
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
|
||||||
import org.thingsboard.server.gen.edge.v1.UserUpdateMsg;
|
import org.thingsboard.server.gen.edge.v1.UserUpdateMsg;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
@ -86,6 +88,10 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
private TenantId tenantId;
|
private TenantId tenantId;
|
||||||
private User tenantAdmin;
|
private User tenantAdmin;
|
||||||
|
|
||||||
|
ListeningExecutorService executor;
|
||||||
|
|
||||||
|
List<ListenableFuture<Edge>> futures;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EdgeDao edgeDao;
|
private EdgeDao edgeDao;
|
||||||
|
|
||||||
@ -99,6 +105,8 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeTest() throws Exception {
|
public void beforeTest() throws Exception {
|
||||||
|
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
|
||||||
|
|
||||||
loginSysAdmin();
|
loginSysAdmin();
|
||||||
|
|
||||||
Tenant tenant = new Tenant();
|
Tenant tenant = new Tenant();
|
||||||
@ -119,6 +127,8 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
|
|
||||||
@After
|
@After
|
||||||
public void afterTest() throws Exception {
|
public void afterTest() throws Exception {
|
||||||
|
executor.shutdownNow();
|
||||||
|
|
||||||
loginSysAdmin();
|
loginSysAdmin();
|
||||||
|
|
||||||
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
|
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
|
||||||
@ -385,11 +395,14 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindTenantEdges() throws Exception {
|
public void testFindTenantEdges() throws Exception {
|
||||||
List<Edge> edges = new ArrayList<>();
|
int cntEntity = 178;
|
||||||
for (int i = 0; i < 178; i++) {
|
futures = new ArrayList<>(cntEntity);
|
||||||
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
Edge edge = constructEdge("Edge" + i, "default");
|
Edge edge = constructEdge("Edge" + i, "default");
|
||||||
edges.add(doPost("/api/edge", edge, Edge.class));
|
futures.add(executor.submit(() ->
|
||||||
|
doPost("/api/edge", edge, Edge.class)));
|
||||||
}
|
}
|
||||||
|
List<Edge> edges = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
List<Edge> loadedEdges = new ArrayList<>();
|
List<Edge> loadedEdges = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(23);
|
PageLink pageLink = new PageLink(23);
|
||||||
PageData<Edge> pageData = null;
|
PageData<Edge> pageData = null;
|
||||||
@ -412,23 +425,30 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testFindTenantEdgesByName() throws Exception {
|
public void testFindTenantEdgesByName() throws Exception {
|
||||||
String title1 = "Edge title 1";
|
String title1 = "Edge title 1";
|
||||||
List<Edge> edgesTitle1 = new ArrayList<>();
|
int cntEntity = 143;
|
||||||
for (int i = 0; i < 143; i++) {
|
futures = new ArrayList<>(cntEntity);
|
||||||
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title1 + suffix;
|
String name = title1 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, "default");
|
Edge edge = constructEdge(name, "default");
|
||||||
edgesTitle1.add(doPost("/api/edge", edge, Edge.class));
|
futures.add(executor.submit(() ->
|
||||||
|
doPost("/api/edge", edge, Edge.class)));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesTitle1 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
String title2 = "Edge title 2";
|
String title2 = "Edge title 2";
|
||||||
List<Edge> edgesTitle2 = new ArrayList<>();
|
cntEntity = 75;
|
||||||
for (int i = 0; i < 75; i++) {
|
futures = new ArrayList<>(cntEntity);
|
||||||
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title2 + suffix;
|
String name = title2 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, "default");
|
Edge edge = constructEdge(name, "default");
|
||||||
edgesTitle2.add(doPost("/api/edge", edge, Edge.class));
|
futures.add(executor.submit(() ->
|
||||||
|
doPost("/api/edge", edge, Edge.class)));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesTitle2 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
List<Edge> loadedEdgesTitle1 = new ArrayList<>();
|
List<Edge> loadedEdgesTitle1 = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(15, 0, title1);
|
PageLink pageLink = new PageLink(15, 0, title1);
|
||||||
@ -494,24 +514,31 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
public void testFindTenantEdgesByType() throws Exception {
|
public void testFindTenantEdgesByType() throws Exception {
|
||||||
String title1 = "Edge title 1";
|
String title1 = "Edge title 1";
|
||||||
String type1 = "typeA";
|
String type1 = "typeA";
|
||||||
List<Edge> edgesType1 = new ArrayList<>();
|
int cntEntity = 143;
|
||||||
for (int i = 0; i < 143; i++) {
|
futures = new ArrayList<>(cntEntity);
|
||||||
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title1 + suffix;
|
String name = title1 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, type1);
|
Edge edge = constructEdge(name, type1);
|
||||||
edgesType1.add(doPost("/api/edge", edge, Edge.class));
|
futures.add(executor.submit(() ->
|
||||||
|
doPost("/api/edge", edge, Edge.class)));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesType1 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
String title2 = "Edge title 2";
|
String title2 = "Edge title 2";
|
||||||
String type2 = "typeB";
|
String type2 = "typeB";
|
||||||
List<Edge> edgesType2 = new ArrayList<>();
|
cntEntity = 75;
|
||||||
for (int i = 0; i < 75; i++) {
|
futures = new ArrayList<>(cntEntity);
|
||||||
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title2 + suffix;
|
String name = title2 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, type2);
|
Edge edge = constructEdge(name, type2);
|
||||||
edgesType2.add(doPost("/api/edge", edge, Edge.class));
|
futures.add(executor.submit(() ->
|
||||||
|
doPost("/api/edge", edge, Edge.class)));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesType2 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
List<Edge> loadedEdgesType1 = new ArrayList<>();
|
List<Edge> loadedEdgesType1 = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(15);
|
PageLink pageLink = new PageLink(15);
|
||||||
@ -582,14 +609,17 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
|
|
||||||
Mockito.reset(tbClusterService, auditLogService);
|
Mockito.reset(tbClusterService, auditLogService);
|
||||||
|
|
||||||
List<Edge> edges = new ArrayList<>();
|
|
||||||
int cntEntity = 128;
|
int cntEntity = 128;
|
||||||
|
futures = new ArrayList<>(cntEntity);
|
||||||
for (int i = 0; i < cntEntity; i++) {
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
Edge edge = constructEdge("Edge" + i, "default");
|
Edge edge = constructEdge("Edge" + i, "default");
|
||||||
edge = doPost("/api/edge", edge, Edge.class);
|
futures.add(executor.submit(() -> {
|
||||||
edges.add(doPost("/api/customer/" + customerId.getId().toString()
|
Edge edge1 = doPost("/api/edge", edge, Edge.class);
|
||||||
+ "/edge/" + edge.getId().getId().toString(), Edge.class));
|
return doPost("/api/customer/" + customerId.getId().toString()
|
||||||
|
+ "/edge/" + edge1.getId().getId().toString(), Edge.class);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
List<Edge> edges = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Edge(), new Edge(),
|
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Edge(), new Edge(),
|
||||||
savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
|
savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
|
||||||
@ -622,28 +652,37 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
customer = doPost("/api/customer", customer, Customer.class);
|
customer = doPost("/api/customer", customer, Customer.class);
|
||||||
CustomerId customerId = customer.getId();
|
CustomerId customerId = customer.getId();
|
||||||
|
|
||||||
|
int cntEntity = 125;
|
||||||
String title1 = "Edge title 1";
|
String title1 = "Edge title 1";
|
||||||
List<Edge> edgesTitle1 = new ArrayList<>();
|
futures = new ArrayList<>(cntEntity);
|
||||||
for (int i = 0; i < 125; i++) {
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title1 + suffix;
|
String name = title1 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, "default");
|
Edge edge = constructEdge(name, "default");
|
||||||
edge = doPost("/api/edge", edge, Edge.class);
|
futures.add(executor.submit(() -> {
|
||||||
edgesTitle1.add(doPost("/api/customer/" + customerId.getId().toString()
|
Edge edge1 = doPost("/api/edge", edge, Edge.class);
|
||||||
+ "/edge/" + edge.getId().getId().toString(), Edge.class));
|
return doPost("/api/customer/" + customerId.getId().toString()
|
||||||
|
+ "/edge/" + edge1.getId().getId().toString(), Edge.class);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesTitle1 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
|
cntEntity = 143;
|
||||||
String title2 = "Edge title 2";
|
String title2 = "Edge title 2";
|
||||||
List<Edge> edgesTitle2 = new ArrayList<>();
|
futures = new ArrayList<>(cntEntity);
|
||||||
for (int i = 0; i < 143; i++) {
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title2 + suffix;
|
String name = title2 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, "default");
|
Edge edge = constructEdge(name, "default");
|
||||||
edge = doPost("/api/edge", edge, Edge.class);
|
futures.add(executor.submit(() -> {
|
||||||
edgesTitle2.add(doPost("/api/customer/" + customerId.getId().toString()
|
Edge edge1 = doPost("/api/edge", edge, Edge.class);
|
||||||
+ "/edge/" + edge.getId().getId().toString(), Edge.class));
|
return doPost("/api/customer/" + customerId.getId().toString()
|
||||||
|
+ "/edge/" + edge1.getId().getId().toString(), Edge.class);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesTitle2 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
List<Edge> loadedEdgesTitle1 = new ArrayList<>();
|
List<Edge> loadedEdgesTitle1 = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(15, 0, title1);
|
PageLink pageLink = new PageLink(15, 0, title1);
|
||||||
@ -687,7 +726,7 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
int cntEntity = loadedEdgesTitle1.size();
|
cntEntity = loadedEdgesTitle1.size();
|
||||||
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Edge(), new Edge(),
|
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Edge(), new Edge(),
|
||||||
savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
|
savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
|
||||||
ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UNASSIGNED_FROM_CUSTOMER, cntEntity, cntEntity, 3);
|
ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UNASSIGNED_FROM_CUSTOMER, cntEntity, cntEntity, 3);
|
||||||
@ -719,30 +758,39 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
|
|||||||
customer = doPost("/api/customer", customer, Customer.class);
|
customer = doPost("/api/customer", customer, Customer.class);
|
||||||
CustomerId customerId = customer.getId();
|
CustomerId customerId = customer.getId();
|
||||||
|
|
||||||
|
int cntEntity = 125;
|
||||||
String title1 = "Edge title 1";
|
String title1 = "Edge title 1";
|
||||||
String type1 = "typeC";
|
String type1 = "typeC";
|
||||||
List<Edge> edgesType1 = new ArrayList<>();
|
futures = new ArrayList<>(cntEntity);
|
||||||
for (int i = 0; i < 125; i++) {
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title1 + suffix;
|
String name = title1 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, type1);
|
Edge edge = constructEdge(name, type1);
|
||||||
edge = doPost("/api/edge", edge, Edge.class);
|
futures.add(executor.submit(() -> {
|
||||||
edgesType1.add(doPost("/api/customer/" + customerId.getId().toString()
|
Edge edge1 = doPost("/api/edge", edge, Edge.class);
|
||||||
+ "/edge/" + edge.getId().getId().toString(), Edge.class));
|
return doPost("/api/customer/" + customerId.getId().toString()
|
||||||
|
+ "/edge/" + edge1.getId().getId().toString(), Edge.class);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesType1 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
|
cntEntity = 143;
|
||||||
String title2 = "Edge title 2";
|
String title2 = "Edge title 2";
|
||||||
String type2 = "typeD";
|
String type2 = "typeD";
|
||||||
List<Edge> edgesType2 = new ArrayList<>();
|
futures = new ArrayList<>(cntEntity);
|
||||||
for (int i = 0; i < 143; i++) {
|
for (int i = 0; i < cntEntity; i++) {
|
||||||
String suffix = StringUtils.randomAlphanumeric(15);
|
String suffix = StringUtils.randomAlphanumeric(15);
|
||||||
String name = title2 + suffix;
|
String name = title2 + suffix;
|
||||||
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase();
|
||||||
Edge edge = constructEdge(name, type2);
|
Edge edge = constructEdge(name, type2);
|
||||||
edge = doPost("/api/edge", edge, Edge.class);
|
futures.add(executor.submit(() -> {
|
||||||
edgesType2.add(doPost("/api/customer/" + customerId.getId().toString()
|
Edge edge1 = doPost("/api/edge", edge, Edge.class);
|
||||||
+ "/edge/" + edge.getId().getId().toString(), Edge.class));
|
return doPost("/api/customer/" + customerId.getId().toString()
|
||||||
|
+ "/edge/" + edge1.getId().getId().toString(), Edge.class);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
List<Edge> edgesType2 = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
|
||||||
|
|
||||||
List<Edge> loadedEdgesType1 = new ArrayList<>();
|
List<Edge> loadedEdgesType1 = new ArrayList<>();
|
||||||
PageLink pageLink = new PageLink(15, 0, title1);
|
PageLink pageLink = new PageLink(15, 0, title1);
|
||||||
|
|||||||
@ -501,7 +501,6 @@ abstract public class BaseDeviceEdgeTest extends AbstractEdgeTest {
|
|||||||
Assert.assertTrue(deviceUpdateMsgOpt.isPresent());
|
Assert.assertTrue(deviceUpdateMsgOpt.isPresent());
|
||||||
DeviceUpdateMsg latestDeviceUpdateMsg = deviceUpdateMsgOpt.get();
|
DeviceUpdateMsg latestDeviceUpdateMsg = deviceUpdateMsgOpt.get();
|
||||||
Assert.assertNotEquals(deviceOnCloudName, latestDeviceUpdateMsg.getName());
|
Assert.assertNotEquals(deviceOnCloudName, latestDeviceUpdateMsg.getName());
|
||||||
Assert.assertEquals(deviceOnCloudName, latestDeviceUpdateMsg.getConflictName());
|
|
||||||
|
|
||||||
UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
|
UUID newDeviceId = new UUID(latestDeviceUpdateMsg.getIdMSB(), latestDeviceUpdateMsg.getIdLSB());
|
||||||
|
|
||||||
|
|||||||
@ -34,5 +34,5 @@ public enum EdgeEventActionType {
|
|||||||
ASSIGNED_TO_EDGE,
|
ASSIGNED_TO_EDGE,
|
||||||
UNASSIGNED_FROM_EDGE,
|
UNASSIGNED_FROM_EDGE,
|
||||||
CREDENTIALS_REQUEST,
|
CREDENTIALS_REQUEST,
|
||||||
ENTITY_MERGE_REQUEST
|
ENTITY_MERGE_REQUEST // deprecated
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ enum UpdateMsgType {
|
|||||||
ENTITY_DELETED_RPC_MESSAGE = 2;
|
ENTITY_DELETED_RPC_MESSAGE = 2;
|
||||||
ALARM_ACK_RPC_MESSAGE = 3;
|
ALARM_ACK_RPC_MESSAGE = 3;
|
||||||
ALARM_CLEAR_RPC_MESSAGE = 4;
|
ALARM_CLEAR_RPC_MESSAGE = 4;
|
||||||
ENTITY_MERGE_RPC_MESSAGE = 5;
|
ENTITY_MERGE_RPC_MESSAGE = 5; // deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
message EntityDataProto {
|
message EntityDataProto {
|
||||||
@ -199,7 +199,7 @@ message DeviceUpdateMsg {
|
|||||||
string type = 9;
|
string type = 9;
|
||||||
optional string label = 10;
|
optional string label = 10;
|
||||||
optional string additionalInfo = 11;
|
optional string additionalInfo = 11;
|
||||||
optional string conflictName = 12;
|
optional string conflictName = 12; // deprecated
|
||||||
optional int64 firmwareIdMSB = 13;
|
optional int64 firmwareIdMSB = 13;
|
||||||
optional int64 firmwareIdLSB = 14;
|
optional int64 firmwareIdLSB = 14;
|
||||||
optional bytes deviceDataBytes = 15;
|
optional bytes deviceDataBytes = 15;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user