git push origin masterMerge branch 'zbeacon-fix/lastActivityTime'

This commit is contained in:
Andrii Shvaika 2021-01-22 16:07:17 +02:00
commit beff831d5d
8 changed files with 51 additions and 19 deletions

View File

@ -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.TransportDeviceInfo;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.common.transport.service.DefaultTransportService; 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;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent; 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(); TransportDeviceInfo device = deviceSessionCtx.getDeviceInfo();
try { try {
JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo());
@ -604,6 +605,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
JsonNode gatewayNode = infoNode.get("gateway"); JsonNode gatewayNode = infoNode.get("gateway");
if (gatewayNode != null && gatewayNode.asBoolean()) { if (gatewayNode != null && gatewayNode.asBoolean()) {
gatewaySessionHandler = new GatewaySessionHandler(deviceSessionCtx, sessionId); 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) { } catch (IOException e) {
@ -639,8 +643,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
transportService.process(deviceSessionCtx.getSessionInfo(), DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), new TransportServiceCallback<Void>() { transportService.process(deviceSessionCtx.getSessionInfo(), DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), new TransportServiceCallback<Void>() {
@Override @Override
public void onSuccess(Void msg) { public void onSuccess(Void msg) {
transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), MqttTransportHandler.this); SessionMetaData sessionMetaData = transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), MqttTransportHandler.this);
checkGatewaySession(); checkGatewaySession(sessionMetaData);
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED, connectMessage)); ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED, connectMessage));
log.info("[{}] Client connected!", sessionId); log.info("[{}] Client connected!", sessionId);
} }

View File

@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 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.ClaimDeviceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
@ -81,9 +82,9 @@ public interface TransportService {
void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback); void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> 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); void reportActivity(SessionInfoProto sessionInfo);

View File

@ -15,16 +15,17 @@
*/ */
package org.thingsboard.server.common.transport.auth; package org.thingsboard.server.common.transport.auth;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.common.transport.TransportContext;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import java.util.UUID; import java.util.UUID;
@Slf4j
public class SessionInfoCreator { public class SessionInfoCreator {
public static TransportProtos.SessionInfoProto create(ValidateDeviceCredentialsResponse msg, TransportContext context, UUID sessionId) { public static TransportProtos.SessionInfoProto create(ValidateDeviceCredentialsResponse msg, TransportContext context, UUID sessionId) {
return TransportProtos.SessionInfoProto.newBuilder() return TransportProtos.SessionInfoProto.newBuilder().setNodeId(context.getNodeId())
.setNodeId(context.getNodeId())
.setSessionIdMSB(sessionId.getMostSignificantBits()) .setSessionIdMSB(sessionId.getMostSignificantBits())
.setSessionIdLSB(sessionId.getLeastSignificantBits()) .setSessionIdLSB(sessionId.getLeastSignificantBits())
.setDeviceIdMSB(msg.getDeviceInfo().getDeviceId().getId().getMostSignificantBits()) .setDeviceIdMSB(msg.getDeviceInfo().getDeviceId().getId().getMostSignificantBits())

View File

@ -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;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; 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.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
@ -107,6 +108,8 @@ import java.util.concurrent.atomic.AtomicInteger;
@TbTransportComponent @TbTransportComponent
public class DefaultTransportService implements TransportService { public class DefaultTransportService implements TransportService {
public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime";
@Value("${transport.sessions.inactivity_timeout}") @Value("${transport.sessions.inactivity_timeout}")
private long sessionInactivityTimeout; private long sessionInactivityTimeout;
@Value("${transport.sessions.report_timeout}") @Value("${transport.sessions.report_timeout}")
@ -232,8 +235,10 @@ public class DefaultTransportService implements TransportService {
} }
@Override @Override
public void registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) { public SessionMetaData registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) {
sessions.putIfAbsent(toSessionId(sessionInfo), new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener)); SessionMetaData newValue = new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener);
SessionMetaData oldValue = sessions.putIfAbsent(toSessionId(sessionInfo), newValue);
return oldValue != null ? oldValue : newValue;
} }
@Override @Override
@ -512,7 +517,7 @@ public class DefaultTransportService implements TransportService {
if (sessionInfo.getGwSessionIdMSB() != 0 && if (sessionInfo.getGwSessionIdMSB() != 0 &&
sessionInfo.getGwSessionIdLSB() != 0) { sessionInfo.getGwSessionIdLSB() != 0) {
SessionMetaData gwMetaData = sessions.get(new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB())); SessionMetaData gwMetaData = sessions.get(new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB()));
if (gwMetaData != null) { if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) {
lastActivityTime = Math.max(gwMetaData.getLastActivityTime(), lastActivityTime); lastActivityTime = Math.max(gwMetaData.getLastActivityTime(), lastActivityTime);
} }
} }
@ -546,7 +551,7 @@ public class DefaultTransportService implements TransportService {
} }
@Override @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); SessionMetaData currentSession = new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener);
sessions.putIfAbsent(toSessionId(sessionInfo), currentSession); sessions.putIfAbsent(toSessionId(sessionInfo), currentSession);
@ -556,6 +561,7 @@ public class DefaultTransportService implements TransportService {
}, timeout, TimeUnit.MILLISECONDS); }, timeout, TimeUnit.MILLISECONDS);
currentSession.setScheduledFuture(executorFuture); currentSession.setScheduledFuture(executorFuture);
return currentSession;
} }
@Override @Override
@ -707,8 +713,13 @@ public class DefaultTransportService implements TransportService {
.setDeviceProfileIdMSB(deviceProfileIdMSB) .setDeviceProfileIdMSB(deviceProfileIdMSB)
.setDeviceProfileIdLSB(deviceProfileIdLSB) .setDeviceProfileIdLSB(deviceProfileIdLSB)
.setDeviceName(device.getName()) .setDeviceName(device.getName())
.setDeviceType(device.getType()) .setDeviceType(device.getType()).build();
.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); md.setSessionInfo(newSessionInfo);
transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile)));
} }

