future;
- switch (type) {
- case EDGE:
- future = edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg);
- break;
- case ASSET:
- future = assetProcessor.processAssetNotification(tenantId, edgeNotificationMsg);
- break;
- case DEVICE:
- future = deviceProcessor.processDeviceNotification(tenantId, edgeNotificationMsg);
- break;
- case ENTITY_VIEW:
- future = entityViewProcessor.processEntityViewNotification(tenantId, edgeNotificationMsg);
- break;
- case DASHBOARD:
- future = dashboardProcessor.processDashboardNotification(tenantId, edgeNotificationMsg);
- break;
- case RULE_CHAIN:
- future = ruleChainProcessor.processRuleChainNotification(tenantId, edgeNotificationMsg);
- break;
- case USER:
- future = userProcessor.processUserNotification(tenantId, edgeNotificationMsg);
- break;
- case CUSTOMER:
- future = customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg);
- break;
- case DEVICE_PROFILE:
- future = deviceProfileProcessor.processDeviceProfileNotification(tenantId, edgeNotificationMsg);
- break;
- case ASSET_PROFILE:
- future = assetProfileProcessor.processAssetProfileNotification(tenantId, edgeNotificationMsg);
- break;
- case OTA_PACKAGE:
- future = otaPackageProcessor.processOtaPackageNotification(tenantId, edgeNotificationMsg);
- break;
- case WIDGETS_BUNDLE:
- future = widgetBundleProcessor.processWidgetsBundleNotification(tenantId, edgeNotificationMsg);
- break;
- case WIDGET_TYPE:
- future = widgetTypeProcessor.processWidgetTypeNotification(tenantId, edgeNotificationMsg);
- break;
- case QUEUE:
- future = queueProcessor.processQueueNotification(tenantId, edgeNotificationMsg);
- break;
- case ALARM:
- future = alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg);
- break;
- case RELATION:
- future = relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg);
- break;
- default:
- log.warn("Edge event type [{}] is not designed to be pushed to edge", type);
- future = Futures.immediateFuture(null);
- }
- Futures.addCallback(future, new FutureCallback<>() {
- @Override
- public void onSuccess(@Nullable Void unused) {
- callback.onSuccess();
- }
-
- @Override
- public void onFailure(Throwable throwable) {
- callBackFailure(edgeNotificationMsg, callback, throwable);
+ executor.submit(() -> {
+ try {
+ if (deadline < System.nanoTime()) {
+ log.warn("[{}] Skipping notification message because deadline reached {}", tenantId, edgeNotificationMsg);
+ return;
+ }
+ EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
+ switch (type) {
+ case EDGE:
+ edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg);
+ break;
+ case ASSET:
+ assetProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case ASSET_PROFILE:
+ assetProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case DEVICE:
+ deviceProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case DEVICE_PROFILE:
+ deviceProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case ENTITY_VIEW:
+ entityViewProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case DASHBOARD:
+ dashboardProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case RULE_CHAIN:
+ ruleChainProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case USER:
+ userProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case CUSTOMER:
+ customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg);
+ break;
+ case OTA_PACKAGE:
+ otaPackageProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case WIDGETS_BUNDLE:
+ widgetBundleProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case WIDGET_TYPE:
+ widgetTypeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case QUEUE:
+ queueProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case ALARM:
+ alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg);
+ break;
+ case RELATION:
+ relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg);
+ break;
+ case TENANT:
+ tenantEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case TENANT_PROFILE:
+ tenantProfileEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ case TB_RESOURCE:
+ resourceEdgeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
+ break;
+ default:
+ log.warn("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type);
+ }
+ } catch (Exception e) {
+ callBackFailure(tenantId, edgeNotificationMsg, callback, e);
}
- }, dbCallBackExecutor);
+ });
+ callback.onSuccess();
} catch (Exception e) {
- callBackFailure(edgeNotificationMsg, callback, e);
+ callBackFailure(tenantId, edgeNotificationMsg, callback, e);
}
}
- private void callBackFailure(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback, Throwable throwable) {
- log.error("Can't push to edge updates, edgeNotificationMsg [{}]", edgeNotificationMsg, throwable);
+ private void callBackFailure(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback, Throwable throwable) {
+ log.error("[{}] Can't push to edge updates, edgeNotificationMsg [{}]", tenantId, edgeNotificationMsg, throwable);
callback.onFailure(throwable);
}
-
}
-
-
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java
index 474c7ba233..881e22eb69 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java
@@ -15,7 +15,6 @@
*/
package org.thingsboard.server.service.edge;
-import freemarker.template.Configuration;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
@@ -33,28 +32,44 @@ import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.queue.QueueService;
+import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.settings.AdminSettingsService;
+import org.thingsboard.server.dao.tenant.TenantProfileService;
+import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserService;
+import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.queue.util.TbCoreComponent;
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.edge.EdgeMsgConstructor;
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessor;
-import org.thingsboard.server.service.edge.rpc.processor.asset.AssetProfileEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessorFactory;
+import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.customer.CustomerEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessor;
-import org.thingsboard.server.service.edge.rpc.processor.device.DeviceProfileEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessorFactory;
+import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.edge.EdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.ota.OtaPackageEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.queue.QueueEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorFactory;
+import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.rule.RuleChainEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.settings.AdminSettingsEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.telemetry.TelemetryEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.tenant.TenantEdgeProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.tenant.TenantProfileEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.user.UserEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetBundleEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetTypeEdgeProcessor;
@@ -80,9 +95,6 @@ public class EdgeContextComponent {
@Autowired
private AdminSettingsService adminSettingsService;
- @Autowired
- private Configuration freemarkerConfig;
-
@Autowired
private DeviceService deviceService;
@@ -113,6 +125,9 @@ public class EdgeContextComponent {
@Autowired
private CustomerService customerService;
+ @Autowired
+ private WidgetTypeService widgetTypeService;
+
@Autowired
private WidgetsBundleService widgetsBundleService;
@@ -122,9 +137,18 @@ public class EdgeContextComponent {
@Autowired
private OtaPackageService otaPackageService;
+ @Autowired
+ private TenantService tenantService;
+
+ @Autowired
+ private TenantProfileService tenantProfileService;
+
@Autowired
private QueueService queueService;
+ @Autowired
+ private ResourceService resourceService;
+
@Autowired
private AlarmEdgeProcessor alarmProcessor;
@@ -179,9 +203,45 @@ public class EdgeContextComponent {
@Autowired
private QueueEdgeProcessor queueEdgeProcessor;
+ @Autowired
+ private TenantEdgeProcessor tenantEdgeProcessor;
+
+ @Autowired
+ private TenantProfileEdgeProcessor tenantProfileEdgeProcessor;
+
+ @Autowired
+ private ResourceEdgeProcessor resourceEdgeProcessor;
+
@Autowired
private EdgeMsgConstructor edgeMsgConstructor;
+ @Autowired
+ private AlarmEdgeProcessorFactory alarmEdgeProcessorFactory;
+
+ @Autowired
+ private AssetEdgeProcessorFactory assetEdgeProcessorFactory;
+
+ @Autowired
+ private AssetProfileEdgeProcessorFactory assetProfileEdgeProcessorFactory;
+
+ @Autowired
+ private DashboardEdgeProcessorFactory dashboardEdgeProcessorFactory;
+
+ @Autowired
+ private DeviceEdgeProcessorFactory deviceEdgeProcessorFactory;
+
+ @Autowired
+ private DeviceProfileEdgeProcessorFactory deviceProfileEdgeProcessorFactory;
+
+ @Autowired
+ private EntityViewProcessorFactory entityViewProcessorFactory;
+
+ @Autowired
+ private RelationEdgeProcessorFactory relationEdgeProcessorFactory;
+
+ @Autowired
+ private ResourceEdgeProcessorFactory resourceEdgeProcessorFactory;
+
@Autowired
private EdgeEventStorageSettings edgeEventStorageSettings;
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
new file mode 100644
index 0000000000..58edc971b8
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
@@ -0,0 +1,176 @@
+/**
+ * Copyright © 2016-2023 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;
+
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.event.TransactionalEventListener;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.cluster.TbClusterService;
+import org.thingsboard.server.common.data.OtaPackageInfo;
+import org.thingsboard.server.common.data.User;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
+import org.thingsboard.server.common.data.edge.EdgeEventActionType;
+import org.thingsboard.server.common.data.edge.EdgeEventType;
+import org.thingsboard.server.common.data.relation.EntityRelation;
+import org.thingsboard.server.common.data.relation.RelationTypeGroup;
+import org.thingsboard.server.common.data.rule.RuleChain;
+import org.thingsboard.server.common.data.rule.RuleChainType;
+import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.edge.EdgeSynchronizationManager;
+import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent;
+import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
+import org.thingsboard.server.dao.eventsourcing.RelationActionEvent;
+import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
+import org.thingsboard.server.dao.user.UserServiceImpl;
+
+import javax.annotation.PostConstruct;
+
+import static org.thingsboard.server.service.entitiy.DefaultTbNotificationEntityService.edgeTypeByActionType;
+
+/**
+ * This event listener does not support async event processing because relay on ThreadLocal
+ * Another possible approach is to implement a special annotation and a bunch of classes similar to TransactionalApplicationListener
+ * This class is the simplest approach to maintain edge synchronization within the single class.
+ *
+ * For async event publishers, you have to decide whether publish event on creating async task in the same thread where dao method called
+ * @Autowired
+ * EdgeEventSynchronizationManager edgeSynchronizationManager
+ * ...
+ * //some async write action make future
+ * if (!edgeSynchronizationManager.isSync()) {
+ * future.addCallback(eventPublisher.publishEvent(...))
+ * }
+ * */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class EdgeEventSourcingListener {
+
+ private final TbClusterService tbClusterService;
+ private final EdgeSynchronizationManager edgeSynchronizationManager;
+
+ @PostConstruct
+ public void init() {
+ log.info("EdgeEventSourcingListener initiated");
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(SaveEntityEvent> event) {
+ try {
+ if (!isValidSaveEntityEventForEdgeProcessing(event.getEntity(), event.getOldEntity())) {
+ return;
+ }
+ log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event);
+ EdgeEventActionType action = Boolean.TRUE.equals(event.getAdded()) ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED;
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), null, event.getEntityId(),
+ null, null, action, edgeSynchronizationManager.getEdgeId().get());
+ } catch (Exception e) {
+ log.error("[{}] failed to process SaveEntityEvent: {}", event.getTenantId(), event, e);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(DeleteEntityEvent> event) {
+ try {
+ log.trace("[{}] DeleteEntityEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), null, event.getEntityId(),
+ JacksonUtil.toString(event.getEntity()), null, EdgeEventActionType.DELETED,
+ edgeSynchronizationManager.getEdgeId().get());
+ } catch (Exception e) {
+ log.error("[{}] failed to process DeleteEntityEvent: {}", event.getTenantId(), event, e);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(ActionEntityEvent event) {
+ try {
+ log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), event.getEdgeId(), event.getEntityId(),
+ event.getBody(), null, edgeTypeByActionType(event.getActionType()),
+ edgeSynchronizationManager.getEdgeId().get());
+ } catch (Exception e) {
+ log.error("[{}] failed to process ActionEntityEvent: {}", event.getTenantId(), event, e);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(RelationActionEvent event) {
+ try {
+ EntityRelation relation = event.getRelation();
+ if (relation == null) {
+ log.trace("[{}] skipping RelationActionEvent event in case relation is null: {}", event.getTenantId(), event);
+ return;
+ }
+ if (!RelationTypeGroup.COMMON.equals(relation.getTypeGroup())) {
+ log.trace("[{}] skipping RelationActionEvent event in case NOT COMMON relation type group: {}", event.getTenantId(), event);
+ return;
+ }
+ log.trace("[{}] RelationActionEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), null, null,
+ JacksonUtil.toString(relation), EdgeEventType.RELATION, edgeTypeByActionType(event.getActionType()),
+ edgeSynchronizationManager.getEdgeId().get());
+ } catch (Exception e) {
+ log.error("[{}] failed to process RelationActionEvent: {}", event.getTenantId(), event, e);
+ }
+ }
+
+ private boolean isValidSaveEntityEventForEdgeProcessing(Object entity, Object oldEntity) {
+ if (entity instanceof OtaPackageInfo) {
+ OtaPackageInfo otaPackageInfo = (OtaPackageInfo) entity;
+ return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData();
+ } else if (entity instanceof RuleChain) {
+ RuleChain ruleChain = (RuleChain) entity;
+ return RuleChainType.EDGE.equals(ruleChain.getType());
+ } else if (entity instanceof User) {
+ User user = (User) entity;
+ if (Authority.SYS_ADMIN.equals(user.getAuthority())) {
+ return false;
+ }
+ if (oldEntity != null) {
+ User oldUser = (User) oldEntity;
+ cleanUpUserAdditionalInfo(oldUser);
+ cleanUpUserAdditionalInfo(user);
+ return !user.equals(oldUser);
+ }
+ } else if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) {
+ return false;
+ }
+ // Default: If the entity doesn't match any of the conditions, consider it as valid.
+ return true;
+ }
+
+ private void cleanUpUserAdditionalInfo(User user) {
+ // reset FAILED_LOGIN_ATTEMPTS and LAST_LOGIN_TS - edge is not interested in this information
+ if (user.getAdditionalInfo() instanceof NullNode) {
+ user.setAdditionalInfo(null);
+ }
+ if (user.getAdditionalInfo() instanceof ObjectNode) {
+ ObjectNode additionalInfo = ((ObjectNode) user.getAdditionalInfo());
+ additionalInfo.remove(UserServiceImpl.FAILED_LOGIN_ATTEMPTS);
+ additionalInfo.remove(UserServiceImpl.LAST_LOGIN_TS);
+ if (additionalInfo.isEmpty()) {
+ user.setAdditionalInfo(null);
+ } else {
+ user.setAdditionalInfo(additionalInfo);
+ }
+ }
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java
new file mode 100644
index 0000000000..ba2cd06ee1
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallInstructionsService.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright © 2016-2023 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.instructions;
+
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+import org.thingsboard.server.common.data.edge.Edge;
+import org.thingsboard.server.common.data.edge.EdgeInstructions;
+import org.thingsboard.server.dao.util.DeviceConnectivityUtil;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.install.InstallScripts;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true")
+@TbCoreComponent
+public class DefaultEdgeInstallInstructionsService implements EdgeInstallInstructionsService {
+
+ private static final String EDGE_DIR = "edge";
+ private static final String INSTRUCTIONS_DIR = "instructions";
+ private static final String INSTALL_DIR = "install";
+
+ private final InstallScripts installScripts;
+
+ @Value("${edges.rpc.port}")
+ private int rpcPort;
+
+ @Value("${edges.rpc.ssl.enabled}")
+ private boolean sslEnabled;
+
+ @Value("${app.version:unknown}")
+ @Setter
+ private String appVersion;
+
+ @Override
+ public EdgeInstructions getInstallInstructions(Edge edge, String installationMethod, HttpServletRequest request) {
+ switch (installationMethod.toLowerCase()) {
+ case "docker":
+ return getDockerInstallInstructions(edge, request);
+ case "ubuntu":
+ return getUbuntuInstallInstructions(edge, request);
+ case "centos":
+ return getCentosInstallInstructions(edge, request);
+ default:
+ throw new IllegalArgumentException("Unsupported installation method for Edge: " + installationMethod);
+ }
+ }
+
+ private EdgeInstructions getDockerInstallInstructions(Edge edge, HttpServletRequest request) {
+ String dockerInstallInstructions = readFile(resolveFile("docker", "instructions.md"));
+ String baseUrl = request.getServerName();
+
+ if (DeviceConnectivityUtil.isLocalhost(baseUrl)) {
+ dockerInstallInstructions = dockerInstallInstructions.replace("${EXTRA_HOSTS}", "extra_hosts:\n - \"host.docker.internal:host-gateway\"\n");
+ dockerInstallInstructions = dockerInstallInstructions.replace("${BASE_URL}", "host.docker.internal");
+ } else {
+ dockerInstallInstructions = dockerInstallInstructions.replace("${EXTRA_HOSTS}", "");
+ dockerInstallInstructions = dockerInstallInstructions.replace("${BASE_URL}", baseUrl);
+ }
+ String edgeVersion = appVersion + "EDGE";
+ edgeVersion = edgeVersion.replace("-SNAPSHOT", "");
+ dockerInstallInstructions = dockerInstallInstructions.replace("${TB_EDGE_VERSION}", edgeVersion);
+ dockerInstallInstructions = replacePlaceholders(dockerInstallInstructions, edge);
+ return new EdgeInstructions(dockerInstallInstructions);
+ }
+
+ private EdgeInstructions getUbuntuInstallInstructions(Edge edge, HttpServletRequest request) {
+ String ubuntuInstallInstructions = readFile(resolveFile("ubuntu", "instructions.md"));
+ ubuntuInstallInstructions = replacePlaceholders(ubuntuInstallInstructions, edge);
+ ubuntuInstallInstructions = ubuntuInstallInstructions.replace("${BASE_URL}", request.getServerName());
+ String edgeVersion = appVersion.replace("-SNAPSHOT", "");
+ ubuntuInstallInstructions = ubuntuInstallInstructions.replace("${TB_EDGE_VERSION}", edgeVersion);
+ return new EdgeInstructions(ubuntuInstallInstructions);
+ }
+
+
+ private EdgeInstructions getCentosInstallInstructions(Edge edge, HttpServletRequest request) {
+ String centosInstallInstructions = readFile(resolveFile("centos", "instructions.md"));
+ centosInstallInstructions = replacePlaceholders(centosInstallInstructions, edge);
+ centosInstallInstructions = centosInstallInstructions.replace("${BASE_URL}", request.getServerName());
+ String edgeVersion = appVersion.replace("-SNAPSHOT", "");
+ centosInstallInstructions = centosInstallInstructions.replace("${TB_EDGE_VERSION}", edgeVersion);
+ return new EdgeInstructions(centosInstallInstructions);
+ }
+
+ private String replacePlaceholders(String instructions, Edge edge) {
+ instructions = instructions.replace("${CLOUD_ROUTING_KEY}", edge.getRoutingKey());
+ instructions = instructions.replace("${CLOUD_ROUTING_SECRET}", edge.getSecret());
+ instructions = instructions.replace("${CLOUD_RPC_PORT}", Integer.toString(rpcPort));
+ instructions = instructions.replace("${CLOUD_RPC_SSL_ENABLED}", Boolean.toString(sslEnabled));
+ return instructions;
+ }
+
+ private String readFile(Path file) {
+ try {
+ return Files.readString(file);
+ } catch (IOException e) {
+ log.warn("Failed to read file: {}", file, e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Path resolveFile(String subDir, String... subDirs) {
+ return getEdgeInstallInstructionsDir().resolve(Paths.get(subDir, subDirs));
+ }
+
+ private Path getEdgeInstallInstructionsDir() {
+ return Paths.get(installScripts.getDataDir(), InstallScripts.JSON_DIR, EDGE_DIR, INSTRUCTIONS_DIR, INSTALL_DIR);
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java
deleted file mode 100644
index 2c4a14635d..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * Copyright © 2016-2023 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.instructions;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.stereotype.Service;
-import org.thingsboard.server.common.data.edge.Edge;
-import org.thingsboard.server.common.data.edge.EdgeInstallInstructions;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-import org.thingsboard.server.service.install.InstallScripts;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-@Service
-@Slf4j
-@RequiredArgsConstructor
-@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true")
-@TbCoreComponent
-public class DefaultEdgeInstallService implements EdgeInstallService {
-
- private static final String EDGE_DIR = "edge";
-
- private static final String EDGE_INSTALL_INSTRUCTIONS_DIR = "install_instructions";
-
- private final InstallScripts installScripts;
-
- @Value("${edges.rpc.port}")
- private int rpcPort;
-
- @Value("${edges.rpc.ssl.enabled}")
- private boolean sslEnabled;
-
- @Value("${app.version:unknown}")
- private String appVersion;
-
- @Override
- public EdgeInstallInstructions getDockerInstallInstructions(TenantId tenantId, Edge edge, HttpServletRequest request) {
- String dockerInstallInstructions = readFile(resolveFile("docker", "instructions.md"));
- String baseUrl = request.getServerName();
- if (baseUrl.contains("localhost") || baseUrl.contains("127.0.0.1")) {
- String localhostWarning = readFile(resolveFile("docker", "localhost_warning.md"));
- dockerInstallInstructions = dockerInstallInstructions.replace("${LOCALHOST_WARNING}", localhostWarning);
- dockerInstallInstructions = dockerInstallInstructions.replace("${BASE_URL}", "!!!REPLACE_ME_TO_HOST_IP_ADDRESS!!!");
- } else {
- dockerInstallInstructions = dockerInstallInstructions.replace("${LOCALHOST_WARNING}", "");
- dockerInstallInstructions = dockerInstallInstructions.replace("${BASE_URL}", baseUrl);
- }
- String edgeVersion = appVersion + "EDGE";
- edgeVersion = edgeVersion.replace("-SNAPSHOT", "");
- dockerInstallInstructions = dockerInstallInstructions.replace("${TB_EDGE_VERSION}", edgeVersion);
- dockerInstallInstructions = dockerInstallInstructions.replace("${CLOUD_ROUTING_KEY}", edge.getRoutingKey());
- dockerInstallInstructions = dockerInstallInstructions.replace("${CLOUD_ROUTING_SECRET}", edge.getSecret());
- dockerInstallInstructions = dockerInstallInstructions.replace("${CLOUD_RPC_PORT}", Integer.toString(rpcPort));
- dockerInstallInstructions = dockerInstallInstructions.replace("${CLOUD_RPC_SSL_ENABLED}", Boolean.toString(sslEnabled));
- return new EdgeInstallInstructions(dockerInstallInstructions);
- }
-
- private String readFile(Path file) {
- try {
- return new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
- } catch (IOException e) {
- log.warn("Failed to read file: {}", file, e);
- throw new RuntimeException(e);
- }
- }
-
- private Path resolveFile(String subDir, String... subDirs) {
- return getEdgeInstallInstructionsDir().resolve(Paths.get(subDir, subDirs));
- }
-
- private Path getEdgeInstallInstructionsDir() {
- return Paths.get(installScripts.getDataDir(), InstallScripts.JSON_DIR, EDGE_DIR, EDGE_INSTALL_INSTRUCTIONS_DIR);
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java
new file mode 100644
index 0000000000..d4fa1f31a7
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeUpgradeInstructionsService.java
@@ -0,0 +1,193 @@
+/**
+ * Copyright © 2016-2023 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.instructions;
+
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+import org.thingsboard.server.common.data.DataConstants;
+import org.thingsboard.server.common.data.EdgeUpgradeInfo;
+import org.thingsboard.server.common.data.edge.EdgeInstructions;
+import org.thingsboard.server.common.data.id.EdgeId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.kv.AttributeKvEntry;
+import org.thingsboard.server.dao.attributes.AttributesService;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.install.InstallScripts;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true")
+@TbCoreComponent
+public class DefaultEdgeUpgradeInstructionsService implements EdgeUpgradeInstructionsService {
+
+ private static final Map upgradeVersionHashMap = new HashMap<>();
+
+ private static final String EDGE_DIR = "edge";
+ private static final String INSTRUCTIONS_DIR = "instructions";
+ private static final String UPGRADE_DIR = "upgrade";
+
+ private final InstallScripts installScripts;
+ private final AttributesService attributesService;
+
+ @Value("${app.version:unknown}")
+ @Setter
+ private String appVersion;
+
+ @Override
+ public EdgeInstructions getUpgradeInstructions(String edgeVersion, String upgradeMethod) {
+ String tbVersion = appVersion.replace("-SNAPSHOT", "");
+ String currentEdgeVersion = convertEdgeVersionToDocsFormat(edgeVersion);
+ switch (upgradeMethod.toLowerCase()) {
+ case "docker":
+ return getDockerUpgradeInstructions(tbVersion, currentEdgeVersion);
+ case "ubuntu":
+ case "centos":
+ return getLinuxUpgradeInstructions(tbVersion, currentEdgeVersion, upgradeMethod.toLowerCase());
+ default:
+ throw new IllegalArgumentException("Unsupported upgrade method for Edge: " + upgradeMethod);
+ }
+ }
+
+ @Override
+ public void updateInstructionMap(Map map) {
+ for (String key : map.keySet()) {
+ upgradeVersionHashMap.put(key, map.get(key));
+ }
+ }
+
+ @Override
+ public boolean isUpgradeAvailable(TenantId tenantId, EdgeId edgeId) throws Exception {
+ Optional attributeKvEntryOpt = attributesService.find(tenantId, edgeId, DataConstants.SERVER_SCOPE, DataConstants.EDGE_VERSION_ATTR_KEY).get();
+ if (attributeKvEntryOpt.isPresent()) {
+ String edgeVersionFormatted = convertEdgeVersionToDocsFormat(attributeKvEntryOpt.get().getValueAsString());
+ return isVersionGreaterOrEqualsThan(edgeVersionFormatted, "3.6.0") && !isVersionGreaterOrEqualsThan(edgeVersionFormatted, appVersion);
+ }
+ return false;
+ }
+
+ private boolean isVersionGreaterOrEqualsThan(String version1, String version2) {
+ String[] v1 = version1.split("\\.");
+ String[] v2 = version2.split("\\.");
+
+ int length = Math.max(v1.length, v2.length);
+ for (int i = 0; i < length; i++) {
+ int num1 = i < v1.length ? Integer.parseInt(v1[i]) : 0;
+ int num2 = i < v2.length ? Integer.parseInt(v2[i]) : 0;
+
+ if (num1 < num2) {
+ return false;
+ } else if (num1 > num2) {
+ return true;
+ }
+ }
+ return true;
+ }
+
+ private EdgeInstructions getDockerUpgradeInstructions(String tbVersion, String currentEdgeVersion) {
+ EdgeUpgradeInfo edgeUpgradeInfo = upgradeVersionHashMap.get(currentEdgeVersion);
+ if (edgeUpgradeInfo == null || edgeUpgradeInfo.getNextEdgeVersion() == null || tbVersion.equals(currentEdgeVersion)) {
+ return new EdgeInstructions("Edge upgrade instruction for " + currentEdgeVersion + "EDGE is not available.");
+ }
+ StringBuilder result = new StringBuilder(readFile(resolveFile("docker", "upgrade_preparing.md")));
+ while (edgeUpgradeInfo.getNextEdgeVersion() != null && !tbVersion.equals(currentEdgeVersion)) {
+ String edgeVersion = edgeUpgradeInfo.getNextEdgeVersion();
+ String dockerUpgradeInstructions = readFile(resolveFile("docker", "instructions.md"));
+ if (edgeUpgradeInfo.isRequiresUpdateDb()) {
+ String upgradeDb = readFile(resolveFile("docker", "upgrade_db.md"));
+ dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${UPGRADE_DB}", upgradeDb);
+ } else {
+ dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${UPGRADE_DB}", "");
+ }
+ dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${TB_EDGE_VERSION}", edgeVersion + "EDGE");
+ dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${FROM_TB_EDGE_VERSION}", currentEdgeVersion + "EDGE");
+ currentEdgeVersion = edgeVersion;
+ edgeUpgradeInfo = upgradeVersionHashMap.get(edgeUpgradeInfo.getNextEdgeVersion());
+ result.append(dockerUpgradeInstructions);
+ }
+ String startService = readFile(resolveFile("docker", "start_service.md"));
+ startService = startService.replace("${TB_EDGE_VERSION}", currentEdgeVersion + "EDGE");
+ result.append(startService);
+ return new EdgeInstructions(result.toString());
+ }
+
+ private EdgeInstructions getLinuxUpgradeInstructions(String tbVersion, String currentEdgeVersion, String os) {
+ EdgeUpgradeInfo edgeUpgradeInfo = upgradeVersionHashMap.get(currentEdgeVersion);
+ if (edgeUpgradeInfo == null || edgeUpgradeInfo.getNextEdgeVersion() == null || tbVersion.equals(currentEdgeVersion)) {
+ return new EdgeInstructions("Edge upgrade instruction for " + currentEdgeVersion + "EDGE is not available.");
+ }
+ String upgrade_preparing = readFile(resolveFile("upgrade_preparing.md"));
+ upgrade_preparing = upgrade_preparing.replace("${OS}", os.equals("centos") ? "RHEL/CentOS 7/8" : "Ubuntu");
+ StringBuilder result = new StringBuilder(upgrade_preparing);
+ while (edgeUpgradeInfo.getNextEdgeVersion() != null && !tbVersion.equals(currentEdgeVersion)) {
+ String edgeVersion = edgeUpgradeInfo.getNextEdgeVersion();
+ String linuxUpgradeInstructions = readFile(resolveFile(os, "instructions.md"));
+ if (edgeUpgradeInfo.isRequiresUpdateDb()) {
+ String upgradeDb = readFile(resolveFile("upgrade_db.md"));
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${UPGRADE_DB}", upgradeDb);
+ } else {
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${UPGRADE_DB}", "");
+ }
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${TB_EDGE_TAG}", getTagVersion(edgeVersion));
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${FROM_TB_EDGE_TAG}", getTagVersion(currentEdgeVersion));
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${TB_EDGE_VERSION}", edgeVersion);
+ linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${FROM_TB_EDGE_VERSION}", currentEdgeVersion);
+ currentEdgeVersion = edgeVersion;
+ edgeUpgradeInfo = upgradeVersionHashMap.get(edgeUpgradeInfo.getNextEdgeVersion());
+ result.append(linuxUpgradeInstructions);
+ }
+ String startService = readFile(resolveFile("start_service.md"));
+ result.append(startService);
+ return new EdgeInstructions(result.toString());
+ }
+
+ private String getTagVersion(String version) {
+ return version.endsWith(".0") ? version.substring(0, version.length() - 2) : version;
+ }
+
+ private String convertEdgeVersionToDocsFormat(String edgeVersion) {
+ return edgeVersion.replace("_", ".").substring(2);
+ }
+
+ private String readFile(Path file) {
+ try {
+ return Files.readString(file);
+ } catch (IOException e) {
+ log.warn("Failed to read file: {}", file, e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Path resolveFile(String subDir, String... subDirs) {
+ return getEdgeInstallInstructionsDir().resolve(Paths.get(subDir, subDirs));
+ }
+
+ private Path getEdgeInstallInstructionsDir() {
+ return Paths.get(installScripts.getDataDir(), InstallScripts.JSON_DIR, EDGE_DIR, INSTRUCTIONS_DIR, UPGRADE_DIR);
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallInstructionsService.java
new file mode 100644
index 0000000000..9df1f86e86
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallInstructionsService.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright © 2016-2023 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.instructions;
+
+import org.thingsboard.server.common.data.edge.Edge;
+import org.thingsboard.server.common.data.edge.EdgeInstructions;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface EdgeInstallInstructionsService {
+
+ EdgeInstructions getInstallInstructions(Edge edge, String installationMethod, HttpServletRequest request);
+
+ void setAppVersion(String version);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java
deleted file mode 100644
index 2a030fc4fa..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright © 2016-2023 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.instructions;
-
-import org.thingsboard.server.common.data.edge.Edge;
-import org.thingsboard.server.common.data.edge.EdgeInstallInstructions;
-import org.thingsboard.server.common.data.id.TenantId;
-
-import javax.servlet.http.HttpServletRequest;
-
-public interface EdgeInstallService {
-
- EdgeInstallInstructions getDockerInstallInstructions(TenantId tenantId, Edge edge, HttpServletRequest request);
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java
new file mode 100644
index 0000000000..30f8082bd3
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeUpgradeInstructionsService.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2016-2023 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.instructions;
+
+import org.thingsboard.server.common.data.EdgeUpgradeInfo;
+import org.thingsboard.server.common.data.edge.EdgeInstructions;
+import org.thingsboard.server.common.data.id.EdgeId;
+import org.thingsboard.server.common.data.id.TenantId;
+
+import java.util.Map;
+
+public interface EdgeUpgradeInstructionsService {
+
+ EdgeInstructions getUpgradeInstructions(String edgeVersion, String upgradeMethod);
+
+ void updateInstructionMap(Map upgradeVersions);
+
+ void setAppVersion(String version);
+
+ boolean isUpgradeAvailable(TenantId tenantId, EdgeId edgeId) throws Exception;
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
index bda510a762..50b80a82f7 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.BooleanDataEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
@@ -71,10 +72,6 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
-import static org.thingsboard.server.common.data.DataConstants.CONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.DISCONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
-
@Service
@Slf4j
@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true")
@@ -198,17 +195,17 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
switch (msg.getMsgType()) {
case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG:
EdgeEventUpdateMsg edgeEventUpdateMsg = (EdgeEventUpdateMsg) msg;
- log.trace("[{}] onToEdgeSessionMsg [{}]", edgeEventUpdateMsg.getTenantId(), msg);
+ log.trace("[{}] onToEdgeSessionMsg [{}]", tenantId, msg);
onEdgeEvent(tenantId, edgeEventUpdateMsg.getEdgeId());
break;
case EDGE_SYNC_REQUEST_TO_EDGE_SESSION_MSG:
ToEdgeSyncRequest toEdgeSyncRequest = (ToEdgeSyncRequest) msg;
- log.trace("[{}] toEdgeSyncRequest [{}]", toEdgeSyncRequest.getTenantId(), msg);
+ log.trace("[{}] toEdgeSyncRequest [{}]", tenantId, msg);
startSyncProcess(tenantId, toEdgeSyncRequest.getEdgeId(), toEdgeSyncRequest.getId());
break;
case EDGE_SYNC_RESPONSE_FROM_EDGE_SESSION_MSG:
FromEdgeSyncResponse fromEdgeSyncResponse = (FromEdgeSyncResponse) msg;
- log.trace("[{}] fromEdgeSyncResponse [{}]", fromEdgeSyncResponse.getTenantId(), msg);
+ log.trace("[{}] fromEdgeSyncResponse [{}]", tenantId, msg);
processSyncResponse(fromEdgeSyncResponse);
break;
}
@@ -266,7 +263,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
}
private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) {
- log.info("[{}] edge [{}] connected successfully.", edgeGrpcSession.getSessionId(), edgeId);
+ TenantId tenantId = edgeGrpcSession.getEdge().getTenantId();
+ log.info("[{}][{}] edge [{}] connected successfully.", tenantId, edgeGrpcSession.getSessionId(), edgeId);
sessions.put(edgeId, edgeGrpcSession);
final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
newEventLock.lock();
@@ -275,10 +273,10 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
} finally {
newEventLock.unlock();
}
- save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true);
+ save(tenantId, edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true);
long lastConnectTs = System.currentTimeMillis();
- save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, lastConnectTs);
- pushRuleEngineMessage(edgeGrpcSession.getEdge().getTenantId(), edgeId, lastConnectTs, CONNECT_EVENT);
+ save(tenantId, edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, lastConnectTs);
+ pushRuleEngineMessage(tenantId, edgeId, lastConnectTs, TbMsgType.CONNECT_EVENT);
cancelScheduleEdgeEventsCheck(edgeId);
scheduleEdgeEventsCheck(edgeGrpcSession);
}
@@ -337,11 +335,14 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
newEventLock.lock();
try {
if (Boolean.TRUE.equals(sessionNewEvents.get(edgeId))) {
- log.trace("[{}] Set session new events flag to false", edgeId.getId());
+ log.trace("[{}][{}] Set session new events flag to false", tenantId, edgeId.getId());
sessionNewEvents.put(edgeId, false);
Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() {
@Override
- public void onSuccess(Void result) {
+ public void onSuccess(Boolean newEventsAdded) {
+ if (Boolean.TRUE.equals(newEventsAdded)) {
+ sessionNewEvents.put(edgeId, true);
+ }
scheduleEdgeEventsCheck(session);
}
@@ -380,53 +381,61 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
}
}
- private void onEdgeDisconnect(EdgeId edgeId) {
- log.info("[{}] edge disconnected!", edgeId);
- EdgeGrpcSession removed = sessions.remove(edgeId);
- final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
- newEventLock.lock();
- try {
- sessionNewEvents.remove(edgeId);
- } finally {
- newEventLock.unlock();
+ private void onEdgeDisconnect(EdgeId edgeId, UUID sessionId) {
+ log.info("[{}][{}] edge disconnected!", edgeId, sessionId);
+ EdgeGrpcSession toRemove = sessions.get(edgeId);
+ if (toRemove.getSessionId().equals(sessionId)) {
+ toRemove = sessions.remove(edgeId);
+ final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
+ newEventLock.lock();
+ try {
+ sessionNewEvents.remove(edgeId);
+ } finally {
+ newEventLock.unlock();
+ }
+ TenantId tenantId = toRemove.getEdge().getTenantId();
+ save(tenantId, edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false);
+ long lastDisconnectTs = System.currentTimeMillis();
+ save(tenantId, edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, lastDisconnectTs);
+ pushRuleEngineMessage(toRemove.getEdge().getTenantId(), edgeId, lastDisconnectTs, TbMsgType.DISCONNECT_EVENT);
+ cancelScheduleEdgeEventsCheck(edgeId);
+ } else {
+ log.debug("[{}] edge session [{}] is not available anymore, nothing to remove. most probably this session is already outdated!", edgeId, sessionId);
}
- save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false);
- long lastDisconnectTs = System.currentTimeMillis();
- save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, lastDisconnectTs);
- pushRuleEngineMessage(removed.getEdge().getTenantId(), edgeId, lastDisconnectTs, DISCONNECT_EVENT);
- cancelScheduleEdgeEventsCheck(edgeId);
}
- private void save(EdgeId edgeId, String key, long value) {
- log.debug("[{}] Updating long edge telemetry [{}] [{}]", edgeId, key, value);
+ private void save(TenantId tenantId, EdgeId edgeId, String key, long value) {
+ log.debug("[{}][{}] Updating long edge telemetry [{}] [{}]", tenantId, edgeId, key, value);
if (persistToTelemetry) {
tsSubService.saveAndNotify(
- TenantId.SYS_TENANT_ID, edgeId,
+ tenantId, edgeId,
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new LongDataEntry(key, value))),
- new AttributeSaveCallback(edgeId, key, value));
+ new AttributeSaveCallback(tenantId, edgeId, key, value));
} else {
- tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(edgeId, key, value));
+ tsSubService.saveAttrAndNotify(tenantId, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(tenantId, edgeId, key, value));
}
}
- private void save(EdgeId edgeId, String key, boolean value) {
- log.debug("[{}] Updating boolean edge telemetry [{}] [{}]", edgeId, key, value);
+ private void save(TenantId tenantId, EdgeId edgeId, String key, boolean value) {
+ log.debug("[{}][{}] Updating boolean edge telemetry [{}] [{}]", tenantId, edgeId, key, value);
if (persistToTelemetry) {
tsSubService.saveAndNotify(
- TenantId.SYS_TENANT_ID, edgeId,
+ tenantId, edgeId,
Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))),
- new AttributeSaveCallback(edgeId, key, value));
+ new AttributeSaveCallback(tenantId, edgeId, key, value));
} else {
- tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(edgeId, key, value));
+ tsSubService.saveAttrAndNotify(tenantId, edgeId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(tenantId, edgeId, key, value));
}
}
private static class AttributeSaveCallback implements FutureCallback {
+ private final TenantId tenantId;
private final EdgeId edgeId;
private final String key;
private final Object value;
- AttributeSaveCallback(EdgeId edgeId, String key, Object value) {
+ AttributeSaveCallback(TenantId tenantId, EdgeId edgeId, String key, Object value) {
+ this.tenantId = tenantId;
this.edgeId = edgeId;
this.key = key;
this.value = value;
@@ -434,19 +443,19 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
@Override
public void onSuccess(@Nullable Void result) {
- log.trace("[{}] Successfully updated attribute [{}] with value [{}]", edgeId, key, value);
+ log.trace("[{}][{}] Successfully updated attribute [{}] with value [{}]", tenantId, edgeId, key, value);
}
@Override
public void onFailure(Throwable t) {
- log.warn("[{}] Failed to update attribute [{}] with value [{}]", edgeId, key, value, t);
+ log.warn("[{}][{}] Failed to update attribute [{}] with value [{}]", tenantId, edgeId, key, value, t);
}
}
- private void pushRuleEngineMessage(TenantId tenantId, EdgeId edgeId, long ts, String msgType) {
+ private void pushRuleEngineMessage(TenantId tenantId, EdgeId edgeId, long ts, TbMsgType msgType) {
try {
ObjectNode edgeState = JacksonUtil.newObjectNode();
- if (msgType.equals(CONNECT_EVENT)) {
+ if (msgType.equals(TbMsgType.CONNECT_EVENT)) {
edgeState.put(DefaultDeviceStateService.ACTIVITY_STATE, true);
edgeState.put(DefaultDeviceStateService.LAST_CONNECT_TIME, ts);
} else {
@@ -456,7 +465,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
String data = JacksonUtil.toString(edgeState);
TbMsgMetaData md = new TbMsgMetaData();
if (!persistToTelemetry) {
- md.putValue(DataConstants.SCOPE, SERVER_SCOPE);
+ md.putValue(DataConstants.SCOPE, DataConstants.SERVER_SCOPE);
}
TbMsg tbMsg = TbMsg.newMsg(msgType, edgeId, md, TbMsgDataType.JSON, data);
clusterService.pushMsgToRuleEngine(tenantId, edgeId, tbMsg, null);
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
index 33aed92682..32ab28b09a 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
@@ -24,6 +24,7 @@ import io.grpc.stub.StreamObserver;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
+import org.springframework.data.util.Pair;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.Edge;
@@ -33,15 +34,22 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
+import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
+import org.thingsboard.server.common.data.page.SortOrder;
+import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg;
import org.thingsboard.server.gen.edge.v1.ConnectRequestMsg;
import org.thingsboard.server.gen.edge.v1.ConnectResponseCode;
import org.thingsboard.server.gen.edge.v1.ConnectResponseMsg;
+import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg;
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
@@ -50,11 +58,13 @@ import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
import org.thingsboard.server.gen.edge.v1.EdgeUpdateMsg;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.gen.edge.v1.EntityDataProto;
+import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
import org.thingsboard.server.gen.edge.v1.EntityViewsRequestMsg;
import org.thingsboard.server.gen.edge.v1.RelationRequestMsg;
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RequestMsg;
import org.thingsboard.server.gen.edge.v1.RequestMsgType;
+import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg;
import org.thingsboard.server.gen.edge.v1.ResponseMsg;
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg;
import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg;
@@ -65,20 +75,27 @@ import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg;
import org.thingsboard.server.service.edge.EdgeContextComponent;
import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.asset.AssetProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.device.DeviceProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.relation.RelationProcessor;
+import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceProcessor;
import java.io.Closeable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
@Slf4j
@Data
@@ -89,20 +106,28 @@ public final class EdgeGrpcSession implements Closeable {
private static final int MAX_DOWNLINK_ATTEMPTS = 10; // max number of attemps to send downlink message if edge connected
private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs";
+ private static final String QUEUE_START_SEQ_ID_ATTR_KEY = "queueStartSeqId";
private final UUID sessionId;
private final BiConsumer sessionOpenListener;
- private final Consumer sessionCloseListener;
+ private final BiConsumer sessionCloseListener;
private final EdgeSessionState sessionState = new EdgeSessionState();
private EdgeContextComponent ctx;
private Edge edge;
+ private TenantId tenantId;
private StreamObserver inputStream;
private StreamObserver outputStream;
private boolean connected;
private boolean syncCompleted;
+ private Long newStartTs;
+ private Long previousStartTs;
+ private Long newStartSeqId;
+ private Long previousStartSeqId;
+ private Long seqIdEnd;
+
private EdgeVersion edgeVersion;
private int maxInboundMessageSize;
@@ -111,7 +136,7 @@ public final class EdgeGrpcSession implements Closeable {
private ScheduledExecutorService sendDownlinkExecutorService;
EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener,
- Consumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize) {
+ BiConsumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize) {
this.sessionId = UUID.randomUUID();
this.ctx = ctx;
this.outputStream = outputStream;
@@ -135,7 +160,7 @@ public final class EdgeGrpcSession implements Closeable {
outputStream.onError(new RuntimeException(responseMsg.getErrorMsg()));
} else {
if (requestMsg.getConnectRequestMsg().hasMaxInboundMessageSize()) {
- log.debug("[{}] Client max inbound message size: {}", sessionId, requestMsg.getConnectRequestMsg().getMaxInboundMessageSize());
+ log.debug("[{}][{}] Client max inbound message size: {}", tenantId, sessionId, requestMsg.getConnectRequestMsg().getMaxInboundMessageSize());
clientMaxInboundMessageSize = requestMsg.getConnectRequestMsg().getMaxInboundMessageSize();
}
connected = true;
@@ -143,8 +168,8 @@ public final class EdgeGrpcSession implements Closeable {
}
if (connected) {
if (requestMsg.getMsgType().equals(RequestMsgType.SYNC_REQUEST_RPC_MESSAGE)) {
- if (requestMsg.hasSyncRequestMsg() && requestMsg.getSyncRequestMsg().getSyncRequired()) {
- boolean fullSync = true;
+ if (requestMsg.hasSyncRequestMsg()) {
+ boolean fullSync = false;
if (requestMsg.getSyncRequestMsg().hasFullSync()) {
fullSync = requestMsg.getSyncRequestMsg().getFullSync();
}
@@ -166,13 +191,13 @@ public final class EdgeGrpcSession implements Closeable {
@Override
public void onError(Throwable t) {
- log.error("[{}] Stream was terminated due to error:", sessionId, t);
+ log.error("[{}][{}] Stream was terminated due to error:", tenantId, sessionId, t);
closeSession();
}
@Override
public void onCompleted() {
- log.info("[{}] Stream was closed and completed successfully!", sessionId);
+ log.info("[{}][{}] Stream was closed and completed successfully!", tenantId, sessionId);
closeSession();
}
@@ -180,7 +205,7 @@ public final class EdgeGrpcSession implements Closeable {
connected = false;
if (edge != null) {
try {
- sessionCloseListener.accept(edge.getId());
+ sessionCloseListener.accept(edge.getId(), sessionId);
} catch (Exception ignored) {
}
}
@@ -193,7 +218,7 @@ public final class EdgeGrpcSession implements Closeable {
}
public void startSyncProcess(boolean fullSync) {
- log.trace("[{}][{}][{}] Staring edge sync process", edge.getTenantId(), edge.getId(), this.sessionId);
+ log.trace("[{}][{}][{}] Staring edge sync process", this.tenantId, edge.getId(), this.sessionId);
syncCompleted = false;
interruptGeneralProcessingOnSync();
doSync(new EdgeSyncCursor(ctx, edge, fullSync));
@@ -203,17 +228,17 @@ public final class EdgeGrpcSession implements Closeable {
if (cursor.hasNext()) {
EdgeEventFetcher next = cursor.getNext();
log.info("[{}][{}] starting sync process, cursor current idx = {}, class = {}",
- edge.getTenantId(), edge.getId(), cursor.getCurrentIdx(), next.getClass().getSimpleName());
- ListenableFuture uuidListenableFuture = startProcessingEdgeEvents(next);
- Futures.addCallback(uuidListenableFuture, new FutureCallback<>() {
+ this.tenantId, edge.getId(), cursor.getCurrentIdx(), next.getClass().getSimpleName());
+ ListenableFuture> future = startProcessingEdgeEvents(next);
+ Futures.addCallback(future, new FutureCallback<>() {
@Override
- public void onSuccess(@Nullable UUID result) {
+ public void onSuccess(@Nullable Pair result) {
doSync(cursor);
}
@Override
public void onFailure(Throwable t) {
- log.error("[{}][{}] Exception during sync process", edge.getTenantId(), edge.getId(), t);
+ log.error("[{}][{}] Exception during sync process", tenantId, edge.getId(), t);
}
}, ctx.getGrpcCallbackExecutorService());
} else {
@@ -230,7 +255,7 @@ public final class EdgeGrpcSession implements Closeable {
@Override
public void onFailure(Throwable t) {
- log.error("[{}][{}] Exception during sending sync complete", edge.getTenantId(), edge.getId(), t);
+ log.error("[{}][{}] Exception during sending sync complete", tenantId, edge.getId(), t);
}
}, ctx.getGrpcCallbackExecutorService());
}
@@ -266,39 +291,40 @@ public final class EdgeGrpcSession implements Closeable {
try {
if (msg.getSuccess()) {
sessionState.getPendingMsgsMap().remove(msg.getDownlinkMsgId());
- log.debug("[{}] Msg has been processed successfully!Msd Id: [{}], Msg: {}", edge.getRoutingKey(), msg.getDownlinkMsgId(), msg);
+ log.debug("[{}][{}] Msg has been processed successfully!Msg Id: [{}], Msg: {}", this.tenantId, edge.getRoutingKey(), msg.getDownlinkMsgId(), msg);
} else {
- log.error("[{}] Msg processing failed! Msd Id: [{}], Error msg: {}", edge.getRoutingKey(), msg.getDownlinkMsgId(), msg.getErrorMsg());
+ log.error("[{}][{}] Msg processing failed! Msg Id: [{}], Error msg: {}", this.tenantId, edge.getRoutingKey(), msg.getDownlinkMsgId(), msg.getErrorMsg());
}
if (sessionState.getPendingMsgsMap().isEmpty()) {
- log.debug("[{}] Pending msgs map is empty. Stopping current iteration", edge.getRoutingKey());
+ log.debug("[{}][{}] Pending msgs map is empty. Stopping current iteration", this.tenantId, edge.getRoutingKey());
stopCurrentSendDownlinkMsgsTask(false);
}
} catch (Exception e) {
- log.error("[{}] Can't process downlink response message [{}]", this.sessionId, msg, e);
+ log.error("[{}][{}] Can't process downlink response message [{}]", this.tenantId, this.sessionId, msg, e);
}
}
private void sendDownlinkMsg(ResponseMsg downlinkMsg) {
- log.trace("[{}] Sending downlink msg [{}]", this.sessionId, downlinkMsg);
+ log.trace("[{}][{}] Sending downlink msg [{}]", this.tenantId, this.sessionId, downlinkMsg);
if (isConnected()) {
downlinkMsgLock.lock();
try {
outputStream.onNext(downlinkMsg);
} catch (Exception e) {
- log.error("[{}] Failed to send downlink message [{}]", this.sessionId, downlinkMsg, e);
+ log.error("[{}][{}] Failed to send downlink message [{}]", this.tenantId, this.sessionId, downlinkMsg, e);
connected = false;
- sessionCloseListener.accept(edge.getId());
+ sessionCloseListener.accept(edge.getId(), sessionId);
} finally {
downlinkMsgLock.unlock();
}
- log.trace("[{}] Response msg successfully sent [{}]", this.sessionId, downlinkMsg);
+ log.trace("[{}][{}] Response msg successfully sent [{}]", this.tenantId, this.sessionId, downlinkMsg);
}
}
void onConfigurationUpdate(Edge edge) {
log.debug("[{}] onConfigurationUpdate [{}]", this.sessionId, edge);
this.edge = edge;
+ this.tenantId = edge.getTenantId();
EdgeUpdateMsg edgeConfig = EdgeUpdateMsg.newBuilder()
.setConfiguration(ctx.getEdgeMsgConstructor().constructEdgeConfiguration(edge)).build();
ResponseMsg edgeConfigMsg = ResponseMsg.newBuilder()
@@ -307,78 +333,100 @@ public final class EdgeGrpcSession implements Closeable {
sendDownlinkMsg(edgeConfigMsg);
}
- ListenableFuture processEdgeEvents() throws Exception {
- SettableFuture result = SettableFuture.create();
- log.trace("[{}] starting processing edge events", this.sessionId);
+ ListenableFuture processEdgeEvents() throws Exception {
+ SettableFuture result = SettableFuture.create();
+ log.trace("[{}][{}] starting processing edge events", this.tenantId, this.sessionId);
if (isConnected() && isSyncCompleted()) {
- Long queueStartTs = getQueueStartTs().get();
+ Pair startTsAndSeqId = getQueueStartTsAndSeqId().get();
+ this.previousStartTs = startTsAndSeqId.getFirst();
+ this.previousStartSeqId = startTsAndSeqId.getSecond();
GeneralEdgeEventFetcher fetcher = new GeneralEdgeEventFetcher(
- queueStartTs,
+ this.previousStartTs,
+ this.previousStartSeqId,
+ this.seqIdEnd,
+ false,
+ Integer.toUnsignedLong(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()),
ctx.getEdgeEventService());
- ListenableFuture ifOffsetFuture = startProcessingEdgeEvents(fetcher);
- Futures.addCallback(ifOffsetFuture, new FutureCallback<>() {
+ Futures.addCallback(startProcessingEdgeEvents(fetcher), new FutureCallback<>() {
@Override
- public void onSuccess(@Nullable UUID ifOffset) {
- if (ifOffset != null) {
- Long newStartTs = Uuids.unixTimestamp(ifOffset);
- ListenableFuture> updateFuture = updateQueueStartTs(newStartTs);
+ public void onSuccess(@Nullable Pair newStartTsAndSeqId) {
+ if (newStartTsAndSeqId != null) {
+ ListenableFuture> updateFuture = updateQueueStartTsAndSeqId(newStartTsAndSeqId);
Futures.addCallback(updateFuture, new FutureCallback<>() {
@Override
public void onSuccess(@Nullable List list) {
- log.debug("[{}] queue offset was updated [{}][{}]", sessionId, ifOffset, newStartTs);
- result.set(null);
+ log.debug("[{}][{}] queue offset was updated [{}]", tenantId, sessionId, newStartTsAndSeqId);
+ if (fetcher.isSeqIdNewCycleStarted()) {
+ seqIdEnd = fetcher.getSeqIdEnd();
+ boolean newEventsAvailable = isNewEdgeEventsAvailable();
+ result.set(newEventsAvailable);
+ } else {
+ seqIdEnd = null;
+ boolean newEventsAvailable = isSeqIdStartedNewCycle();
+ if (!newEventsAvailable) {
+ newEventsAvailable = isNewEdgeEventsAvailable();
+ }
+ result.set(newEventsAvailable);
+ }
}
@Override
public void onFailure(Throwable t) {
- log.error("[{}] Failed to update queue offset [{}]", sessionId, ifOffset, t);
+ log.error("[{}][{}] Failed to update queue offset [{}]", tenantId, sessionId, newStartTsAndSeqId, t);
result.setException(t);
}
}, ctx.getGrpcCallbackExecutorService());
} else {
- log.trace("[{}] ifOffset is null. Skipping iteration without db update", sessionId);
+ log.trace("[{}][{}] newStartTsAndSeqId is null. Skipping iteration without db update", tenantId, sessionId);
result.set(null);
}
}
@Override
public void onFailure(Throwable t) {
- log.error("[{}] Failed to process events", sessionId, t);
+ log.error("[{}][{}] Failed to process events", tenantId, sessionId, t);
result.setException(t);
}
}, ctx.getGrpcCallbackExecutorService());
} else {
- log.trace("[{}] edge is not connected or sync is not completed. Skipping iteration", sessionId);
+ log.trace("[{}][{}] edge is not connected or sync is not completed. Skipping iteration", tenantId, sessionId);
result.set(null);
}
return result;
}
- private ListenableFuture startProcessingEdgeEvents(EdgeEventFetcher fetcher) {
- SettableFuture result = SettableFuture.create();
+ private ListenableFuture> startProcessingEdgeEvents(EdgeEventFetcher fetcher) {
+ SettableFuture> result = SettableFuture.create();
PageLink pageLink = fetcher.getPageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount());
processEdgeEvents(fetcher, pageLink, result);
return result;
}
- private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture result) {
+ private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture> result) {
try {
PageData pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink);
if (isConnected() && !pageData.getData().isEmpty()) {
- log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size());
+ log.trace("[{}][{}][{}] event(s) are going to be processed.", this.tenantId, this.sessionId, pageData.getData().size());
List downlinkMsgsPack = convertToDownlinkMsgsPack(pageData.getData());
Futures.addCallback(sendDownlinkMsgsPack(downlinkMsgsPack), new FutureCallback<>() {
@Override
public void onSuccess(@Nullable Boolean isInterrupted) {
if (Boolean.TRUE.equals(isInterrupted)) {
- log.debug("[{}][{}][{}] Send downlink messages task was interrupted", edge.getTenantId(), edge.getId(), sessionId);
+ log.debug("[{}][{}][{}] Send downlink messages task was interrupted", tenantId, edge.getId(), sessionId);
result.set(null);
} else {
if (isConnected() && pageData.hasNext()) {
processEdgeEvents(fetcher, pageLink.nextPageLink(), result);
} else {
- UUID ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId();
- result.set(ifOffset);
+ EdgeEvent latestEdgeEvent = pageData.getData().get(pageData.getData().size() - 1);
+ UUID idOffset = latestEdgeEvent.getUuidId();
+ if (idOffset != null) {
+ Long newStartTs = Uuids.unixTimestamp(idOffset);
+ long newStartSeqId = latestEdgeEvent.getSeqId();
+ result.set(Pair.of(newStartTs, newStartSeqId));
+ } else {
+ result.set(null);
+ }
}
}
}
@@ -417,14 +465,14 @@ public final class EdgeGrpcSession implements Closeable {
if (isConnected() && sessionState.getPendingMsgsMap().values().size() > 0) {
List copy = new ArrayList<>(sessionState.getPendingMsgsMap().values());
if (attempt > 1) {
- log.warn("[{}] Failed to deliver the batch: {}, attempt: {}", this.sessionId, copy, attempt);
+ log.warn("[{}][{}] Failed to deliver the batch: {}, attempt: {}", this.tenantId, this.sessionId, copy, attempt);
}
- log.trace("[{}] [{}] downlink msg(s) are going to be send.", this.sessionId, copy.size());
+ log.trace("[{}][{}][{}] downlink msg(s) are going to be send.", this.tenantId, this.sessionId, copy.size());
for (DownlinkMsg downlinkMsg : copy) {
if (this.clientMaxInboundMessageSize != 0 && downlinkMsg.getSerializedSize() > this.clientMaxInboundMessageSize) {
log.error("[{}][{}][{}] Downlink msg size [{}] exceeds client max inbound message size [{}]. Skipping this message. " +
"Please increase value of CLOUD_RPC_MAX_INBOUND_MESSAGE_SIZE env variable on the edge and restart it." +
- "Message {}", edge.getTenantId(), edge.getId(), this.sessionId, downlinkMsg.getSerializedSize(),
+ "Message {}", this.tenantId, edge.getId(), this.sessionId, downlinkMsg.getSerializedSize(),
this.clientMaxInboundMessageSize, downlinkMsg);
sessionState.getPendingMsgsMap().remove(downlinkMsg.getDownlinkMsgId());
} else {
@@ -436,15 +484,15 @@ public final class EdgeGrpcSession implements Closeable {
if (attempt < MAX_DOWNLINK_ATTEMPTS) {
scheduleDownlinkMsgsPackSend(attempt + 1);
} else {
- log.warn("[{}] Failed to deliver the batch after {} attempts. Next messages are going to be discarded {}",
- this.sessionId, MAX_DOWNLINK_ATTEMPTS, copy);
+ log.warn("[{}][{}] Failed to deliver the batch after {} attempts. Next messages are going to be discarded {}",
+ this.tenantId, this.sessionId, MAX_DOWNLINK_ATTEMPTS, copy);
stopCurrentSendDownlinkMsgsTask(false);
}
} else {
stopCurrentSendDownlinkMsgsTask(false);
}
} catch (Exception e) {
- log.warn("[{}] Failed to send downlink msgs. Error msg {}", this.sessionId, e.getMessage(), e);
+ log.warn("[{}][{}] Failed to send downlink msgs. Error msg {}", this.tenantId, this.sessionId, e.getMessage(), e);
stopCurrentSendDownlinkMsgsTask(true);
}
};
@@ -461,113 +509,163 @@ public final class EdgeGrpcSession implements Closeable {
}
}
- private DownlinkMsg convertToDownlinkMsg(EdgeEvent edgeEvent) {
- log.trace("[{}][{}] converting edge event to downlink msg [{}]", edge.getTenantId(), this.sessionId, edgeEvent);
- DownlinkMsg downlinkMsg = null;
- try {
- switch (edgeEvent.getAction()) {
- case UPDATED:
- case ADDED:
- case DELETED:
- case ASSIGNED_TO_EDGE:
- case UNASSIGNED_FROM_EDGE:
- case ALARM_ACK:
- case ALARM_CLEAR:
- case CREDENTIALS_UPDATED:
- case RELATION_ADD_OR_UPDATE:
- case RELATION_DELETED:
- case ASSIGNED_TO_CUSTOMER:
- case UNASSIGNED_FROM_CUSTOMER:
- case CREDENTIALS_REQUEST:
- case RPC_CALL:
- downlinkMsg = convertEntityEventToDownlink(edgeEvent);
- log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg);
- break;
- case ATTRIBUTES_UPDATED:
- case POST_ATTRIBUTES:
- case ATTRIBUTES_DELETED:
- case TIMESERIES_UPDATED:
- downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edgeEvent);
- break;
- default:
- log.warn("[{}][{}] Unsupported action type [{}]", edge.getTenantId(), this.sessionId, edgeEvent.getAction());
+ private List convertToDownlinkMsgsPack(List edgeEvents) {
+ List result = new ArrayList<>();
+ for (EdgeEvent edgeEvent : edgeEvents) {
+ log.trace("[{}][{}] converting edge event to downlink msg [{}]", this.tenantId, this.sessionId, edgeEvent);
+ DownlinkMsg downlinkMsg = null;
+ try {
+ switch (edgeEvent.getAction()) {
+ case UPDATED:
+ case ADDED:
+ case DELETED:
+ case ASSIGNED_TO_EDGE:
+ case UNASSIGNED_FROM_EDGE:
+ case ALARM_ACK:
+ case ALARM_CLEAR:
+ case CREDENTIALS_UPDATED:
+ case RELATION_ADD_OR_UPDATE:
+ case RELATION_DELETED:
+ case CREDENTIALS_REQUEST:
+ case RPC_CALL:
+ case ASSIGNED_TO_CUSTOMER:
+ case UNASSIGNED_FROM_CUSTOMER:
+ downlinkMsg = convertEntityEventToDownlink(edgeEvent);
+ log.trace("[{}][{}] entity message processed [{}]", this.tenantId, this.sessionId, downlinkMsg);
+ break;
+ case ATTRIBUTES_UPDATED:
+ case POST_ATTRIBUTES:
+ case ATTRIBUTES_DELETED:
+ case TIMESERIES_UPDATED:
+ downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edgeEvent);
+ break;
+ default:
+ log.warn("[{}][{}] Unsupported action type [{}]", this.tenantId, this.sessionId, edgeEvent.getAction());
+ }
+ } catch (Exception e) {
+ log.error("[{}][{}] Exception during converting edge event to downlink msg", this.tenantId, this.sessionId, e);
+ }
+ if (downlinkMsg != null) {
+ result.add(downlinkMsg);
+ }
+ }
+ return result;
+ }
+
+ private ListenableFuture> getQueueStartTsAndSeqId() {
+ ListenableFuture> future =
+ ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, Arrays.asList(QUEUE_START_TS_ATTR_KEY, QUEUE_START_SEQ_ID_ATTR_KEY));
+ return Futures.transform(future, attributeKvEntries -> {
+ long startTs = 0L;
+ long startSeqId = 0L;
+ for (AttributeKvEntry attributeKvEntry : attributeKvEntries) {
+ if (QUEUE_START_TS_ATTR_KEY.equals(attributeKvEntry.getKey())) {
+ startTs = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
+ }
+ if (QUEUE_START_SEQ_ID_ATTR_KEY.equals(attributeKvEntry.getKey())) {
+ startSeqId = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
+ }
}
+ if (startSeqId == 0L) {
+ startSeqId = findStartSeqIdFromOldestEventIfAny();
+ }
+ return Pair.of(startTs, startSeqId);
+ }, ctx.getGrpcCallbackExecutorService());
+ }
+
+ private boolean isSeqIdStartedNewCycle() {
+ try {
+ TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, this.newStartTs, System.currentTimeMillis());
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), 0L, this.previousStartSeqId == 0 ? null : this.previousStartSeqId - 1, pageLink);
+ return !edgeEvents.getData().isEmpty();
} catch (Exception e) {
- log.error("[{}][{}] Exception during converting edge event to downlink msg", edge.getTenantId(), this.sessionId, e);
+ log.error("[{}][{}][{}] Failed to execute isSeqIdStartedNewCycle", this.tenantId, edge.getId(), sessionId, e);
}
- return downlinkMsg;
+ return false;
}
- private List convertToDownlinkMsgsPack(List edgeEvents) {
- return edgeEvents
- .stream()
- .map(this::convertToDownlinkMsg)
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
+ private boolean isNewEdgeEventsAvailable() {
+ try {
+ TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, this.newStartTs, System.currentTimeMillis());
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), this.newStartSeqId, null, pageLink);
+ return !edgeEvents.getData().isEmpty();
+ } catch (Exception e) {
+ log.error("[{}][{}][{}] Failed to execute isNewEdgeEventsAvailable", this.tenantId, edge.getId(), sessionId, e);
+ }
+ return false;
}
- private ListenableFuture getQueueStartTs() {
- ListenableFuture> future =
- ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, QUEUE_START_TS_ATTR_KEY);
- return Futures.transform(future, attributeKvEntryOpt -> {
- if (attributeKvEntryOpt != null && attributeKvEntryOpt.isPresent()) {
- AttributeKvEntry attributeKvEntry = attributeKvEntryOpt.get();
- return attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
- } else {
- return 0L;
+ private long findStartSeqIdFromOldestEventIfAny() {
+ long startSeqId = 0L;
+ try {
+ TimePageLink pageLink = new TimePageLink(1, 0, null, new SortOrder("createdTime"), null, null);
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), null, null, pageLink);
+ if (!edgeEvents.getData().isEmpty()) {
+ startSeqId = edgeEvents.getData().get(0).getSeqId() - 1;
}
- }, ctx.getGrpcCallbackExecutorService());
+ } catch (Exception e) {
+ log.error("[{}][{}][{}] Failed to execute findStartSeqIdFromOldestEventIfAny", this.tenantId, edge.getId(), sessionId, e);
+ }
+ return startSeqId;
}
- private ListenableFuture> updateQueueStartTs(Long newStartTs) {
- log.trace("[{}] updating QueueStartTs [{}][{}]", this.sessionId, edge.getId(), newStartTs);
- List attributes = Collections.singletonList(
- new BaseAttributeKvEntry(
- new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis()));
+ private ListenableFuture> updateQueueStartTsAndSeqId(Pair pair) {
+ this.newStartTs = pair.getFirst();
+ this.newStartSeqId = pair.getSecond();
+ log.trace("[{}] updateQueueStartTsAndSeqId [{}][{}][{}]", this.sessionId, edge.getId(), this.newStartTs, this.newStartSeqId);
+ List attributes = Arrays.asList(
+ new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, this.newStartTs), System.currentTimeMillis()),
+ new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_SEQ_ID_ATTR_KEY, this.newStartSeqId), System.currentTimeMillis()));
return ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes);
}
private DownlinkMsg convertEntityEventToDownlink(EdgeEvent edgeEvent) {
- log.trace("Executing convertEntityEventToDownlink, edgeEvent [{}], action [{}]", edgeEvent, edgeEvent.getAction());
+ log.trace("[{}] Executing convertEntityEventToDownlink, edgeEvent [{}], action [{}]", this.tenantId, edgeEvent, edgeEvent.getAction());
switch (edgeEvent.getType()) {
case EDGE:
return ctx.getEdgeProcessor().convertEdgeEventToDownlink(edgeEvent);
case DEVICE:
- return ctx.getDeviceProcessor().convertDeviceEventToDownlink(edgeEvent);
+ return ctx.getDeviceProcessor().convertDeviceEventToDownlink(edgeEvent, this.edge.getId(), this.edgeVersion);
case DEVICE_PROFILE:
- return ctx.getDeviceProfileProcessor().convertDeviceProfileEventToDownlink(edgeEvent);
+ return ctx.getDeviceProfileProcessor().convertDeviceProfileEventToDownlink(edgeEvent, this.edge.getId(), this.edgeVersion);
case ASSET_PROFILE:
- return ctx.getAssetProfileProcessor().convertAssetProfileEventToDownlink(edgeEvent);
+ return ctx.getAssetProfileProcessor().convertAssetProfileEventToDownlink(edgeEvent, this.edge.getId(), this.edgeVersion);
case ASSET:
- return ctx.getAssetProcessor().convertAssetEventToDownlink(edgeEvent);
+ return ctx.getAssetProcessor().convertAssetEventToDownlink(edgeEvent, this.edge.getId(), this.edgeVersion);
case ENTITY_VIEW:
- return ctx.getEntityViewProcessor().convertEntityViewEventToDownlink(edgeEvent);
+ return ctx.getEntityViewProcessor().convertEntityViewEventToDownlink(edgeEvent, this.edgeVersion);
case DASHBOARD:
- return ctx.getDashboardProcessor().convertDashboardEventToDownlink(edgeEvent);
+ return ctx.getDashboardProcessor().convertDashboardEventToDownlink(edgeEvent, this.edgeVersion);
case CUSTOMER:
- return ctx.getCustomerProcessor().convertCustomerEventToDownlink(edgeEvent);
+ return ctx.getCustomerProcessor().convertCustomerEventToDownlink(edgeEvent, this.edgeVersion);
case RULE_CHAIN:
- return ctx.getRuleChainProcessor().convertRuleChainEventToDownlink(edgeEvent);
+ return ctx.getRuleChainProcessor().convertRuleChainEventToDownlink(edgeEvent, this.edgeVersion);
case RULE_CHAIN_METADATA:
return ctx.getRuleChainProcessor().convertRuleChainMetadataEventToDownlink(edgeEvent, this.edgeVersion);
case ALARM:
- return ctx.getAlarmProcessor().convertAlarmEventToDownlink(edgeEvent);
+ return ctx.getAlarmProcessor().convertAlarmEventToDownlink(edgeEvent, this.edgeVersion);
case USER:
- return ctx.getUserProcessor().convertUserEventToDownlink(edgeEvent);
+ return ctx.getUserProcessor().convertUserEventToDownlink(edgeEvent, this.edgeVersion);
case RELATION:
- return ctx.getRelationProcessor().convertRelationEventToDownlink(edgeEvent);
+ return ctx.getRelationProcessor().convertRelationEventToDownlink(edgeEvent, this.edgeVersion);
case WIDGETS_BUNDLE:
- return ctx.getWidgetBundleProcessor().convertWidgetsBundleEventToDownlink(edgeEvent);
+ return ctx.getWidgetBundleProcessor().convertWidgetsBundleEventToDownlink(edgeEvent, this.edgeVersion);
case WIDGET_TYPE:
- return ctx.getWidgetTypeProcessor().convertWidgetTypeEventToDownlink(edgeEvent);
+ return ctx.getWidgetTypeProcessor().convertWidgetTypeEventToDownlink(edgeEvent, this.edgeVersion);
case ADMIN_SETTINGS:
- return ctx.getAdminSettingsProcessor().convertAdminSettingsEventToDownlink(edgeEvent);
+ return ctx.getAdminSettingsProcessor().convertAdminSettingsEventToDownlink(edgeEvent, this.edgeVersion);
case OTA_PACKAGE:
- return ctx.getOtaPackageEdgeProcessor().convertOtaPackageEventToDownlink(edgeEvent);
+ return ctx.getOtaPackageEdgeProcessor().convertOtaPackageEventToDownlink(edgeEvent, this.edgeVersion);
+ case TB_RESOURCE:
+ return ctx.getResourceEdgeProcessor().convertResourceEventToDownlink(edgeEvent, this.edgeVersion);
case QUEUE:
- return ctx.getQueueEdgeProcessor().convertQueueEventToDownlink(edgeEvent);
+ return ctx.getQueueEdgeProcessor().convertQueueEventToDownlink(edgeEvent, this.edgeVersion);
+ case TENANT:
+ return ctx.getTenantEdgeProcessor().convertTenantEventToDownlink(edgeEvent, this.edgeVersion);
+ case TENANT_PROFILE:
+ return ctx.getTenantProfileEdgeProcessor().convertTenantProfileEventToDownlink(edgeEvent, this.edgeVersion);
default:
- log.warn("Unsupported edge event type [{}]", edgeEvent);
+ log.warn("[{}] Unsupported edge event type [{}]", this.tenantId, edgeEvent);
return null;
}
}
@@ -580,24 +678,63 @@ public final class EdgeGrpcSession implements Closeable {
result.addAll(ctx.getTelemetryProcessor().processTelemetryMsg(edge.getTenantId(), entityData));
}
}
+ if (uplinkMsg.getDeviceProfileUpdateMsgCount() > 0) {
+ for (DeviceProfileUpdateMsg deviceProfileUpdateMsg : uplinkMsg.getDeviceProfileUpdateMsgList()) {
+ result.add(((DeviceProfileProcessor) ctx.getDeviceProfileEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processDeviceProfileMsgFromEdge(edge.getTenantId(), edge, deviceProfileUpdateMsg));
+ }
+ }
if (uplinkMsg.getDeviceUpdateMsgCount() > 0) {
for (DeviceUpdateMsg deviceUpdateMsg : uplinkMsg.getDeviceUpdateMsgList()) {
- result.add(ctx.getDeviceProcessor().processDeviceMsgFromEdge(edge.getTenantId(), edge, deviceUpdateMsg));
+ result.add(((DeviceProcessor) ctx.getDeviceEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processDeviceMsgFromEdge(edge.getTenantId(), edge, deviceUpdateMsg));
}
}
if (uplinkMsg.getDeviceCredentialsUpdateMsgCount() > 0) {
for (DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg : uplinkMsg.getDeviceCredentialsUpdateMsgList()) {
- result.add(ctx.getDeviceProcessor().processDeviceCredentialsMsg(edge.getTenantId(), deviceCredentialsUpdateMsg));
+ result.add(((DeviceProcessor) ctx.getDeviceEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processDeviceCredentialsMsgFromEdge(edge.getTenantId(), edge.getId(), deviceCredentialsUpdateMsg));
+ }
+ }
+ if (uplinkMsg.getAssetProfileUpdateMsgCount() > 0) {
+ for (AssetProfileUpdateMsg assetProfileUpdateMsg : uplinkMsg.getAssetProfileUpdateMsgList()) {
+ result.add(((AssetProfileProcessor) ctx.getAssetProfileEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processAssetProfileMsgFromEdge(edge.getTenantId(), edge, assetProfileUpdateMsg));
+ }
+ }
+ if (uplinkMsg.getAssetUpdateMsgCount() > 0) {
+ for (AssetUpdateMsg assetUpdateMsg : uplinkMsg.getAssetUpdateMsgList()) {
+ result.add(((AssetProcessor) ctx.getAssetEdgeProcessorFactory().getProcessorByEdgeVersion(edgeVersion))
+ .processAssetMsgFromEdge(edge.getTenantId(), edge, assetUpdateMsg));
}
}
if (uplinkMsg.getAlarmUpdateMsgCount() > 0) {
for (AlarmUpdateMsg alarmUpdateMsg : uplinkMsg.getAlarmUpdateMsgList()) {
- result.add(ctx.getAlarmProcessor().processAlarmMsg(edge.getTenantId(), alarmUpdateMsg));
+ result.add(((AlarmProcessor) ctx.getAlarmEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processAlarmMsgFromEdge(edge.getTenantId(), edge.getId(), alarmUpdateMsg));
+ }
+ }
+ if (uplinkMsg.getEntityViewUpdateMsgCount() > 0) {
+ for (EntityViewUpdateMsg entityViewUpdateMsg : uplinkMsg.getEntityViewUpdateMsgList()) {
+ result.add(((EntityViewProcessor) ctx.getEntityViewProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processEntityViewMsgFromEdge(edge.getTenantId(), edge, entityViewUpdateMsg));
}
}
if (uplinkMsg.getRelationUpdateMsgCount() > 0) {
for (RelationUpdateMsg relationUpdateMsg : uplinkMsg.getRelationUpdateMsgList()) {
- result.add(ctx.getRelationProcessor().processRelationMsg(edge.getTenantId(), relationUpdateMsg));
+ result.add(((RelationProcessor) ctx.getRelationEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processRelationMsgFromEdge(edge.getTenantId(), edge, relationUpdateMsg));
+ }
+ }
+ if (uplinkMsg.getDashboardUpdateMsgCount() > 0) {
+ for (DashboardUpdateMsg dashboardUpdateMsg : uplinkMsg.getDashboardUpdateMsgList()) {
+ result.add(((DashboardProcessor) ctx.getDashboardEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processDashboardMsgFromEdge(edge.getTenantId(), edge, dashboardUpdateMsg));
+ }
+ }
+ if (uplinkMsg.getResourceUpdateMsgCount() > 0) {
+ for (ResourceUpdateMsg resourceUpdateMsg : uplinkMsg.getResourceUpdateMsgList()) {
+ result.add(((ResourceProcessor) ctx.getResourceEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion)).processResourceMsgFromEdge(edge.getTenantId(), edge, resourceUpdateMsg));
}
}
if (uplinkMsg.getRuleChainMetadataRequestMsgCount() > 0) {
@@ -627,7 +764,8 @@ public final class EdgeGrpcSession implements Closeable {
}
if (uplinkMsg.getDeviceRpcCallMsgCount() > 0) {
for (DeviceRpcCallMsg deviceRpcCallMsg : uplinkMsg.getDeviceRpcCallMsgList()) {
- result.add(ctx.getDeviceProcessor().processDeviceRpcCallFromEdge(edge.getTenantId(), edge, deviceRpcCallMsg));
+ result.add(((DeviceProcessor) ctx.getDeviceEdgeProcessorFactory().getProcessorByEdgeVersion(this.edgeVersion))
+ .processDeviceRpcCallFromEdge(edge.getTenantId(), edge, deviceRpcCallMsg));
}
}
if (uplinkMsg.getWidgetBundleTypesRequestMsgCount() > 0) {
@@ -641,7 +779,7 @@ public final class EdgeGrpcSession implements Closeable {
}
}
} catch (Exception e) {
- log.error("[{}] Can't process uplink msg [{}]", this.sessionId, uplinkMsg, e);
+ log.error("[{}][{}] Can't process uplink msg [{}]", this.tenantId, this.sessionId, uplinkMsg, e);
return Futures.immediateFailedFuture(e);
}
return Futures.allAsList(result);
@@ -652,10 +790,12 @@ public final class EdgeGrpcSession implements Closeable {
Optional optional = ctx.getEdgeService().findEdgeByRoutingKey(TenantId.SYS_TENANT_ID, request.getEdgeRoutingKey());
if (optional.isPresent()) {
edge = optional.get();
+ this.tenantId = edge.getTenantId();
try {
if (edge.getSecret().equals(request.getEdgeSecret())) {
sessionOpenListener.accept(edge.getId(), this);
this.edgeVersion = request.getEdgeVersion();
+ processSaveEdgeVersionAsAttribute(request.getEdgeVersion().name());
return ConnectResponseMsg.newBuilder()
.setResponseCode(ConnectResponseCode.ACCEPTED)
.setErrorMsg("")
@@ -681,24 +821,32 @@ public final class EdgeGrpcSession implements Closeable {
.setConfiguration(EdgeConfiguration.getDefaultInstance()).build();
}
+ private void processSaveEdgeVersionAsAttribute(String edgeVersion) {
+ AttributeKvEntry attributeKvEntry = new BaseAttributeKvEntry(new StringDataEntry(DataConstants.EDGE_VERSION_ATTR_KEY, edgeVersion), System.currentTimeMillis());
+ ctx.getAttributesService().save(this.tenantId, this.edge.getId(), DataConstants.SERVER_SCOPE, attributeKvEntry);
+ }
+
@Override
public void close() {
- log.debug("[{}] Closing session", sessionId);
+ log.debug("[{}][{}] Closing session", this.tenantId, sessionId);
connected = false;
try {
outputStream.onCompleted();
} catch (Exception e) {
- log.debug("[{}] Failed to close output stream: {}", sessionId, e.getMessage());
+ log.debug("[{}][{}] Failed to close output stream: {}", this.tenantId, sessionId, e.getMessage());
}
}
private void interruptPreviousSendDownlinkMsgsTask() {
- log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", edge.getTenantId(), edge.getId(), this.sessionId);
- stopCurrentSendDownlinkMsgsTask(true);
+ if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()
+ || sessionState.getScheduledSendDownlinkTask() != null && !sessionState.getScheduledSendDownlinkTask().isCancelled()) {
+ log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", this.tenantId, edge.getId(), this.sessionId);
+ stopCurrentSendDownlinkMsgsTask(true);
+ }
}
private void interruptGeneralProcessingOnSync() {
- log.debug("[{}][{}][{}] Sync process started. General processing interrupted!", edge.getTenantId(), edge.getId(), this.sessionId);
+ log.debug("[{}][{}][{}] Sync process started. General processing interrupted!", this.tenantId, edge.getId(), this.sessionId);
stopCurrentSendDownlinkMsgsTask(true);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java
index bf3e804f7e..0fc5c93388 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java
@@ -25,6 +25,7 @@ import org.thingsboard.server.service.edge.rpc.fetch.AssetsEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.CustomerEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.CustomerUsersEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.DashboardsEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.fetch.DefaultProfilesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.DeviceProfilesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.DevicesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.EdgeEventFetcher;
@@ -32,8 +33,12 @@ import org.thingsboard.server.service.edge.rpc.fetch.EntityViewsEdgeEventFetcher
import org.thingsboard.server.service.edge.rpc.fetch.OtaPackagesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.QueuesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.RuleChainsEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.fetch.SystemWidgetTypesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.SystemWidgetsBundlesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.TenantAdminUsersEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.fetch.TenantEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.fetch.TenantResourcesEdgeEventFetcher;
+import org.thingsboard.server.service.edge.rpc.fetch.TenantWidgetTypesEdgeEventFetcher;
import org.thingsboard.server.service.edge.rpc.fetch.TenantWidgetsBundlesEdgeEventFetcher;
import java.util.LinkedList;
@@ -48,11 +53,10 @@ public class EdgeSyncCursor {
public EdgeSyncCursor(EdgeContextComponent ctx, Edge edge, boolean fullSync) {
if (fullSync) {
+ fetchers.add(new TenantEdgeEventFetcher(ctx.getTenantService()));
fetchers.add(new QueuesEdgeEventFetcher(ctx.getQueueService()));
fetchers.add(new RuleChainsEdgeEventFetcher(ctx.getRuleChainService()));
- fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService(), ctx.getFreemarkerConfig()));
- fetchers.add(new DeviceProfilesEdgeEventFetcher(ctx.getDeviceProfileService()));
- fetchers.add(new AssetProfilesEdgeEventFetcher(ctx.getAssetProfileService()));
+ fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService()));
fetchers.add(new TenantAdminUsersEdgeEventFetcher(ctx.getUserService()));
Customer publicCustomer = ctx.getCustomerService().findOrCreatePublicCustomer(edge.getTenantId());
fetchers.add(new CustomerEdgeEventFetcher(publicCustomer.getId()));
@@ -61,14 +65,20 @@ public class EdgeSyncCursor {
fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId()));
}
}
+ fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService()));
+ fetchers.add(new DefaultProfilesEdgeEventFetcher(ctx.getDeviceProfileService(), ctx.getAssetProfileService()));
+ fetchers.add(new DeviceProfilesEdgeEventFetcher(ctx.getDeviceProfileService()));
+ fetchers.add(new AssetProfilesEdgeEventFetcher(ctx.getAssetProfileService()));
fetchers.add(new DevicesEdgeEventFetcher(ctx.getDeviceService()));
fetchers.add(new AssetsEdgeEventFetcher(ctx.getAssetService()));
fetchers.add(new EntityViewsEdgeEventFetcher(ctx.getEntityViewService()));
- fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService()));
if (fullSync) {
+ fetchers.add(new SystemWidgetTypesEdgeEventFetcher(ctx.getWidgetTypeService()));
+ fetchers.add(new TenantWidgetTypesEdgeEventFetcher(ctx.getWidgetTypeService()));
fetchers.add(new SystemWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new TenantWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new OtaPackagesEdgeEventFetcher(ctx.getOtaPackageService()));
+ fetchers.add(new TenantResourcesEdgeEventFetcher(ctx.getResourceService()));
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java
deleted file mode 100644
index 79754b867c..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsMsgConstructor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.AdminSettings;
-import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class AdminSettingsMsgConstructor {
-
- public AdminSettingsUpdateMsg constructAdminSettingsUpdateMsg(AdminSettings adminSettings) {
- AdminSettingsUpdateMsg.Builder builder = AdminSettingsUpdateMsg.newBuilder()
- .setKey(adminSettings.getKey())
- .setJsonValue(JacksonUtil.toString(adminSettings.getJsonValue()));
- if (adminSettings.getId() != null) {
- builder.setIsSystem(true);
- }
- return builder.build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java
deleted file mode 100644
index 69a83da0a0..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.alarm.Alarm;
-import org.thingsboard.server.common.data.id.AssetId;
-import org.thingsboard.server.common.data.id.DeviceId;
-import org.thingsboard.server.common.data.id.EntityViewId;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.dao.asset.AssetService;
-import org.thingsboard.server.dao.device.DeviceService;
-import org.thingsboard.server.dao.entityview.EntityViewService;
-import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class AlarmMsgConstructor {
-
- @Autowired
- private DeviceService deviceService;
-
- @Autowired
- private AssetService assetService;
-
- @Autowired
- private EntityViewService entityViewService;
-
- public AlarmUpdateMsg constructAlarmUpdatedMsg(TenantId tenantId, UpdateMsgType msgType, Alarm alarm) {
- String entityName = null;
- switch (alarm.getOriginator().getEntityType()) {
- case DEVICE:
- entityName = deviceService.findDeviceById(tenantId, new DeviceId(alarm.getOriginator().getId())).getName();
- break;
- case ASSET:
- entityName = assetService.findAssetById(tenantId, new AssetId(alarm.getOriginator().getId())).getName();
- break;
- case ENTITY_VIEW:
- entityName = entityViewService.findEntityViewById(tenantId, new EntityViewId(alarm.getOriginator().getId())).getName();
- break;
- }
- AlarmUpdateMsg.Builder builder = AlarmUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(alarm.getId().getId().getMostSignificantBits())
- .setIdLSB(alarm.getId().getId().getLeastSignificantBits())
- .setName(alarm.getName())
- .setType(alarm.getType())
- .setOriginatorName(entityName)
- .setOriginatorType(alarm.getOriginator().getEntityType().name())
- .setSeverity(alarm.getSeverity().name())
- .setStatus(alarm.getStatus().name())
- .setStartTs(alarm.getStartTs())
- .setEndTs(alarm.getEndTs())
- .setAckTs(alarm.getAckTs())
- .setClearTs(alarm.getClearTs())
- .setDetails(JacksonUtil.toString(alarm.getDetails()))
- .setPropagate(alarm.isPropagate())
- .setPropagateToOwner(alarm.isPropagateToOwner())
- .setPropagateToTenant(alarm.isPropagateToTenant());
- return builder.build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java
deleted file mode 100644
index 86ffc6dd5c..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetMsgConstructor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.asset.Asset;
-import org.thingsboard.server.common.data.id.AssetId;
-import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class AssetMsgConstructor {
-
- public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset) {
- AssetUpdateMsg.Builder builder = AssetUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(asset.getUuidId().getMostSignificantBits())
- .setIdLSB(asset.getUuidId().getLeastSignificantBits())
- .setName(asset.getName())
- .setType(asset.getType());
- if (asset.getLabel() != null) {
- builder.setLabel(asset.getLabel());
- }
- if (asset.getCustomerId() != null) {
- builder.setCustomerIdMSB(asset.getCustomerId().getId().getMostSignificantBits());
- builder.setCustomerIdLSB(asset.getCustomerId().getId().getLeastSignificantBits());
- }
- if (asset.getAssetProfileId() != null) {
- builder.setAssetProfileIdMSB(asset.getAssetProfileId().getId().getMostSignificantBits());
- builder.setAssetProfileIdLSB(asset.getAssetProfileId().getId().getLeastSignificantBits());
- }
- if (asset.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(asset.getAdditionalInfo()));
- }
- return builder.build();
- }
-
- public AssetUpdateMsg constructAssetDeleteMsg(AssetId assetId) {
- return AssetUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(assetId.getId().getMostSignificantBits())
- .setIdLSB(assetId.getId().getLeastSignificantBits()).build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetProfileMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetProfileMsgConstructor.java
deleted file mode 100644
index f5b921a32b..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AssetProfileMsgConstructor.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.google.protobuf.ByteString;
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.asset.AssetProfile;
-import org.thingsboard.server.common.data.id.AssetProfileId;
-import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-import java.nio.charset.StandardCharsets;
-
-@Component
-@TbCoreComponent
-public class AssetProfileMsgConstructor {
-
- public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) {
- AssetProfileUpdateMsg.Builder builder = AssetProfileUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(assetProfile.getId().getId().getMostSignificantBits())
- .setIdLSB(assetProfile.getId().getId().getLeastSignificantBits())
- .setName(assetProfile.getName())
- .setDefault(assetProfile.isDefault());
- if (assetProfile.getDefaultDashboardId() != null) {
- builder.setDefaultDashboardIdMSB(assetProfile.getDefaultDashboardId().getId().getMostSignificantBits())
- .setDefaultDashboardIdLSB(assetProfile.getDefaultDashboardId().getId().getLeastSignificantBits());
- }
- if (assetProfile.getDefaultQueueName() != null) {
- builder.setDefaultQueueName(assetProfile.getDefaultQueueName());
- }
- if (assetProfile.getDescription() != null) {
- builder.setDescription(assetProfile.getDescription());
- }
- if (assetProfile.getImage() != null) {
- builder.setImage(ByteString.copyFrom(assetProfile.getImage().getBytes(StandardCharsets.UTF_8)));
- }
- if (assetProfile.getDefaultEdgeRuleChainId() != null) {
- builder.setDefaultRuleChainIdMSB(assetProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits())
- .setDefaultRuleChainIdLSB(assetProfile.getDefaultEdgeRuleChainId().getId().getLeastSignificantBits());
- }
- return builder.build();
- }
-
- public AssetProfileUpdateMsg constructAssetProfileDeleteMsg(AssetProfileId assetProfileId) {
- return AssetProfileUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(assetProfileId.getId().getMostSignificantBits())
- .setIdLSB(assetProfileId.getId().getLeastSignificantBits()).build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/BaseMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/BaseMsgConstructorFactory.java
new file mode 100644
index 0000000000..e0982e3fba
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/BaseMsgConstructorFactory.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2016-2023 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.constructor;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.gen.edge.v1.EdgeVersion;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public abstract class BaseMsgConstructorFactory {
+
+ @Autowired
+ protected T v1Constructor;
+
+ @Autowired
+ protected U v2Constructor;
+
+ public MsgConstructor getMsgConstructorByEdgeVersion(EdgeVersion edgeVersion) {
+ switch (edgeVersion) {
+ case V_3_3_0:
+ case V_3_3_3:
+ case V_3_4_0:
+ case V_3_6_0:
+ case V_3_6_1:
+ return v1Constructor;
+ case V_3_6_2:
+ default:
+ return v2Constructor;
+ }
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java
deleted file mode 100644
index 0465dd5a94..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerMsgConstructor.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.Customer;
-import org.thingsboard.server.common.data.id.CustomerId;
-import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class CustomerMsgConstructor {
-
- public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) {
- CustomerUpdateMsg.Builder builder = CustomerUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(customer.getId().getId().getMostSignificantBits())
- .setIdLSB(customer.getId().getId().getLeastSignificantBits())
- .setTitle(customer.getTitle());
- if (customer.getCountry() != null) {
- builder.setCountry(customer.getCountry());
- }
- if (customer.getState() != null) {
- builder.setState(customer.getState());
- }
- if (customer.getCity() != null) {
- builder.setCity(customer.getCity());
- }
- if (customer.getAddress() != null) {
- builder.setAddress(customer.getAddress());
- }
- if (customer.getAddress2() != null) {
- builder.setAddress2(customer.getAddress2());
- }
- if (customer.getZip() != null) {
- builder.setZip(customer.getZip());
- }
- if (customer.getPhone() != null) {
- builder.setPhone(customer.getPhone());
- }
- if (customer.getEmail() != null) {
- builder.setEmail(customer.getEmail());
- }
- if (customer.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(customer.getAdditionalInfo()));
- }
- return builder.build();
- }
-
- public CustomerUpdateMsg constructCustomerDeleteMsg(CustomerId customerId) {
- return CustomerUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(customerId.getId().getMostSignificantBits())
- .setIdLSB(customerId.getId().getLeastSignificantBits()).build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java
deleted file mode 100644
index edfdefb603..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DashboardMsgConstructor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.Dashboard;
-import org.thingsboard.server.common.data.id.DashboardId;
-import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class DashboardMsgConstructor {
-
- public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) {
- DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(dashboard.getId().getId().getMostSignificantBits())
- .setIdLSB(dashboard.getId().getId().getLeastSignificantBits())
- .setTitle(dashboard.getTitle())
- .setConfiguration(JacksonUtil.toString(dashboard.getConfiguration()));
- if (dashboard.getAssignedCustomers() != null) {
- builder.setAssignedCustomers(JacksonUtil.toString(dashboard.getAssignedCustomers()));
- }
- return builder.build();
- }
-
- public DashboardUpdateMsg constructDashboardDeleteMsg(DashboardId dashboardId) {
- return DashboardUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(dashboardId.getId().getMostSignificantBits())
- .setIdLSB(dashboardId.getId().getLeastSignificantBits()).build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java
deleted file mode 100644
index 78b785a5d8..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.google.protobuf.ByteString;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.Device;
-import org.thingsboard.server.common.data.id.DeviceId;
-import org.thingsboard.server.common.data.security.DeviceCredentials;
-import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
-import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.RpcRequestMsg;
-import org.thingsboard.server.gen.edge.v1.RpcResponseMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.DataDecodingEncodingService;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-import java.util.UUID;
-
-@Component
-@TbCoreComponent
-public class DeviceMsgConstructor {
-
- @Autowired
- private DataDecodingEncodingService dataDecodingEncodingService;
-
- public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) {
- DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(device.getId().getId().getMostSignificantBits())
- .setIdLSB(device.getId().getId().getLeastSignificantBits())
- .setName(device.getName())
- .setType(device.getType());
- if (device.getLabel() != null) {
- builder.setLabel(device.getLabel());
- }
- if (device.getCustomerId() != null) {
- builder.setCustomerIdMSB(device.getCustomerId().getId().getMostSignificantBits());
- builder.setCustomerIdLSB(device.getCustomerId().getId().getLeastSignificantBits());
- }
- if (device.getDeviceProfileId() != null) {
- builder.setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits());
- builder.setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits());
- }
- if (device.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo()));
- }
- if (device.getFirmwareId() != null) {
- builder.setFirmwareIdMSB(device.getFirmwareId().getId().getMostSignificantBits())
- .setFirmwareIdLSB(device.getFirmwareId().getId().getLeastSignificantBits());
- }
- if (device.getSoftwareId() != null) {
- builder.setSoftwareIdMSB(device.getSoftwareId().getId().getMostSignificantBits())
- .setSoftwareIdLSB(device.getSoftwareId().getId().getLeastSignificantBits());
- }
- if (device.getDeviceData() != null) {
- builder.setDeviceDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(device.getDeviceData())));
- }
- return builder.build();
- }
-
- public DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials) {
- DeviceCredentialsUpdateMsg.Builder builder = DeviceCredentialsUpdateMsg.newBuilder()
- .setDeviceIdMSB(deviceCredentials.getDeviceId().getId().getMostSignificantBits())
- .setDeviceIdLSB(deviceCredentials.getDeviceId().getId().getLeastSignificantBits());
- if (deviceCredentials.getCredentialsType() != null) {
- builder.setCredentialsType(deviceCredentials.getCredentialsType().name())
- .setCredentialsId(deviceCredentials.getCredentialsId());
- }
- if (deviceCredentials.getCredentialsValue() != null) {
- builder.setCredentialsValue(deviceCredentials.getCredentialsValue());
- }
- return builder.build();
- }
-
- public DeviceUpdateMsg constructDeviceDeleteMsg(DeviceId deviceId) {
- return DeviceUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(deviceId.getId().getMostSignificantBits())
- .setIdLSB(deviceId.getId().getLeastSignificantBits()).build();
- }
-
- public DeviceRpcCallMsg constructDeviceRpcCallMsg(UUID deviceId, JsonNode body) {
- DeviceRpcCallMsg.Builder builder = constructDeviceRpcMsg(deviceId, body);
- if (body.has("error") || body.has("response")) {
- RpcResponseMsg.Builder responseBuilder = RpcResponseMsg.newBuilder();
- if (body.has("error")) {
- responseBuilder.setError(body.get("error").asText());
- } else {
- responseBuilder.setResponse(body.get("response").asText());
- }
- builder.setResponseMsg(responseBuilder.build());
- } else {
- RpcRequestMsg.Builder requestBuilder = RpcRequestMsg.newBuilder();
- requestBuilder.setMethod(body.get("method").asText());
- requestBuilder.setParams(body.get("params").asText());
- builder.setRequestMsg(requestBuilder.build());
- }
- return builder.build();
- }
-
- private DeviceRpcCallMsg.Builder constructDeviceRpcMsg(UUID deviceId, JsonNode body) {
- DeviceRpcCallMsg.Builder builder = DeviceRpcCallMsg.newBuilder()
- .setDeviceIdMSB(deviceId.getMostSignificantBits())
- .setDeviceIdLSB(deviceId.getLeastSignificantBits())
- .setRequestId(body.get("requestId").asInt());
- if (body.get("oneway") != null) {
- builder.setOneway(body.get("oneway").asBoolean());
- }
- if (body.get("requestUUID") != null) {
- UUID requestUUID = UUID.fromString(body.get("requestUUID").asText());
- builder.setRequestUuidMSB(requestUUID.getMostSignificantBits())
- .setRequestUuidLSB(requestUUID.getLeastSignificantBits());
- }
- if (body.get("expirationTime") != null) {
- builder.setExpirationTime(body.get("expirationTime").asLong());
- }
- if (body.get("persisted") != null) {
- builder.setPersisted(body.get("persisted").asBoolean());
- }
- if (body.get("retries") != null) {
- builder.setRetries(body.get("retries").asInt());
- }
- if (body.get("additionalInfo") != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(body.get("additionalInfo")));
- }
- if (body.get("serviceId") != null) {
- builder.setServiceId(body.get("serviceId").asText());
- }
- if (body.get("sessionId") != null) {
- builder.setSessionId(body.get("sessionId").asText());
- }
- return builder;
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceProfileMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceProfileMsgConstructor.java
deleted file mode 100644
index d8e19ee854..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceProfileMsgConstructor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.google.protobuf.ByteString;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.DeviceProfile;
-import org.thingsboard.server.common.data.id.DeviceProfileId;
-import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.DataDecodingEncodingService;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-import java.nio.charset.StandardCharsets;
-
-@Component
-@TbCoreComponent
-public class DeviceProfileMsgConstructor {
-
- @Autowired
- private DataDecodingEncodingService dataDecodingEncodingService;
-
- public DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile) {
- DeviceProfileUpdateMsg.Builder builder = DeviceProfileUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(deviceProfile.getId().getId().getMostSignificantBits())
- .setIdLSB(deviceProfile.getId().getId().getLeastSignificantBits())
- .setName(deviceProfile.getName())
- .setDefault(deviceProfile.isDefault())
- .setType(deviceProfile.getType().name())
- .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData())));
- if (deviceProfile.getDefaultQueueName() != null) {
- builder.setDefaultQueueName(deviceProfile.getDefaultQueueName());
- }
- if (deviceProfile.getDescription() != null) {
- builder.setDescription(deviceProfile.getDescription());
- }
- if (deviceProfile.getTransportType() != null) {
- builder.setTransportType(deviceProfile.getTransportType().name());
- }
- if (deviceProfile.getProvisionType() != null) {
- builder.setProvisionType(deviceProfile.getProvisionType().name());
- }
- if (deviceProfile.getProvisionDeviceKey() != null) {
- builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey());
- }
- if (deviceProfile.getImage() != null) {
- builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8)));
- }
- if (deviceProfile.getFirmwareId() != null) {
- builder.setFirmwareIdMSB(deviceProfile.getFirmwareId().getId().getMostSignificantBits())
- .setFirmwareIdLSB(deviceProfile.getFirmwareId().getId().getLeastSignificantBits());
- }
- if (deviceProfile.getSoftwareId() != null) {
- builder.setSoftwareIdMSB(deviceProfile.getSoftwareId().getId().getMostSignificantBits())
- .setSoftwareIdLSB(deviceProfile.getSoftwareId().getId().getLeastSignificantBits());
- }
- if (deviceProfile.getDefaultEdgeRuleChainId() != null) {
- builder.setDefaultRuleChainIdMSB(deviceProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits())
- .setDefaultRuleChainIdLSB(deviceProfile.getDefaultEdgeRuleChainId().getId().getLeastSignificantBits());
- }
- if (deviceProfile.getDefaultDashboardId() != null) {
- builder.setDefaultDashboardIdMSB(deviceProfile.getDefaultDashboardId().getId().getMostSignificantBits())
- .setDefaultDashboardIdLSB(deviceProfile.getDefaultDashboardId().getId().getLeastSignificantBits());
- }
- return builder.build();
- }
-
- public DeviceProfileUpdateMsg constructDeviceProfileDeleteMsg(DeviceProfileId deviceProfileId) {
- return DeviceProfileUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(deviceProfileId.getId().getMostSignificantBits())
- .setIdLSB(deviceProfileId.getId().getLeastSignificantBits()).build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EdgeMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EdgeMsgConstructor.java
deleted file mode 100644
index 3416240b2c..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EdgeMsgConstructor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.edge.Edge;
-import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class EdgeMsgConstructor {
-
- public EdgeConfiguration constructEdgeConfiguration(Edge edge) {
- EdgeConfiguration.Builder builder = EdgeConfiguration.newBuilder()
- .setEdgeIdMSB(edge.getId().getId().getMostSignificantBits())
- .setEdgeIdLSB(edge.getId().getId().getLeastSignificantBits())
- .setTenantIdMSB(edge.getTenantId().getId().getMostSignificantBits())
- .setTenantIdLSB(edge.getTenantId().getId().getLeastSignificantBits())
- .setName(edge.getName())
- .setType(edge.getType())
- .setRoutingKey(edge.getRoutingKey())
- .setSecret(edge.getSecret())
- .setAdditionalInfo(JacksonUtil.toString(edge.getAdditionalInfo()))
- .setCloudType("CE");
- if (edge.getCustomerId() != null) {
- builder.setCustomerIdMSB(edge.getCustomerId().getId().getMostSignificantBits())
- .setCustomerIdLSB(edge.getCustomerId().getId().getLeastSignificantBits());
- }
- return builder.build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java
deleted file mode 100644
index 242a15ba56..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.reflect.TypeToken;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.DataConstants;
-import org.thingsboard.server.common.data.StringUtils;
-import org.thingsboard.server.common.data.edge.EdgeEventActionType;
-import org.thingsboard.server.common.data.id.EntityId;
-import org.thingsboard.server.common.transport.adaptor.JsonConverter;
-import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg;
-import org.thingsboard.server.gen.edge.v1.EntityDataProto;
-import org.thingsboard.server.gen.transport.TransportProtos;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-import java.util.List;
-
-@Component
-@Slf4j
-@TbCoreComponent
-public class EntityDataMsgConstructor {
-
- public EntityDataProto constructEntityDataMsg(EntityId entityId, EdgeEventActionType actionType, JsonElement entityData) {
- EntityDataProto.Builder builder = EntityDataProto.newBuilder()
- .setEntityIdMSB(entityId.getId().getMostSignificantBits())
- .setEntityIdLSB(entityId.getId().getLeastSignificantBits())
- .setEntityType(entityId.getEntityType().name());
- switch (actionType) {
- case TIMESERIES_UPDATED:
- try {
- JsonObject data = entityData.getAsJsonObject();
- long ts;
- if (data.get("ts") != null && !data.get("ts").isJsonNull()) {
- ts = data.getAsJsonPrimitive("ts").getAsLong();
- } else {
- ts = System.currentTimeMillis();
- }
- builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts));
- } catch (Exception e) {
- log.warn("[{}] Can't convert to telemetry proto, entityData [{}]", entityId, entityData, e);
- }
- break;
- case ATTRIBUTES_UPDATED:
- try {
- JsonObject data = entityData.getAsJsonObject();
- TransportProtos.PostAttributeMsg attributesUpdatedMsg = JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"));
- builder.setAttributesUpdatedMsg(attributesUpdatedMsg);
- builder.setPostAttributeScope(getScopeOfDefault(data));
- } catch (Exception e) {
- log.warn("[{}] Can't convert to AttributesUpdatedMsg proto, entityData [{}]", entityId, entityData, e);
- }
- break;
- case POST_ATTRIBUTES:
- try {
- JsonObject data = entityData.getAsJsonObject();
- TransportProtos.PostAttributeMsg postAttributesMsg = JsonConverter.convertToAttributesProto(data.getAsJsonObject("kv"));
- builder.setPostAttributesMsg(postAttributesMsg);
- builder.setPostAttributeScope(getScopeOfDefault(data));
- } catch (Exception e) {
- log.warn("[{}] Can't convert to PostAttributesMsg, entityData [{}]", entityId, entityData, e);
- }
- break;
- case ATTRIBUTES_DELETED:
- try {
- AttributeDeleteMsg.Builder attributeDeleteMsg = AttributeDeleteMsg.newBuilder();
- attributeDeleteMsg.setScope(entityData.getAsJsonObject().getAsJsonPrimitive("scope").getAsString());
- JsonArray jsonArray = entityData.getAsJsonObject().getAsJsonArray("keys");
- List keys = new Gson().fromJson(jsonArray.toString(), new TypeToken<>(){}.getType());
- attributeDeleteMsg.addAllAttributeNames(keys);
- attributeDeleteMsg.build();
- builder.setAttributeDeleteMsg(attributeDeleteMsg);
- } catch (Exception e) {
- log.warn("[{}] Can't convert to AttributeDeleteMsg proto, entityData [{}]", entityId, entityData, e);
- }
- break;
- }
- return builder.build();
- }
-
- private String getScopeOfDefault(JsonObject data) {
- JsonPrimitive scope = data.getAsJsonPrimitive("scope");
- String result = DataConstants.SERVER_SCOPE;
- if (scope != null && StringUtils.isNotBlank(scope.getAsString())) {
- result = scope.getAsString();
- }
- return result;
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java
deleted file mode 100644
index 235199d75e..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityViewMsgConstructor.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.EntityView;
-import org.thingsboard.server.common.data.id.EntityViewId;
-import org.thingsboard.server.gen.edge.v1.EdgeEntityType;
-import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class EntityViewMsgConstructor {
-
- public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView) {
- EdgeEntityType entityType;
- switch (entityView.getEntityId().getEntityType()) {
- case DEVICE:
- entityType = EdgeEntityType.DEVICE;
- break;
- case ASSET:
- entityType = EdgeEntityType.ASSET;
- break;
- default:
- throw new RuntimeException("Unsupported entity type [" + entityView.getEntityId().getEntityType() + "]");
- }
- EntityViewUpdateMsg.Builder builder = EntityViewUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(entityView.getId().getId().getMostSignificantBits())
- .setIdLSB(entityView.getId().getId().getLeastSignificantBits())
- .setName(entityView.getName())
- .setType(entityView.getType())
- .setEntityIdMSB(entityView.getEntityId().getId().getMostSignificantBits())
- .setEntityIdLSB(entityView.getEntityId().getId().getLeastSignificantBits())
- .setEntityType(entityType);
- if (entityView.getCustomerId() != null) {
- builder.setCustomerIdMSB(entityView.getCustomerId().getId().getMostSignificantBits());
- builder.setCustomerIdLSB(entityView.getCustomerId().getId().getLeastSignificantBits());
- }
- if (entityView.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(entityView.getAdditionalInfo()));
- }
- return builder.build();
- }
-
- public EntityViewUpdateMsg constructEntityViewDeleteMsg(EntityViewId entityViewId) {
- return EntityViewUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(entityViewId.getId().getMostSignificantBits())
- .setIdLSB(entityViewId.getId().getLeastSignificantBits()).build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/MsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/MsgConstructor.java
new file mode 100644
index 0000000000..071f2bc25d
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/MsgConstructor.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright © 2016-2023 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.constructor;
+
+public interface MsgConstructor {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/OtaPackageMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/OtaPackageMsgConstructor.java
deleted file mode 100644
index 253305a5ab..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/OtaPackageMsgConstructor.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.google.protobuf.ByteString;
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.OtaPackage;
-import org.thingsboard.server.common.data.id.OtaPackageId;
-import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class OtaPackageMsgConstructor {
-
- public OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage) {
- OtaPackageUpdateMsg.Builder builder = OtaPackageUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(otaPackage.getId().getId().getMostSignificantBits())
- .setIdLSB(otaPackage.getId().getId().getLeastSignificantBits())
- .setType(otaPackage.getType().name())
- .setTitle(otaPackage.getTitle())
- .setVersion(otaPackage.getVersion())
- .setTag(otaPackage.getTag());
-
- if (otaPackage.getDeviceProfileId() != null) {
- builder.setDeviceProfileIdMSB(otaPackage.getDeviceProfileId().getId().getMostSignificantBits())
- .setDeviceProfileIdLSB(otaPackage.getDeviceProfileId().getId().getLeastSignificantBits());
- }
-
- if (otaPackage.getUrl() != null) {
- builder.setUrl(otaPackage.getUrl());
- }
- if (otaPackage.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(otaPackage.getAdditionalInfo()));
- }
- if (otaPackage.getFileName() != null) {
- builder.setFileName(otaPackage.getFileName());
- }
- if (otaPackage.getContentType() != null) {
- builder.setContentType(otaPackage.getContentType());
- }
- if (otaPackage.getChecksumAlgorithm() != null) {
- builder.setChecksumAlgorithm(otaPackage.getChecksumAlgorithm().name());
- }
- if (otaPackage.getChecksum() != null) {
- builder.setChecksum(otaPackage.getChecksum());
- }
- if (otaPackage.getDataSize() != null) {
- builder.setDataSize(otaPackage.getDataSize());
- }
- if (otaPackage.getData() != null) {
- builder.setData(ByteString.copyFrom(otaPackage.getData().array()));
- }
- return builder.build();
- }
-
- public OtaPackageUpdateMsg constructOtaPackageDeleteMsg(OtaPackageId otaPackageId) {
- return OtaPackageUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(otaPackageId.getId().getMostSignificantBits())
- .setIdLSB(otaPackageId.getId().getLeastSignificantBits()).build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/QueueMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/QueueMsgConstructor.java
deleted file mode 100644
index 2644a5409b..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/QueueMsgConstructor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.id.QueueId;
-import org.thingsboard.server.common.data.queue.ProcessingStrategy;
-import org.thingsboard.server.common.data.queue.Queue;
-import org.thingsboard.server.common.data.queue.SubmitStrategy;
-import org.thingsboard.server.gen.edge.v1.ProcessingStrategyProto;
-import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.SubmitStrategyProto;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class QueueMsgConstructor {
-
- public QueueUpdateMsg constructQueueUpdatedMsg(UpdateMsgType msgType, Queue queue) {
- QueueUpdateMsg.Builder builder = QueueUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(queue.getId().getId().getMostSignificantBits())
- .setIdLSB(queue.getId().getId().getLeastSignificantBits())
- .setTenantIdMSB(queue.getTenantId().getId().getMostSignificantBits())
- .setTenantIdLSB(queue.getTenantId().getId().getLeastSignificantBits())
- .setName(queue.getName())
- .setTopic(queue.getTopic())
- .setPollInterval(queue.getPollInterval())
- .setPartitions(queue.getPartitions())
- .setConsumerPerPartition(queue.isConsumerPerPartition())
- .setPackProcessingTimeout(queue.getPackProcessingTimeout())
- .setSubmitStrategy(createSubmitStrategyProto(queue.getSubmitStrategy()))
- .setProcessingStrategy(createProcessingStrategyProto(queue.getProcessingStrategy()));
- return builder.build();
- }
-
- private ProcessingStrategyProto createProcessingStrategyProto(ProcessingStrategy processingStrategy) {
- return ProcessingStrategyProto.newBuilder()
- .setType(processingStrategy.getType().name())
- .setRetries(processingStrategy.getRetries())
- .setFailurePercentage(processingStrategy.getFailurePercentage())
- .setPauseBetweenRetries(processingStrategy.getPauseBetweenRetries())
- .setMaxPauseBetweenRetries(processingStrategy.getMaxPauseBetweenRetries())
- .build();
- }
-
- private SubmitStrategyProto createSubmitStrategyProto(SubmitStrategy submitStrategy) {
- return SubmitStrategyProto.newBuilder()
- .setType(submitStrategy.getType().name())
- .setBatchSize(submitStrategy.getBatchSize())
- .build();
- }
-
- public QueueUpdateMsg constructQueueDeleteMsg(QueueId queueId) {
- return QueueUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(queueId.getId().getMostSignificantBits())
- .setIdLSB(queueId.getId().getLeastSignificantBits()).build();
- }
-
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java
deleted file mode 100644
index 24786a4f7c..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RelationMsgConstructor.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.relation.EntityRelation;
-import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class RelationMsgConstructor {
-
- public RelationUpdateMsg constructRelationUpdatedMsg(UpdateMsgType msgType, EntityRelation entityRelation) {
- RelationUpdateMsg.Builder builder = RelationUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setFromIdMSB(entityRelation.getFrom().getId().getMostSignificantBits())
- .setFromIdLSB(entityRelation.getFrom().getId().getLeastSignificantBits())
- .setFromEntityType(entityRelation.getFrom().getEntityType().name())
- .setToIdMSB(entityRelation.getTo().getId().getMostSignificantBits())
- .setToIdLSB(entityRelation.getTo().getId().getLeastSignificantBits())
- .setToEntityType(entityRelation.getTo().getEntityType().name())
- .setType(entityRelation.getType());
- if (entityRelation.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(entityRelation.getAdditionalInfo()));
- }
- if (entityRelation.getTypeGroup() != null) {
- builder.setTypeGroup(entityRelation.getTypeGroup().name());
- }
- return builder.build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java
deleted file mode 100644
index 8f91f5d19e..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructor.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.id.RuleChainId;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.common.data.rule.RuleChain;
-import org.thingsboard.server.common.data.rule.RuleChainMetaData;
-import org.thingsboard.server.gen.edge.v1.EdgeVersion;
-import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMetadataConstructor;
-import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMetadataConstructorFactory;
-
-@Component
-@Slf4j
-@TbCoreComponent
-public class RuleChainMsgConstructor {
-
- public RuleChainUpdateMsg constructRuleChainUpdatedMsg(UpdateMsgType msgType, RuleChain ruleChain, boolean isRoot) {
- RuleChainUpdateMsg.Builder builder = RuleChainUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(ruleChain.getId().getId().getMostSignificantBits())
- .setIdLSB(ruleChain.getId().getId().getLeastSignificantBits())
- .setName(ruleChain.getName())
- .setRoot(isRoot)
- .setDebugMode(ruleChain.isDebugMode())
- .setConfiguration(JacksonUtil.toString(ruleChain.getConfiguration()));
- if (ruleChain.getFirstRuleNodeId() != null) {
- builder.setFirstRuleNodeIdMSB(ruleChain.getFirstRuleNodeId().getId().getMostSignificantBits())
- .setFirstRuleNodeIdLSB(ruleChain.getFirstRuleNodeId().getId().getLeastSignificantBits());
- }
- return builder.build();
- }
-
- public RuleChainMetadataUpdateMsg constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
- UpdateMsgType msgType,
- RuleChainMetaData ruleChainMetaData,
- EdgeVersion edgeVersion) {
- RuleChainMetadataConstructor ruleChainMetadataConstructor
- = RuleChainMetadataConstructorFactory.getByEdgeVersion(edgeVersion);
- return ruleChainMetadataConstructor.constructRuleChainMetadataUpdatedMsg(tenantId, msgType, ruleChainMetaData);
- }
-
- public RuleChainUpdateMsg constructRuleChainDeleteMsg(RuleChainId ruleChainId) {
- return RuleChainUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(ruleChainId.getId().getMostSignificantBits())
- .setIdLSB(ruleChainId.getId().getLeastSignificantBits()).build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java
deleted file mode 100644
index fbd3b31688..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserMsgConstructor.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.User;
-import org.thingsboard.server.common.data.id.UserId;
-import org.thingsboard.server.common.data.security.UserCredentials;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.UserUpdateMsg;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class UserMsgConstructor {
-
- public UserUpdateMsg constructUserUpdatedMsg(UpdateMsgType msgType, User user) {
- UserUpdateMsg.Builder builder = UserUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(user.getId().getId().getMostSignificantBits())
- .setIdLSB(user.getId().getId().getLeastSignificantBits())
- .setEmail(user.getEmail())
- .setAuthority(user.getAuthority().name());
- if (user.getCustomerId() != null) {
- builder.setCustomerIdMSB(user.getCustomerId().getId().getMostSignificantBits());
- builder.setCustomerIdLSB(user.getCustomerId().getId().getLeastSignificantBits());
- }
- if (user.getFirstName() != null) {
- builder.setFirstName(user.getFirstName());
- }
- if (user.getLastName() != null) {
- builder.setLastName(user.getLastName());
- }
- if (user.getAdditionalInfo() != null) {
- builder.setAdditionalInfo(JacksonUtil.toString(user.getAdditionalInfo()));
- }
- return builder.build();
- }
-
- public UserUpdateMsg constructUserDeleteMsg(UserId userId) {
- return UserUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(userId.getId().getMostSignificantBits())
- .setIdLSB(userId.getId().getLeastSignificantBits()).build();
- }
-
- public UserCredentialsUpdateMsg constructUserCredentialsUpdatedMsg(UserCredentials userCredentials) {
- UserCredentialsUpdateMsg.Builder builder = UserCredentialsUpdateMsg.newBuilder()
- .setUserIdMSB(userCredentials.getUserId().getId().getMostSignificantBits())
- .setUserIdLSB(userCredentials.getUserId().getId().getLeastSignificantBits())
- .setEnabled(userCredentials.isEnabled())
- .setPassword(userCredentials.getPassword());
- return builder.build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java
deleted file mode 100644
index a574b8bb4b..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import org.springframework.stereotype.Component;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.common.data.id.WidgetTypeId;
-import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-@Component
-@TbCoreComponent
-public class WidgetTypeMsgConstructor {
-
- public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetTypeDetails widgetTypeDetails) {
- WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(widgetTypeDetails.getId().getId().getMostSignificantBits())
- .setIdLSB(widgetTypeDetails.getId().getId().getLeastSignificantBits());
- if (widgetTypeDetails.getBundleAlias() != null) {
- builder.setBundleAlias(widgetTypeDetails.getBundleAlias());
- }
- if (widgetTypeDetails.getAlias() != null) {
- builder.setAlias(widgetTypeDetails.getAlias());
- }
- if (widgetTypeDetails.getName() != null) {
- builder.setName(widgetTypeDetails.getName());
- }
- if (widgetTypeDetails.getDescriptor() != null) {
- builder.setDescriptorJson(JacksonUtil.toString(widgetTypeDetails.getDescriptor()));
- }
- if (widgetTypeDetails.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
- builder.setIsSystem(true);
- }
- if (widgetTypeDetails.getImage() != null) {
- builder.setImage(widgetTypeDetails.getImage());
- }
- if (widgetTypeDetails.getDescription() != null) {
- builder.setDescription(widgetTypeDetails.getDescription());
- }
- return builder.build();
- }
-
- public WidgetTypeUpdateMsg constructWidgetTypeDeleteMsg(WidgetTypeId widgetTypeId) {
- return WidgetTypeUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(widgetTypeId.getId().getMostSignificantBits())
- .setIdLSB(widgetTypeId.getId().getLeastSignificantBits())
- .build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java
deleted file mode 100644
index 36e43b9579..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleMsgConstructor.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor;
-
-import com.google.protobuf.ByteString;
-import org.springframework.stereotype.Component;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.common.data.id.WidgetsBundleId;
-import org.thingsboard.server.common.data.widget.WidgetsBundle;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-
-import java.nio.charset.StandardCharsets;
-
-@Component
-@TbCoreComponent
-public class WidgetsBundleMsgConstructor {
-
- public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle) {
- WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder()
- .setMsgType(msgType)
- .setIdMSB(widgetsBundle.getId().getId().getMostSignificantBits())
- .setIdLSB(widgetsBundle.getId().getId().getLeastSignificantBits())
- .setTitle(widgetsBundle.getTitle())
- .setAlias(widgetsBundle.getAlias());
- if (widgetsBundle.getImage() != null) {
- builder.setImage(ByteString.copyFrom(widgetsBundle.getImage().getBytes(StandardCharsets.UTF_8)));
- }
- if (widgetsBundle.getDescription() != null) {
- builder.setDescription(widgetsBundle.getDescription());
- }
- if (widgetsBundle.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
- builder.setIsSystem(true);
- }
- return builder.build();
- }
-
- public WidgetsBundleUpdateMsg constructWidgetsBundleDeleteMsg(WidgetsBundleId widgetsBundleId) {
- return WidgetsBundleUpdateMsg.newBuilder()
- .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
- .setIdMSB(widgetsBundleId.getId().getMostSignificantBits())
- .setIdLSB(widgetsBundleId.getId().getLeastSignificantBits())
- .build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructor.java
new file mode 100644
index 0000000000..fd3b4ef95d
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructor.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.alarm;
+
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface AlarmMsgConstructor extends MsgConstructor {
+
+ AlarmUpdateMsg constructAlarmUpdatedMsg(UpdateMsgType msgType, Alarm alarm, String entityName);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorFactory.java
new file mode 100644
index 0000000000..63c9ad8bf5
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.alarm;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class AlarmMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV1.java
new file mode 100644
index 0000000000..b1294f5904
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV1.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright © 2016-2023 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.constructor.alarm;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class AlarmMsgConstructorV1 implements AlarmMsgConstructor {
+
+ @Override
+ public AlarmUpdateMsg constructAlarmUpdatedMsg(UpdateMsgType msgType, Alarm alarm, String entityName) {
+ return AlarmUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(alarm.getId().getId().getMostSignificantBits())
+ .setIdLSB(alarm.getId().getId().getLeastSignificantBits())
+ .setName(alarm.getName())
+ .setType(alarm.getType())
+ .setOriginatorName(entityName)
+ .setOriginatorType(alarm.getOriginator().getEntityType().name())
+ .setSeverity(alarm.getSeverity().name())
+ .setStatus(alarm.getStatus().name())
+ .setStartTs(alarm.getStartTs())
+ .setEndTs(alarm.getEndTs())
+ .setAckTs(alarm.getAckTs())
+ .setClearTs(alarm.getClearTs())
+ .setDetails(JacksonUtil.toString(alarm.getDetails()))
+ .setPropagate(alarm.isPropagate())
+ .setPropagateToOwner(alarm.isPropagateToOwner())
+ .setPropagateToTenant(alarm.isPropagateToTenant()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV2.java
new file mode 100644
index 0000000000..9034755db6
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/alarm/AlarmMsgConstructorV2.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright © 2016-2023 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.constructor.alarm;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class AlarmMsgConstructorV2 implements AlarmMsgConstructor {
+
+ @Override
+ public AlarmUpdateMsg constructAlarmUpdatedMsg(UpdateMsgType msgType, Alarm alarm, String entityName) {
+ return AlarmUpdateMsg.newBuilder().setMsgType(msgType)
+ .setEntity(JacksonUtil.toString(alarm))
+ .setIdMSB(alarm.getId().getId().getMostSignificantBits())
+ .setIdLSB(alarm.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructor.java
new file mode 100644
index 0000000000..338375ac37
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructor.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright © 2016-2023 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.constructor.asset;
+
+import org.thingsboard.server.common.data.asset.Asset;
+import org.thingsboard.server.common.data.asset.AssetProfile;
+import org.thingsboard.server.common.data.id.AssetId;
+import org.thingsboard.server.common.data.id.AssetProfileId;
+import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface AssetMsgConstructor extends MsgConstructor {
+
+ AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset);
+
+ AssetUpdateMsg constructAssetDeleteMsg(AssetId assetId);
+
+ AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile);
+
+ AssetProfileUpdateMsg constructAssetProfileDeleteMsg(AssetProfileId assetProfileId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorFactory.java
new file mode 100644
index 0000000000..bd756cb139
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.asset;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class AssetMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java
new file mode 100644
index 0000000000..ddf975d4ab
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright © 2016-2023 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.constructor.asset;
+
+import com.google.protobuf.ByteString;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.asset.Asset;
+import org.thingsboard.server.common.data.asset.AssetProfile;
+import org.thingsboard.server.dao.resource.ImageService;
+import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+import java.nio.charset.StandardCharsets;
+
+@Component
+@TbCoreComponent
+public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor {
+
+ @Autowired
+ private ImageService imageService;
+
+ @Override
+ public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset) {
+ AssetUpdateMsg.Builder builder = AssetUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(asset.getUuidId().getMostSignificantBits())
+ .setIdLSB(asset.getUuidId().getLeastSignificantBits())
+ .setName(asset.getName())
+ .setType(asset.getType());
+ if (asset.getLabel() != null) {
+ builder.setLabel(asset.getLabel());
+ }
+ if (asset.getCustomerId() != null) {
+ builder.setCustomerIdMSB(asset.getCustomerId().getId().getMostSignificantBits());
+ builder.setCustomerIdLSB(asset.getCustomerId().getId().getLeastSignificantBits());
+ }
+ if (asset.getAssetProfileId() != null) {
+ builder.setAssetProfileIdMSB(asset.getAssetProfileId().getId().getMostSignificantBits());
+ builder.setAssetProfileIdLSB(asset.getAssetProfileId().getId().getLeastSignificantBits());
+ }
+ if (asset.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(asset.getAdditionalInfo()));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) {
+ imageService.inlineImageForEdge(assetProfile);
+ AssetProfileUpdateMsg.Builder builder = AssetProfileUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(assetProfile.getId().getId().getMostSignificantBits())
+ .setIdLSB(assetProfile.getId().getId().getLeastSignificantBits())
+ .setName(assetProfile.getName())
+ .setDefault(assetProfile.isDefault());
+ if (assetProfile.getDefaultDashboardId() != null) {
+ builder.setDefaultDashboardIdMSB(assetProfile.getDefaultDashboardId().getId().getMostSignificantBits())
+ .setDefaultDashboardIdLSB(assetProfile.getDefaultDashboardId().getId().getLeastSignificantBits());
+ }
+ if (assetProfile.getDefaultQueueName() != null) {
+ builder.setDefaultQueueName(assetProfile.getDefaultQueueName());
+ }
+ if (assetProfile.getDescription() != null) {
+ builder.setDescription(assetProfile.getDescription());
+ }
+ if (assetProfile.getImage() != null) {
+ builder.setImage(ByteString.copyFrom(assetProfile.getImage().getBytes(StandardCharsets.UTF_8)));
+ }
+ if (assetProfile.getDefaultEdgeRuleChainId() != null) {
+ builder.setDefaultRuleChainIdMSB(assetProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits())
+ .setDefaultRuleChainIdLSB(assetProfile.getDefaultEdgeRuleChainId().getId().getLeastSignificantBits());
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV2.java
new file mode 100644
index 0000000000..b7e00473b5
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV2.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright © 2016-2023 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.constructor.asset;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.asset.Asset;
+import org.thingsboard.server.common.data.asset.AssetProfile;
+import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class AssetMsgConstructorV2 extends BaseAssetMsgConstructor {
+
+ @Override
+ public AssetUpdateMsg constructAssetUpdatedMsg(UpdateMsgType msgType, Asset asset) {
+ return AssetUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(asset))
+ .setIdMSB(asset.getUuidId().getMostSignificantBits())
+ .setIdLSB(asset.getUuidId().getLeastSignificantBits()).build();
+ }
+
+ @Override
+ public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) {
+ return AssetProfileUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(assetProfile))
+ .setIdMSB(assetProfile.getId().getId().getMostSignificantBits())
+ .setIdLSB(assetProfile.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/BaseAssetMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/BaseAssetMsgConstructor.java
new file mode 100644
index 0000000000..b8fe8ad870
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/BaseAssetMsgConstructor.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright © 2016-2023 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.constructor.asset;
+
+import org.thingsboard.server.common.data.id.AssetId;
+import org.thingsboard.server.common.data.id.AssetProfileId;
+import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseAssetMsgConstructor implements AssetMsgConstructor {
+
+ @Override
+ public AssetUpdateMsg constructAssetDeleteMsg(AssetId assetId) {
+ return AssetUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(assetId.getId().getMostSignificantBits())
+ .setIdLSB(assetId.getId().getLeastSignificantBits()).build();
+ }
+
+ @Override
+ public AssetProfileUpdateMsg constructAssetProfileDeleteMsg(AssetProfileId assetProfileId) {
+ return AssetProfileUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(assetProfileId.getId().getMostSignificantBits())
+ .setIdLSB(assetProfileId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/BaseCustomerMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/BaseCustomerMsgConstructor.java
new file mode 100644
index 0000000000..6d532a5e1c
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/BaseCustomerMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.customer;
+
+import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseCustomerMsgConstructor implements CustomerMsgConstructor {
+
+ @Override
+ public CustomerUpdateMsg constructCustomerDeleteMsg(CustomerId customerId) {
+ return CustomerUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(customerId.getId().getMostSignificantBits())
+ .setIdLSB(customerId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructor.java
new file mode 100644
index 0000000000..7351822a3f
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.customer;
+
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface CustomerMsgConstructor extends MsgConstructor {
+
+ CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer);
+
+ CustomerUpdateMsg constructCustomerDeleteMsg(CustomerId customerId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorFactory.java
new file mode 100644
index 0000000000..ba66a69cab
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.customer;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class CustomerMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV1.java
new file mode 100644
index 0000000000..e6bb95defa
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV1.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright © 2016-2023 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.constructor.customer;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class CustomerMsgConstructorV1 extends BaseCustomerMsgConstructor {
+
+ @Override
+ public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) {
+ CustomerUpdateMsg.Builder builder = CustomerUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(customer.getId().getId().getMostSignificantBits())
+ .setIdLSB(customer.getId().getId().getLeastSignificantBits())
+ .setTitle(customer.getTitle());
+ if (customer.getCountry() != null) {
+ builder.setCountry(customer.getCountry());
+ }
+ if (customer.getState() != null) {
+ builder.setState(customer.getState());
+ }
+ if (customer.getCity() != null) {
+ builder.setCity(customer.getCity());
+ }
+ if (customer.getAddress() != null) {
+ builder.setAddress(customer.getAddress());
+ }
+ if (customer.getAddress2() != null) {
+ builder.setAddress2(customer.getAddress2());
+ }
+ if (customer.getZip() != null) {
+ builder.setZip(customer.getZip());
+ }
+ if (customer.getPhone() != null) {
+ builder.setPhone(customer.getPhone());
+ }
+ if (customer.getEmail() != null) {
+ builder.setEmail(customer.getEmail());
+ }
+ if (customer.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(customer.getAdditionalInfo()));
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV2.java
new file mode 100644
index 0000000000..94764e1178
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/customer/CustomerMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.customer;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Customer;
+import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class CustomerMsgConstructorV2 extends BaseCustomerMsgConstructor {
+
+ @Override
+ public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) {
+ return CustomerUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(customer))
+ .setIdMSB(customer.getId().getId().getMostSignificantBits())
+ .setIdLSB(customer.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/BaseDashboardMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/BaseDashboardMsgConstructor.java
new file mode 100644
index 0000000000..f8e42c1461
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/BaseDashboardMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.dashboard;
+
+import org.thingsboard.server.common.data.id.DashboardId;
+import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseDashboardMsgConstructor implements DashboardMsgConstructor {
+
+ @Override
+ public DashboardUpdateMsg constructDashboardDeleteMsg(DashboardId dashboardId) {
+ return DashboardUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(dashboardId.getId().getMostSignificantBits())
+ .setIdLSB(dashboardId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructor.java
new file mode 100644
index 0000000000..96504e5036
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.dashboard;
+
+import org.thingsboard.server.common.data.Dashboard;
+import org.thingsboard.server.common.data.id.DashboardId;
+import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface DashboardMsgConstructor extends MsgConstructor {
+
+ DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard);
+
+ DashboardUpdateMsg constructDashboardDeleteMsg(DashboardId dashboardId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorFactory.java
new file mode 100644
index 0000000000..b559e0f454
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.dashboard;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class DashboardMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java
new file mode 100644
index 0000000000..548b1e1fd0
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright © 2016-2023 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.constructor.dashboard;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Dashboard;
+import org.thingsboard.server.dao.resource.ImageService;
+import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class DashboardMsgConstructorV1 extends BaseDashboardMsgConstructor {
+
+ @Autowired
+ private ImageService imageService;
+
+ @Override
+ public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) {
+ imageService.inlineImagesForEdge(dashboard);
+ DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(dashboard.getId().getId().getMostSignificantBits())
+ .setIdLSB(dashboard.getId().getId().getLeastSignificantBits())
+ .setTitle(dashboard.getTitle())
+ .setConfiguration(JacksonUtil.toString(dashboard.getConfiguration()))
+ .setMobileHide(dashboard.isMobileHide());
+ if (dashboard.getAssignedCustomers() != null) {
+ builder.setAssignedCustomers(JacksonUtil.toString(dashboard.getAssignedCustomers()));
+ }
+ if (dashboard.getImage() != null) {
+ builder.setImage(dashboard.getImage());
+ }
+ if (dashboard.getMobileOrder() != null) {
+ builder.setMobileOrder(dashboard.getMobileOrder());
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV2.java
new file mode 100644
index 0000000000..0940423119
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.dashboard;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Dashboard;
+import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class DashboardMsgConstructorV2 extends BaseDashboardMsgConstructor {
+
+ @Override
+ public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) {
+ return DashboardUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(dashboard))
+ .setIdMSB(dashboard.getId().getId().getMostSignificantBits())
+ .setIdLSB(dashboard.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/BaseDeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/BaseDeviceMsgConstructor.java
new file mode 100644
index 0000000000..21d761dc26
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/BaseDeviceMsgConstructor.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright © 2016-2023 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.constructor.device;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.DeviceProfileId;
+import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.RpcRequestMsg;
+import org.thingsboard.server.gen.edge.v1.RpcResponseMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+import java.util.UUID;
+
+public abstract class BaseDeviceMsgConstructor implements DeviceMsgConstructor {
+
+ @Override
+ public DeviceUpdateMsg constructDeviceDeleteMsg(DeviceId deviceId) {
+ return DeviceUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(deviceId.getId().getMostSignificantBits())
+ .setIdLSB(deviceId.getId().getLeastSignificantBits()).build();
+ }
+
+ @Override
+ public DeviceProfileUpdateMsg constructDeviceProfileDeleteMsg(DeviceProfileId deviceProfileId) {
+ return DeviceProfileUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(deviceProfileId.getId().getMostSignificantBits())
+ .setIdLSB(deviceProfileId.getId().getLeastSignificantBits()).build();
+ }
+
+ @Override
+ public DeviceRpcCallMsg constructDeviceRpcCallMsg(UUID deviceId, JsonNode body) {
+ DeviceRpcCallMsg.Builder builder = constructDeviceRpcMsg(deviceId, body);
+ if (body.has("error") || body.has("response")) {
+ RpcResponseMsg.Builder responseBuilder = RpcResponseMsg.newBuilder();
+ if (body.has("error")) {
+ responseBuilder.setError(body.get("error").asText());
+ } else {
+ responseBuilder.setResponse(body.get("response").asText());
+ }
+ builder.setResponseMsg(responseBuilder.build());
+ } else {
+ RpcRequestMsg.Builder requestBuilder = RpcRequestMsg.newBuilder();
+ requestBuilder.setMethod(body.get("method").asText());
+ requestBuilder.setParams(body.get("params").asText());
+ builder.setRequestMsg(requestBuilder.build());
+ }
+ return builder.build();
+ }
+
+ private DeviceRpcCallMsg.Builder constructDeviceRpcMsg(UUID deviceId, JsonNode body) {
+ DeviceRpcCallMsg.Builder builder = DeviceRpcCallMsg.newBuilder()
+ .setDeviceIdMSB(deviceId.getMostSignificantBits())
+ .setDeviceIdLSB(deviceId.getLeastSignificantBits())
+ .setRequestId(body.get("requestId").asInt());
+ if (body.get("oneway") != null) {
+ builder.setOneway(body.get("oneway").asBoolean());
+ }
+ if (body.get("requestUUID") != null) {
+ UUID requestUUID = UUID.fromString(body.get("requestUUID").asText());
+ builder.setRequestUuidMSB(requestUUID.getMostSignificantBits())
+ .setRequestUuidLSB(requestUUID.getLeastSignificantBits());
+ }
+ if (body.get("expirationTime") != null) {
+ builder.setExpirationTime(body.get("expirationTime").asLong());
+ }
+ if (body.get("persisted") != null) {
+ builder.setPersisted(body.get("persisted").asBoolean());
+ }
+ if (body.get("retries") != null) {
+ builder.setRetries(body.get("retries").asInt());
+ }
+ if (body.get("additionalInfo") != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(body.get("additionalInfo")));
+ }
+ if (body.get("serviceId") != null) {
+ builder.setServiceId(body.get("serviceId").asText());
+ }
+ if (body.get("sessionId") != null) {
+ builder.setSessionId(body.get("sessionId").asText());
+ }
+ return builder;
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructor.java
new file mode 100644
index 0000000000..4636dfd5ae
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructor.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2016-2023 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.constructor.device;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.DeviceProfileId;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+import java.util.UUID;
+
+public interface DeviceMsgConstructor extends MsgConstructor {
+
+ DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device);
+
+ DeviceUpdateMsg constructDeviceDeleteMsg(DeviceId deviceId);
+
+ DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials);
+
+ DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile);
+
+ DeviceProfileUpdateMsg constructDeviceProfileDeleteMsg(DeviceProfileId deviceProfileId);
+
+ DeviceRpcCallMsg constructDeviceRpcCallMsg(UUID deviceId, JsonNode body);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorFactory.java
new file mode 100644
index 0000000000..98add6af2c
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.device;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class DeviceMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java
new file mode 100644
index 0000000000..04f23f25b4
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright © 2016-2023 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.constructor.device;
+
+import com.google.protobuf.ByteString;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.dao.resource.ImageService;
+import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.DataDecodingEncodingService;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+import java.nio.charset.StandardCharsets;
+
+@Component
+@TbCoreComponent
+public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor {
+
+ @Autowired
+ private DataDecodingEncodingService dataDecodingEncodingService;
+
+ @Autowired
+ private ImageService imageService;
+
+ @Override
+ public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) {
+ DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(device.getId().getId().getMostSignificantBits())
+ .setIdLSB(device.getId().getId().getLeastSignificantBits())
+ .setName(device.getName())
+ .setType(device.getType());
+ if (device.getLabel() != null) {
+ builder.setLabel(device.getLabel());
+ }
+ if (device.getCustomerId() != null) {
+ builder.setCustomerIdMSB(device.getCustomerId().getId().getMostSignificantBits());
+ builder.setCustomerIdLSB(device.getCustomerId().getId().getLeastSignificantBits());
+ }
+ if (device.getDeviceProfileId() != null) {
+ builder.setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits());
+ builder.setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits());
+ }
+ if (device.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(device.getAdditionalInfo()));
+ }
+ if (device.getFirmwareId() != null) {
+ builder.setFirmwareIdMSB(device.getFirmwareId().getId().getMostSignificantBits())
+ .setFirmwareIdLSB(device.getFirmwareId().getId().getLeastSignificantBits());
+ }
+ if (device.getSoftwareId() != null) {
+ builder.setSoftwareIdMSB(device.getSoftwareId().getId().getMostSignificantBits())
+ .setSoftwareIdLSB(device.getSoftwareId().getId().getLeastSignificantBits());
+ }
+ if (device.getDeviceData() != null) {
+ builder.setDeviceDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(device.getDeviceData())));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials) {
+ DeviceCredentialsUpdateMsg.Builder builder = DeviceCredentialsUpdateMsg.newBuilder()
+ .setDeviceIdMSB(deviceCredentials.getDeviceId().getId().getMostSignificantBits())
+ .setDeviceIdLSB(deviceCredentials.getDeviceId().getId().getLeastSignificantBits());
+ if (deviceCredentials.getCredentialsType() != null) {
+ builder.setCredentialsType(deviceCredentials.getCredentialsType().name())
+ .setCredentialsId(deviceCredentials.getCredentialsId());
+ }
+ if (deviceCredentials.getCredentialsValue() != null) {
+ builder.setCredentialsValue(deviceCredentials.getCredentialsValue());
+ }
+ return builder.build();
+ }
+
+ @Override
+ public DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile) {
+ imageService.inlineImageForEdge(deviceProfile);
+ DeviceProfileUpdateMsg.Builder builder = DeviceProfileUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(deviceProfile.getId().getId().getMostSignificantBits())
+ .setIdLSB(deviceProfile.getId().getId().getLeastSignificantBits())
+ .setName(deviceProfile.getName())
+ .setDefault(deviceProfile.isDefault())
+ .setType(deviceProfile.getType().name())
+ .setProfileDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile.getProfileData())));
+ if (deviceProfile.getDefaultQueueName() != null) {
+ builder.setDefaultQueueName(deviceProfile.getDefaultQueueName());
+ }
+ if (deviceProfile.getDescription() != null) {
+ builder.setDescription(deviceProfile.getDescription());
+ }
+ if (deviceProfile.getTransportType() != null) {
+ builder.setTransportType(deviceProfile.getTransportType().name());
+ }
+ if (deviceProfile.getProvisionType() != null) {
+ builder.setProvisionType(deviceProfile.getProvisionType().name());
+ }
+ if (deviceProfile.getProvisionDeviceKey() != null) {
+ builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey());
+ }
+ if (deviceProfile.getImage() != null) {
+ builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8)));
+ }
+ if (deviceProfile.getFirmwareId() != null) {
+ builder.setFirmwareIdMSB(deviceProfile.getFirmwareId().getId().getMostSignificantBits())
+ .setFirmwareIdLSB(deviceProfile.getFirmwareId().getId().getLeastSignificantBits());
+ }
+ if (deviceProfile.getSoftwareId() != null) {
+ builder.setSoftwareIdMSB(deviceProfile.getSoftwareId().getId().getMostSignificantBits())
+ .setSoftwareIdLSB(deviceProfile.getSoftwareId().getId().getLeastSignificantBits());
+ }
+ if (deviceProfile.getDefaultEdgeRuleChainId() != null) {
+ builder.setDefaultRuleChainIdMSB(deviceProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits())
+ .setDefaultRuleChainIdLSB(deviceProfile.getDefaultEdgeRuleChainId().getId().getLeastSignificantBits());
+ }
+ if (deviceProfile.getDefaultDashboardId() != null) {
+ builder.setDefaultDashboardIdMSB(deviceProfile.getDefaultDashboardId().getId().getMostSignificantBits())
+ .setDefaultDashboardIdLSB(deviceProfile.getDefaultDashboardId().getId().getLeastSignificantBits());
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV2.java
new file mode 100644
index 0000000000..189251f8c4
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV2.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright © 2016-2023 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.constructor.device;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class DeviceMsgConstructorV2 extends BaseDeviceMsgConstructor {
+
+ @Override
+ public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device) {
+ return DeviceUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(device))
+ .setIdMSB(device.getId().getId().getMostSignificantBits())
+ .setIdLSB(device.getId().getId().getLeastSignificantBits()).build();
+ }
+
+ @Override
+ public DeviceCredentialsUpdateMsg constructDeviceCredentialsUpdatedMsg(DeviceCredentials deviceCredentials) {
+ return DeviceCredentialsUpdateMsg.newBuilder().setEntity(JacksonUtil.toString(deviceCredentials)).build();
+ }
+
+ @Override
+ public DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile) {
+ return DeviceProfileUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(deviceProfile))
+ .setIdMSB(deviceProfile.getId().getId().getMostSignificantBits())
+ .setIdLSB(deviceProfile.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/edge/EdgeMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/edge/EdgeMsgConstructor.java
new file mode 100644
index 0000000000..c3741ee8bf
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/edge/EdgeMsgConstructor.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2016-2023 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.constructor.edge;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.edge.Edge;
+import org.thingsboard.server.gen.edge.v1.EdgeConfiguration;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class EdgeMsgConstructor {
+
+ public EdgeConfiguration constructEdgeConfiguration(Edge edge) {
+ EdgeConfiguration.Builder builder = EdgeConfiguration.newBuilder()
+ .setEdgeIdMSB(edge.getId().getId().getMostSignificantBits())
+ .setEdgeIdLSB(edge.getId().getId().getLeastSignificantBits())
+ .setTenantIdMSB(edge.getTenantId().getId().getMostSignificantBits())
+ .setTenantIdLSB(edge.getTenantId().getId().getLeastSignificantBits())
+ .setName(edge.getName())
+ .setType(edge.getType())
+ .setRoutingKey(edge.getRoutingKey())
+ .setSecret(edge.getSecret())
+ .setAdditionalInfo(JacksonUtil.toString(edge.getAdditionalInfo()))
+ .setCloudType("CE");
+ if (edge.getCustomerId() != null) {
+ builder.setCustomerIdMSB(edge.getCustomerId().getId().getMostSignificantBits())
+ .setCustomerIdLSB(edge.getCustomerId().getId().getLeastSignificantBits());
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/BaseEntityViewMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/BaseEntityViewMsgConstructor.java
new file mode 100644
index 0000000000..a037e3ee09
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/BaseEntityViewMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.entityview;
+
+import org.thingsboard.server.common.data.id.EntityViewId;
+import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseEntityViewMsgConstructor implements EntityViewMsgConstructor {
+
+ @Override
+ public EntityViewUpdateMsg constructEntityViewDeleteMsg(EntityViewId entityViewId) {
+ return EntityViewUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(entityViewId.getId().getMostSignificantBits())
+ .setIdLSB(entityViewId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructor.java
new file mode 100644
index 0000000000..7f14f62c68
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.entityview;
+
+import org.thingsboard.server.common.data.EntityView;
+import org.thingsboard.server.common.data.id.EntityViewId;
+import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface EntityViewMsgConstructor extends MsgConstructor {
+
+ EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView);
+
+ EntityViewUpdateMsg constructEntityViewDeleteMsg(EntityViewId entityViewId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorFactory.java
new file mode 100644
index 0000000000..1a4ae9ef33
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.entityview;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class EntityViewMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV1.java
new file mode 100644
index 0000000000..da369ecf90
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV1.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright © 2016-2023 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.constructor.entityview;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.EntityView;
+import org.thingsboard.server.gen.edge.v1.EdgeEntityType;
+import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class EntityViewMsgConstructorV1 extends BaseEntityViewMsgConstructor {
+
+ @Override
+ public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView) {
+ EdgeEntityType edgeEntityType = checkEntityType(entityView.getEntityId().getEntityType());
+ EntityViewUpdateMsg.Builder builder = EntityViewUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(entityView.getId().getId().getMostSignificantBits())
+ .setIdLSB(entityView.getId().getId().getLeastSignificantBits())
+ .setName(entityView.getName())
+ .setType(entityView.getType())
+ .setEntityIdMSB(entityView.getEntityId().getId().getMostSignificantBits())
+ .setEntityIdLSB(entityView.getEntityId().getId().getLeastSignificantBits())
+ .setEntityType(edgeEntityType);
+ if (entityView.getCustomerId() != null) {
+ builder.setCustomerIdMSB(entityView.getCustomerId().getId().getMostSignificantBits());
+ builder.setCustomerIdLSB(entityView.getCustomerId().getId().getLeastSignificantBits());
+ }
+ if (entityView.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(entityView.getAdditionalInfo()));
+ }
+ return builder.build();
+ }
+
+ private EdgeEntityType checkEntityType(EntityType entityType) {
+ switch (entityType) {
+ case DEVICE:
+ return EdgeEntityType.DEVICE;
+ case ASSET:
+ return EdgeEntityType.ASSET;
+ default:
+ throw new RuntimeException("Unsupported entity type [" + entityType + "]");
+ }
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV2.java
new file mode 100644
index 0000000000..c1eae91097
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/entityview/EntityViewMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.entityview;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.EntityView;
+import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class EntityViewMsgConstructorV2 extends BaseEntityViewMsgConstructor {
+
+ @Override
+ public EntityViewUpdateMsg constructEntityViewUpdatedMsg(UpdateMsgType msgType, EntityView entityView) {
+ return EntityViewUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(entityView))
+ .setIdMSB(entityView.getId().getId().getMostSignificantBits())
+ .setIdLSB(entityView.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/BaseOtaPackageMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/BaseOtaPackageMsgConstructor.java
new file mode 100644
index 0000000000..110c24caca
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/BaseOtaPackageMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.ota;
+
+import org.thingsboard.server.common.data.id.OtaPackageId;
+import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseOtaPackageMsgConstructor implements OtaPackageMsgConstructor {
+
+ @Override
+ public OtaPackageUpdateMsg constructOtaPackageDeleteMsg(OtaPackageId otaPackageId) {
+ return OtaPackageUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(otaPackageId.getId().getMostSignificantBits())
+ .setIdLSB(otaPackageId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructor.java
new file mode 100644
index 0000000000..500500a7fc
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.ota;
+
+import org.thingsboard.server.common.data.OtaPackage;
+import org.thingsboard.server.common.data.id.OtaPackageId;
+import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface OtaPackageMsgConstructor extends MsgConstructor {
+
+ OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage);
+
+ OtaPackageUpdateMsg constructOtaPackageDeleteMsg(OtaPackageId otaPackageId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorFactory.java
new file mode 100644
index 0000000000..2427174892
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.ota;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class OtaPackageMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV1.java
new file mode 100644
index 0000000000..5e1f297c01
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV1.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright © 2016-2023 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.constructor.ota;
+
+import com.google.protobuf.ByteString;
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.OtaPackage;
+import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class OtaPackageMsgConstructorV1 extends BaseOtaPackageMsgConstructor {
+
+ @Override
+ public OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage) {
+ OtaPackageUpdateMsg.Builder builder = OtaPackageUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(otaPackage.getId().getId().getMostSignificantBits())
+ .setIdLSB(otaPackage.getId().getId().getLeastSignificantBits())
+ .setType(otaPackage.getType().name())
+ .setTitle(otaPackage.getTitle())
+ .setVersion(otaPackage.getVersion())
+ .setTag(otaPackage.getTag());
+
+ if (otaPackage.getDeviceProfileId() != null) {
+ builder.setDeviceProfileIdMSB(otaPackage.getDeviceProfileId().getId().getMostSignificantBits())
+ .setDeviceProfileIdLSB(otaPackage.getDeviceProfileId().getId().getLeastSignificantBits());
+ }
+
+ if (otaPackage.getUrl() != null) {
+ builder.setUrl(otaPackage.getUrl());
+ }
+ if (otaPackage.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(otaPackage.getAdditionalInfo()));
+ }
+ if (otaPackage.getFileName() != null) {
+ builder.setFileName(otaPackage.getFileName());
+ }
+ if (otaPackage.getContentType() != null) {
+ builder.setContentType(otaPackage.getContentType());
+ }
+ if (otaPackage.getChecksumAlgorithm() != null) {
+ builder.setChecksumAlgorithm(otaPackage.getChecksumAlgorithm().name());
+ }
+ if (otaPackage.getChecksum() != null) {
+ builder.setChecksum(otaPackage.getChecksum());
+ }
+ if (otaPackage.getDataSize() != null) {
+ builder.setDataSize(otaPackage.getDataSize());
+ }
+ if (otaPackage.getData() != null) {
+ builder.setData(ByteString.copyFrom(otaPackage.getData().array()));
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV2.java
new file mode 100644
index 0000000000..69d7f12874
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/ota/OtaPackageMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.ota;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.OtaPackage;
+import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class OtaPackageMsgConstructorV2 extends BaseOtaPackageMsgConstructor {
+
+ @Override
+ public OtaPackageUpdateMsg constructOtaPackageUpdatedMsg(UpdateMsgType msgType, OtaPackage otaPackage) {
+ return OtaPackageUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(otaPackage))
+ .setIdMSB(otaPackage.getId().getId().getMostSignificantBits())
+ .setIdLSB(otaPackage.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/BaseQueueMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/BaseQueueMsgConstructor.java
new file mode 100644
index 0000000000..486a143d85
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/BaseQueueMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.queue;
+
+import org.thingsboard.server.common.data.id.QueueId;
+import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseQueueMsgConstructor implements QueueMsgConstructor {
+
+ @Override
+ public QueueUpdateMsg constructQueueDeleteMsg(QueueId queueId) {
+ return QueueUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(queueId.getId().getMostSignificantBits())
+ .setIdLSB(queueId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructor.java
new file mode 100644
index 0000000000..847f19419e
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.queue;
+
+import org.thingsboard.server.common.data.id.QueueId;
+import org.thingsboard.server.common.data.queue.Queue;
+import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface QueueMsgConstructor extends MsgConstructor {
+
+ QueueUpdateMsg constructQueueUpdatedMsg(UpdateMsgType msgType, Queue queue);
+
+ QueueUpdateMsg constructQueueDeleteMsg(QueueId queueId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorFactory.java
new file mode 100644
index 0000000000..9d322a8ad7
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.queue;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class QueueMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV1.java
new file mode 100644
index 0000000000..8621ce1011
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV1.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright © 2016-2023 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.constructor.queue;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.id.QueueId;
+import org.thingsboard.server.common.data.queue.ProcessingStrategy;
+import org.thingsboard.server.common.data.queue.Queue;
+import org.thingsboard.server.common.data.queue.SubmitStrategy;
+import org.thingsboard.server.gen.edge.v1.ProcessingStrategyProto;
+import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.SubmitStrategyProto;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class QueueMsgConstructorV1 extends BaseQueueMsgConstructor {
+
+ @Override
+ public QueueUpdateMsg constructQueueUpdatedMsg(UpdateMsgType msgType, Queue queue) {
+ return QueueUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(queue.getId().getId().getMostSignificantBits())
+ .setIdLSB(queue.getId().getId().getLeastSignificantBits())
+ .setTenantIdMSB(queue.getTenantId().getId().getMostSignificantBits())
+ .setTenantIdLSB(queue.getTenantId().getId().getLeastSignificantBits())
+ .setName(queue.getName())
+ .setTopic(queue.getTopic())
+ .setPollInterval(queue.getPollInterval())
+ .setPartitions(queue.getPartitions())
+ .setConsumerPerPartition(queue.isConsumerPerPartition())
+ .setPackProcessingTimeout(queue.getPackProcessingTimeout())
+ .setSubmitStrategy(createSubmitStrategyProto(queue.getSubmitStrategy()))
+ .setProcessingStrategy(createProcessingStrategyProto(queue.getProcessingStrategy())).build();
+ }
+
+ private ProcessingStrategyProto createProcessingStrategyProto(ProcessingStrategy processingStrategy) {
+ return ProcessingStrategyProto.newBuilder()
+ .setType(processingStrategy.getType().name())
+ .setRetries(processingStrategy.getRetries())
+ .setFailurePercentage(processingStrategy.getFailurePercentage())
+ .setPauseBetweenRetries(processingStrategy.getPauseBetweenRetries())
+ .setMaxPauseBetweenRetries(processingStrategy.getMaxPauseBetweenRetries())
+ .build();
+ }
+
+ private SubmitStrategyProto createSubmitStrategyProto(SubmitStrategy submitStrategy) {
+ return SubmitStrategyProto.newBuilder()
+ .setType(submitStrategy.getType().name())
+ .setBatchSize(submitStrategy.getBatchSize())
+ .build();
+ }
+
+ public QueueUpdateMsg constructQueueDeleteMsg(QueueId queueId) {
+ return QueueUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(queueId.getId().getMostSignificantBits())
+ .setIdLSB(queueId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV2.java
new file mode 100644
index 0000000000..1bf80eea64
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/queue/QueueMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.queue;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.queue.Queue;
+import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class QueueMsgConstructorV2 extends BaseQueueMsgConstructor {
+
+ @Override
+ public QueueUpdateMsg constructQueueUpdatedMsg(UpdateMsgType msgType, Queue queue) {
+ return QueueUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(queue))
+ .setIdMSB(queue.getId().getId().getMostSignificantBits())
+ .setIdLSB(queue.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructor.java
new file mode 100644
index 0000000000..f7fac6ce71
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructor.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.relation;
+
+import org.thingsboard.server.common.data.relation.EntityRelation;
+import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface RelationMsgConstructor extends MsgConstructor {
+
+ RelationUpdateMsg constructRelationUpdatedMsg(UpdateMsgType msgType, EntityRelation entityRelation);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorFactory.java
new file mode 100644
index 0000000000..f0ddebc880
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.relation;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class RelationMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV1.java
new file mode 100644
index 0000000000..394086fdd0
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV1.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright © 2016-2023 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.constructor.relation;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.relation.EntityRelation;
+import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class RelationMsgConstructorV1 implements RelationMsgConstructor {
+
+ @Override
+ public RelationUpdateMsg constructRelationUpdatedMsg(UpdateMsgType msgType, EntityRelation entityRelation) {
+ RelationUpdateMsg.Builder builder = RelationUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setFromIdMSB(entityRelation.getFrom().getId().getMostSignificantBits())
+ .setFromIdLSB(entityRelation.getFrom().getId().getLeastSignificantBits())
+ .setFromEntityType(entityRelation.getFrom().getEntityType().name())
+ .setToIdMSB(entityRelation.getTo().getId().getMostSignificantBits())
+ .setToIdLSB(entityRelation.getTo().getId().getLeastSignificantBits())
+ .setToEntityType(entityRelation.getTo().getEntityType().name())
+ .setType(entityRelation.getType());
+ if (entityRelation.getAdditionalInfo() != null) {
+ builder.setAdditionalInfo(JacksonUtil.toString(entityRelation.getAdditionalInfo()));
+ }
+ if (entityRelation.getTypeGroup() != null) {
+ builder.setTypeGroup(entityRelation.getTypeGroup().name());
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV2.java
new file mode 100644
index 0000000000..4510909490
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/relation/RelationMsgConstructorV2.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2016-2023 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.constructor.relation;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.relation.EntityRelation;
+import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class RelationMsgConstructorV2 implements RelationMsgConstructor {
+
+
+ @Override
+ public RelationUpdateMsg constructRelationUpdatedMsg(UpdateMsgType msgType, EntityRelation entityRelation) {
+ return RelationUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(entityRelation)).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/BaseResourceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/BaseResourceMsgConstructor.java
new file mode 100644
index 0000000000..620f71c9e7
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/BaseResourceMsgConstructor.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright © 2016-2023 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.constructor.resource;
+
+import org.thingsboard.server.common.data.id.TbResourceId;
+import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+public abstract class BaseResourceMsgConstructor implements ResourceMsgConstructor {
+
+ @Override
+ public ResourceUpdateMsg constructResourceDeleteMsg(TbResourceId tbResourceId) {
+ return ResourceUpdateMsg.newBuilder()
+ .setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
+ .setIdMSB(tbResourceId.getId().getMostSignificantBits())
+ .setIdLSB(tbResourceId.getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructor.java
new file mode 100644
index 0000000000..cfeedced80
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructor.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2023 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.constructor.resource;
+
+import org.thingsboard.server.common.data.TbResource;
+import org.thingsboard.server.common.data.id.TbResourceId;
+import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.service.edge.rpc.constructor.MsgConstructor;
+
+public interface ResourceMsgConstructor extends MsgConstructor {
+
+ ResourceUpdateMsg constructResourceUpdatedMsg(UpdateMsgType msgType, TbResource tbResource);
+
+ ResourceUpdateMsg constructResourceDeleteMsg(TbResourceId tbResourceId);
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorFactory.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorFactory.java
new file mode 100644
index 0000000000..20443e4244
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorFactory.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2023 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.constructor.resource;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+import org.thingsboard.server.service.edge.rpc.constructor.BaseMsgConstructorFactory;
+
+@Component
+@TbCoreComponent
+public class ResourceMsgConstructorFactory extends BaseMsgConstructorFactory {
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV1.java
new file mode 100644
index 0000000000..f58f0b7c25
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV1.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2016-2023 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.constructor.resource;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.ResourceType;
+import org.thingsboard.server.common.data.TbResource;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class ResourceMsgConstructorV1 extends BaseResourceMsgConstructor {
+
+ @Override
+ public ResourceUpdateMsg constructResourceUpdatedMsg(UpdateMsgType msgType, TbResource tbResource) {
+ if (ResourceType.IMAGE.equals(tbResource.getResourceType())) {
+ // Exclude support for a recently added resource type when dealing with older Edges
+ // to maintain compatibility and avoid potential issues.
+ return null;
+ }
+ ResourceUpdateMsg.Builder builder = ResourceUpdateMsg.newBuilder()
+ .setMsgType(msgType)
+ .setIdMSB(tbResource.getId().getId().getMostSignificantBits())
+ .setIdLSB(tbResource.getId().getId().getLeastSignificantBits())
+ .setTitle(tbResource.getTitle())
+ .setResourceKey(tbResource.getResourceKey())
+ .setResourceType(tbResource.getResourceType().name())
+ .setFileName(tbResource.getFileName());
+ if (tbResource.getData() != null) {
+ builder.setData(tbResource.getEncodedData());
+ }
+ if (tbResource.getEtag() != null) {
+ builder.setEtag(tbResource.getEtag());
+ }
+ if (TenantId.SYS_TENANT_ID.equals(tbResource.getTenantId())) {
+ builder.setIsSystem(true);
+ }
+ return builder.build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV2.java
new file mode 100644
index 0000000000..094e5636bb
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/resource/ResourceMsgConstructorV2.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright © 2016-2023 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.constructor.resource;
+
+import org.springframework.stereotype.Component;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.TbResource;
+import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.TbCoreComponent;
+
+@Component
+@TbCoreComponent
+public class ResourceMsgConstructorV2 extends BaseResourceMsgConstructor {
+
+ @Override
+ public ResourceUpdateMsg constructResourceUpdatedMsg(UpdateMsgType msgType, TbResource tbResource) {
+ return ResourceUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(tbResource))
+ .setIdMSB(tbResource.getId().getId().getMostSignificantBits())
+ .setIdLSB(tbResource.getId().getId().getLeastSignificantBits()).build();
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/AbstractRuleChainMetadataConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/AbstractRuleChainMetadataConstructor.java
deleted file mode 100644
index 28c1b1c458..0000000000
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/AbstractRuleChainMetadataConstructor.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * Copyright © 2016-2023 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.constructor.rule;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.thingsboard.common.util.JacksonUtil;
-import org.thingsboard.server.common.data.id.TenantId;
-import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
-import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
-import org.thingsboard.server.common.data.rule.RuleChainMetaData;
-import org.thingsboard.server.common.data.rule.RuleNode;
-import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto;
-import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto;
-import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
-import org.thingsboard.server.gen.edge.v1.RuleNodeProto;
-import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.NavigableSet;
-
-@Slf4j
-@AllArgsConstructor
-public abstract class AbstractRuleChainMetadataConstructor implements RuleChainMetadataConstructor {
-
- @Override
- public RuleChainMetadataUpdateMsg constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
- UpdateMsgType msgType,
- RuleChainMetaData ruleChainMetaData) {
- try {
- RuleChainMetadataUpdateMsg.Builder builder = RuleChainMetadataUpdateMsg.newBuilder();
- builder.setRuleChainIdMSB(ruleChainMetaData.getRuleChainId().getId().getMostSignificantBits())
- .setRuleChainIdLSB(ruleChainMetaData.getRuleChainId().getId().getLeastSignificantBits());
- constructRuleChainMetadataUpdatedMsg(tenantId, builder, ruleChainMetaData);
- builder.setMsgType(msgType);
- return builder.build();
- } catch (JsonProcessingException ex) {
- log.error("Can't construct RuleChainMetadataUpdateMsg", ex);
- }
- return null;
- }
-
- protected abstract void constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
- RuleChainMetadataUpdateMsg.Builder builder,
- RuleChainMetaData ruleChainMetaData) throws JsonProcessingException;
-
- protected List constructConnections(List connections) {
- List result = new ArrayList<>();
- if (connections != null && !connections.isEmpty()) {
- for (NodeConnectionInfo connection : connections) {
- result.add(constructConnection(connection));
- }
- }
- return result;
- }
-
- private NodeConnectionInfoProto constructConnection(NodeConnectionInfo connection) {
- return NodeConnectionInfoProto.newBuilder()
- .setFromIndex(connection.getFromIndex())
- .setToIndex(connection.getToIndex())
- .setType(connection.getType())
- .build();
- }
-
- protected List constructNodes(List nodes) throws JsonProcessingException {
- List result = new ArrayList<>();
- if (nodes != null && !nodes.isEmpty()) {
- for (RuleNode node : nodes) {
- result.add(constructNode(node));
- }
- }
- return result;
- }
-
- private RuleNodeProto constructNode(RuleNode node) throws JsonProcessingException {
- return RuleNodeProto.newBuilder()
- .setIdMSB(node.getId().getId().getMostSignificantBits())
- .setIdLSB(node.getId().getId().getLeastSignificantBits())
- .setType(node.getType())
- .setName(node.getName())
- .setDebugMode(node.isDebugMode())
- .setConfiguration(JacksonUtil.OBJECT_MAPPER.writeValueAsString(node.getConfiguration()))
- .setAdditionalInfo(JacksonUtil.OBJECT_MAPPER.writeValueAsString(node.getAdditionalInfo()))
- .build();
- }
-
- protected List constructRuleChainConnections(List ruleChainConnections,
- NavigableSet removedNodeIndexes) throws JsonProcessingException {
- List result = new ArrayList<>();
- if (ruleChainConnections != null && !ruleChainConnections.isEmpty()) {
- for (RuleChainConnectionInfo ruleChainConnectionInfo : ruleChainConnections) {
- if (!removedNodeIndexes.isEmpty()) { // 3_3_0 only
- int fromIndex = ruleChainConnectionInfo.getFromIndex();
- // decrease index because of removed nodes
- for (Integer removedIndex : removedNodeIndexes) {
- if (fromIndex > removedIndex) {
- fromIndex = fromIndex - 1;
- }
- }
- ruleChainConnectionInfo.setFromIndex(fromIndex);
- ObjectNode additionalInfo = (ObjectNode) ruleChainConnectionInfo.getAdditionalInfo();
- if (additionalInfo.get("ruleChainNodeId") == null) {
- additionalInfo.put("ruleChainNodeId", "rule-chain-node-UNDEFINED");
- }
- }
- result.add(constructRuleChainConnection(ruleChainConnectionInfo));
- }
- }
- return result;
- }
-
- private RuleChainConnectionInfoProto constructRuleChainConnection(RuleChainConnectionInfo ruleChainConnectionInfo) throws JsonProcessingException {
- return RuleChainConnectionInfoProto.newBuilder()
- .setFromIndex(ruleChainConnectionInfo.getFromIndex())
- .setTargetRuleChainIdMSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getMostSignificantBits())
- .setTargetRuleChainIdLSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getLeastSignificantBits())
- .setType(ruleChainConnectionInfo.getType())
- .setAdditionalInfo(JacksonUtil.OBJECT_MAPPER.writeValueAsString(ruleChainConnectionInfo.getAdditionalInfo()))
- .build();
- }
-}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/BaseRuleChainMetadataConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/BaseRuleChainMetadataConstructor.java
new file mode 100644
index 0000000000..be10a714f6
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/rule/BaseRuleChainMetadataConstructor.java
@@ -0,0 +1,133 @@
+/**
+ * Copyright © 2016-2023 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.constructor.rule;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
+import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
+import org.thingsboard.server.common.data.rule.RuleChainMetaData;
+import org.thingsboard.server.common.data.rule.RuleNode;
+import org.thingsboard.server.gen.edge.v1.EdgeVersion;
+import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto;
+import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto;
+import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.RuleNodeProto;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NavigableSet;
+
+@Slf4j
+@AllArgsConstructor
+public abstract class BaseRuleChainMetadataConstructor implements RuleChainMetadataConstructor {
+
+ @Override
+ public RuleChainMetadataUpdateMsg constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
+ UpdateMsgType msgType,
+ RuleChainMetaData ruleChainMetaData,
+ EdgeVersion edgeVersion) {
+ RuleChainMetadataUpdateMsg.Builder builder = RuleChainMetadataUpdateMsg.newBuilder();
+ constructRuleChainMetadataUpdatedMsg(tenantId, builder, ruleChainMetaData);
+ builder.setMsgType(msgType);
+ return builder.build();
+ }
+
+ protected abstract void constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
+ RuleChainMetadataUpdateMsg.Builder builder,
+ RuleChainMetaData ruleChainMetaData);
+
+ protected List constructConnections(List connections) {
+ List result = new ArrayList<>();
+ if (connections != null && !connections.isEmpty()) {
+ for (NodeConnectionInfo connection : connections) {
+ result.add(constructConnection(connection));
+ }
+ }
+ return result;
+ }
+
+ private NodeConnectionInfoProto constructConnection(NodeConnectionInfo connection) {
+ return NodeConnectionInfoProto.newBuilder()
+ .setFromIndex(connection.getFromIndex())
+ .setToIndex(connection.getToIndex())
+ .setType(connection.getType())
+ .build();
+ }
+
+ protected List constructNodes(List nodes) {
+ List result = new ArrayList<>();
+ if (nodes != null && !nodes.isEmpty()) {
+ for (RuleNode node : nodes) {
+ result.add(constructNode(node));
+ }
+ }
+ return result;
+ }
+
+ private RuleNodeProto constructNode(RuleNode node) {
+ return RuleNodeProto.newBuilder()
+ .setIdMSB(node.getId().getId().getMostSignificantBits())
+ .setIdLSB(node.getId().getId().getLeastSignificantBits())
+ .setType(node.getType())
+ .setName(node.getName())
+ .setDebugMode(node.isDebugMode())
+ .setConfiguration(JacksonUtil.toString(node.getConfiguration()))
+ .setAdditionalInfo(JacksonUtil.toString(node.getAdditionalInfo()))
+ .setSingletonMode(node.isSingletonMode())
+ .setConfigurationVersion(node.getConfigurationVersion())
+ .build();
+ }
+
+ protected List constructRuleChainConnections(List ruleChainConnections,
+ NavigableSet removedNodeIndexes) {
+ List