diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index e7c295b9e6..8a8fcff2a4 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -55,6 +55,7 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.service.DefaultTransportService; +import org.thingsboard.server.common.transport.service.SessionMetaData; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; @@ -596,7 +597,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement } } - private void checkGatewaySession() { + private void checkGatewaySession(SessionMetaData sessionMetaData) { TransportDeviceInfo device = deviceSessionCtx.getDeviceInfo(); try { JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); @@ -604,6 +605,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement JsonNode gatewayNode = infoNode.get("gateway"); if (gatewayNode != null && gatewayNode.asBoolean()) { gatewaySessionHandler = new GatewaySessionHandler(deviceSessionCtx, sessionId); + if (infoNode.has(DefaultTransportService.OVERWRITE_ACTIVITY_TIME) && infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).isBoolean()) { + sessionMetaData.setOverwriteActivityTime(infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).asBoolean()); + } } } } catch (IOException e) { @@ -639,8 +643,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement transportService.process(deviceSessionCtx.getSessionInfo(), DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), new TransportServiceCallback() { @Override public void onSuccess(Void msg) { - transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), MqttTransportHandler.this); - checkGatewaySession(); + SessionMetaData sessionMetaData = transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), MqttTransportHandler.this); + checkGatewaySession(sessionMetaData); ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED, connectMessage)); log.info("[{}] Client connected!", sessionId); } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java index 6ec1337c62..1d30f561aa 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; +import org.thingsboard.server.common.transport.service.SessionMetaData; import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; @@ -81,9 +82,9 @@ public interface TransportService { void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback callback); - void registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener); + SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener); - void registerSyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout); + SessionMetaData registerSyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout); void reportActivity(SessionInfoProto sessionInfo); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/auth/SessionInfoCreator.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/auth/SessionInfoCreator.java index 235ae6b3a3..ab18b930f9 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/auth/SessionInfoCreator.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/auth/SessionInfoCreator.java @@ -15,16 +15,17 @@ */ package org.thingsboard.server.common.transport.auth; +import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.gen.transport.TransportProtos; import java.util.UUID; +@Slf4j public class SessionInfoCreator { public static TransportProtos.SessionInfoProto create(ValidateDeviceCredentialsResponse msg, TransportContext context, UUID sessionId) { - return TransportProtos.SessionInfoProto.newBuilder() - .setNodeId(context.getNodeId()) + return TransportProtos.SessionInfoProto.newBuilder().setNodeId(context.getNodeId()) .setSessionIdMSB(sessionId.getMostSignificantBits()) .setSessionIdLSB(sessionId.getLeastSignificantBits()) .setDeviceIdMSB(msg.getDeviceInfo().getDeviceId().getId().getMostSignificantBits()) diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index 5e46a77fb1..8ef0187342 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -61,6 +61,7 @@ import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; @@ -107,6 +108,8 @@ import java.util.concurrent.atomic.AtomicInteger; @TbTransportComponent public class DefaultTransportService implements TransportService { + public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime"; + @Value("${transport.sessions.inactivity_timeout}") private long sessionInactivityTimeout; @Value("${transport.sessions.report_timeout}") @@ -232,8 +235,10 @@ public class DefaultTransportService implements TransportService { } @Override - public void registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) { - sessions.putIfAbsent(toSessionId(sessionInfo), new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener)); + public SessionMetaData registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) { + SessionMetaData newValue = new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener); + SessionMetaData oldValue = sessions.putIfAbsent(toSessionId(sessionInfo), newValue); + return oldValue != null ? oldValue : newValue; } @Override @@ -512,7 +517,7 @@ public class DefaultTransportService implements TransportService { if (sessionInfo.getGwSessionIdMSB() != 0 && sessionInfo.getGwSessionIdLSB() != 0) { SessionMetaData gwMetaData = sessions.get(new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB())); - if (gwMetaData != null) { + if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) { lastActivityTime = Math.max(gwMetaData.getLastActivityTime(), lastActivityTime); } } @@ -546,7 +551,7 @@ public class DefaultTransportService implements TransportService { } @Override - public void registerSyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) { + public SessionMetaData registerSyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) { SessionMetaData currentSession = new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener); sessions.putIfAbsent(toSessionId(sessionInfo), currentSession); @@ -556,6 +561,7 @@ public class DefaultTransportService implements TransportService { }, timeout, TimeUnit.MILLISECONDS); currentSession.setScheduledFuture(executorFuture); + return currentSession; } @Override @@ -707,8 +713,13 @@ public class DefaultTransportService implements TransportService { .setDeviceProfileIdMSB(deviceProfileIdMSB) .setDeviceProfileIdLSB(deviceProfileIdLSB) .setDeviceName(device.getName()) - .setDeviceType(device.getType()) - .build(); + .setDeviceType(device.getType()).build(); + if (device.getAdditionalInfo().has("gateway") + && device.getAdditionalInfo().get("gateway").asBoolean() + && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME) + && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) { + md.setOverwriteActivityTime(device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean()); + } md.setSessionInfo(newSessionInfo); transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/SessionMetaData.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/SessionMetaData.java index c81ca05bc1..bb0ed7aa58 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/SessionMetaData.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/SessionMetaData.java @@ -25,7 +25,7 @@ import java.util.concurrent.ScheduledFuture; * Created by ashvayka on 15.10.18. */ @Data -class SessionMetaData { +public class SessionMetaData { private volatile TransportProtos.SessionInfoProto sessionInfo; private final TransportProtos.SessionType sessionType; @@ -36,6 +36,7 @@ class SessionMetaData { private volatile long lastReportedActivityTime; private volatile boolean subscribedToAttributes; private volatile boolean subscribedToRPC; + private volatile boolean overwriteActivityTime; SessionMetaData(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SessionType sessionType, SessionMsgListener listener) { this.sessionInfo = sessionInfo; diff --git a/ui-ngx/src/app/modules/home/pages/device/device.component.html b/ui-ngx/src/app/modules/home/pages/device/device.component.html index 7f7465a5e6..b01aced285 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device.component.html +++ b/ui-ngx/src/app/modules/home/pages/device/device.component.html @@ -100,9 +100,15 @@ required>
- - {{ 'device.is-gateway' | translate }} - +
+ + {{ 'device.is-gateway' | translate }} + + + {{ 'device.overwrite-activity-time' | translate }} + +
device.description diff --git a/ui-ngx/src/app/modules/home/pages/device/device.component.ts b/ui-ngx/src/app/modules/home/pages/device/device.component.ts index 782ed9e23a..660b6341ca 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device.component.ts @@ -84,6 +84,7 @@ export class DeviceComponent extends EntityComponent { additionalInfo: this.fb.group( { gateway: [entity && entity.additionalInfo ? entity.additionalInfo.gateway : false], + overwriteActivityTime: [entity && entity.additionalInfo ? entity.additionalInfo.overwriteActivityTime: false], description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], } ) @@ -96,8 +97,13 @@ export class DeviceComponent extends EntityComponent { this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId}); this.entityForm.patchValue({label: entity.label}); this.entityForm.patchValue({deviceData: entity.deviceData}); - this.entityForm.patchValue({additionalInfo: - {gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false}}); + this.entityForm.patchValue({ + additionalInfo: + { + gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false, + overwriteActivityTime: entity.additionalInfo ? entity.additionalInfo.overwriteActivityTime : false + } + }); this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}}); } diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index a099baaeb3..ea0e45cbd2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -906,6 +906,7 @@ "unable-delete-device-alias-title": "Unable to delete device alias", "unable-delete-device-alias-text": "Device alias '{{deviceAlias}}' can't be deleted as it used by the following widget(s):
{{widgetsList}}", "is-gateway": "Is gateway", + "overwrite-activity-time": "Overwrite activity time for connected device", "public": "Public", "device-public": "Device is public", "select-device": "Select device", @@ -1721,6 +1722,7 @@ "entity-field": "Entity field", "access-token": "Access token", "isgateway": "Is Gateway", + "activity-time-from-gateway-device": "Activity time from gateway device", "description": "Description" }, "stepper-text":{