View File

@ -25,7 +25,7 @@ import java.util.concurrent.ScheduledFuture;
* Created by ashvayka on 15.10.18. * Created by ashvayka on 15.10.18.
*/ */
@Data @Data
class SessionMetaData { public class SessionMetaData {
private volatile TransportProtos.SessionInfoProto sessionInfo; private volatile TransportProtos.SessionInfoProto sessionInfo;
private final TransportProtos.SessionType sessionType; private final TransportProtos.SessionType sessionType;
@ -36,6 +36,7 @@ class SessionMetaData {
private volatile long lastReportedActivityTime; private volatile long lastReportedActivityTime;
private volatile boolean subscribedToAttributes; private volatile boolean subscribedToAttributes;
private volatile boolean subscribedToRPC; private volatile boolean subscribedToRPC;
private volatile boolean overwriteActivityTime;
SessionMetaData(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SessionType sessionType, SessionMsgListener listener) { SessionMetaData(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SessionType sessionType, SessionMsgListener listener) {
this.sessionInfo = sessionInfo; this.sessionInfo = sessionInfo;

View File

@ -100,9 +100,15 @@
required> required>
</tb-device-data> </tb-device-data>
<div formGroupName="additionalInfo" fxLayout="column"> <div formGroupName="additionalInfo" fxLayout="column">
<mat-checkbox fxFlex formControlName="gateway" style="padding-bottom: 16px;"> <div fxLayout="row" fxLayout.xs="column" style="padding-bottom: 16px;">
{{ 'device.is-gateway' | translate }} <mat-checkbox fxFlex.gt-sm="30" fxFlex formControlName="gateway">
</mat-checkbox> {{ 'device.is-gateway' | translate }}
</mat-checkbox>
<mat-checkbox fxFlex *ngIf="entityForm.get('additionalInfo.gateway').value"
formControlName="overwriteActivityTime">
{{ 'device.overwrite-activity-time' | translate }}
</mat-checkbox>
</div>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label translate>device.description</mat-label> <mat-label translate>device.description</mat-label>
<textarea matInput formControlName="description" rows="2"></textarea> <textarea matInput formControlName="description" rows="2"></textarea>

View File

@ -84,6 +84,7 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
additionalInfo: this.fb.group( additionalInfo: this.fb.group(
{ {
gateway: [entity && entity.additionalInfo ? entity.additionalInfo.gateway : false], gateway: [entity && entity.additionalInfo ? entity.additionalInfo.gateway : false],
overwriteActivityTime: [entity && entity.additionalInfo ? entity.additionalInfo.overwriteActivityTime: false],
description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''],
} }
) )
@ -96,8 +97,13 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> {
this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId}); this.entityForm.patchValue({deviceProfileId: entity.deviceProfileId});
this.entityForm.patchValue({label: entity.label}); this.entityForm.patchValue({label: entity.label});
this.entityForm.patchValue({deviceData: entity.deviceData}); this.entityForm.patchValue({deviceData: entity.deviceData});
this.entityForm.patchValue({additionalInfo: this.entityForm.patchValue({
{gateway: entity.additionalInfo ? entity.additionalInfo.gateway : false}}); 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 : ''}}); this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
} }

View File

@ -906,6 +906,7 @@
"unable-delete-device-alias-title": "Unable to delete device alias", "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):<br/>{{widgetsList}}", "unable-delete-device-alias-text": "Device alias '{{deviceAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}",
"is-gateway": "Is gateway", "is-gateway": "Is gateway",
"overwrite-activity-time": "Overwrite activity time for connected device",
"public": "Public", "public": "Public",
"device-public": "Device is public", "device-public": "Device is public",
"select-device": "Select device", "select-device": "Select device",
@ -1721,6 +1722,7 @@
"entity-field": "Entity field", "entity-field": "Entity field",
"access-token": "Access token", "access-token": "Access token",
"isgateway": "Is Gateway", "isgateway": "Is Gateway",
"activity-time-from-gateway-device": "Activity time from gateway device",
"description": "Description" "description": "Description"
}, },
"stepper-text":{ "stepper-text":{