added power mode to lwm2m-device-profile-transport-configuration

This commit is contained in:
YevhenBondarenko 2021-06-24 10:53:35 +03:00
parent ba507e9910
commit a665b2cbe6
25 changed files with 186 additions and 186 deletions

View File

@ -41,6 +41,8 @@ import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
@ -459,6 +461,13 @@ public class DefaultTransportApiService implements TransportApiService {
}
private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
PowerMode powerMode = null;
switch (device.getDeviceData().getTransportConfiguration().getType()) {
case LWM2M:
powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
break;
}
return DeviceInfoProto.newBuilder()
.setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
.setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())
@ -471,6 +480,7 @@ public class DefaultTransportApiService implements TransportApiService {
.setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits())
.setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits())
.setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()))
.setPowerMode(powerMode != null ? powerMode.name() : null)
.build();
}

View File

@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfiguration;
import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
import java.util.HashMap;
import java.util.Map;
@ -30,6 +27,8 @@ import java.util.Map;
@Data
public class Lwm2mDeviceTransportConfiguration implements DeviceTransportConfiguration {
private PowerMode powerMode;
@JsonIgnore
private Map<String, Object> properties = new HashMap<>();

View File

@ -115,6 +115,7 @@ message DeviceInfoProto {
int64 deviceProfileIdLSB = 9;
int64 customerIdMSB = 10;
int64 customerIdLSB = 11;
string powerMode = 12;
}
/**

View File

@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.data.security.DeviceTokenCredentials;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.common.msg.session.SessionMsgType;
@ -515,23 +514,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource {
exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
successful = false;
}
if (msg.getPersisted()) {
RpcStatus status;
if (!successful) {
status = RpcStatus.FAILED;
} else if (msg.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(msg.getRequestId())
.setRequestIdLSB(msg.getRequestIdLSB())
.setRequestIdMSB(msg.getRequestIdMSB())
.setStatus(status.name())
.build();
coapTransportResource.transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);
}
coapTransportResource.transportService.process(sessionInfo, msg, !successful, TransportServiceCallback.EMPTY);
}
@Override

View File

@ -406,21 +406,7 @@ public class DeviceApiController implements TbTransportService {
@Override
public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg msg) {
responseWriter.setResult(new ResponseEntity<>(JsonConverter.toJson(msg, true).toString(), HttpStatus.OK));
if (msg.getPersisted()) {
RpcStatus status;
if (msg.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(msg.getRequestId())
.setRequestIdLSB(msg.getRequestIdLSB())
.setRequestIdMSB(msg.getRequestIdMSB())
.setStatus(status.name())
.build();
transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);
}
transportService.process(sessionInfo, msg, false, TransportServiceCallback.EMPTY);
}
@Override

View File

@ -33,6 +33,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer;
import java.io.IOException;
@ -84,7 +85,14 @@ public class LwM2mCredentialsSecurityInfoValidator {
} catch (InterruptedException e) {
log.error("Failed to await credentials!", e);
}
return resultSecurityStore[0];
TbLwM2MSecurityInfo securityInfo = resultSecurityStore[0];
if (securityInfo.getSecurityMode() == null) {
throw new LwM2MAuthException();
}
return securityInfo;
}
/**

View File

@ -16,6 +16,7 @@
package org.thingsboard.server.transport.lwm2m.secure;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.request.Identity;
import org.eclipse.leshan.core.request.UplinkRequest;
import org.eclipse.leshan.server.registration.Registration;
@ -24,14 +25,15 @@ import org.eclipse.leshan.server.security.SecurityChecker;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.springframework.stereotype.Component;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
@Component
@RequiredArgsConstructor
@TbLwM2mTransportComponent
@Slf4j
public class TbLwM2MAuthorizer implements Authorizer {
private final TbLwM2MDtlsSessionStore sessionStorage;
@ -57,7 +59,12 @@ public class TbLwM2MAuthorizer implements Authorizer {
}
SecurityInfo expectedSecurityInfo = null;
if (securityStore != null) {
expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint());
try {
expectedSecurityInfo = securityStore.getByEndpoint(registration.getEndpoint());
} catch (LwM2MAuthException e) {
log.warn("Registration failed: FORBIDDEN, endpointId: [{}]", registration.getEndpoint());
return null;
}
}
if (securityChecker.checkSecurityInfo(registration.getEndpoint(), senderIdentity, expectedSecurityInfo)) {
return registration;

View File

@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.transport.SessionMsgListener;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.TransportServiceCallback;
@ -58,7 +57,7 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
@Override
public void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification) {
this.attributesService.onAttributesUpdate(attributeUpdateNotification, this.sessionInfo);
}
}
@Override
public void onRemoteSessionCloseCommand(UUID sessionId, SessionCloseNotificationProto sessionCloseNotification) {
@ -83,21 +82,7 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
@Override
public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) {
this.rpcHandler.onToDeviceRpcRequest(toDeviceRequest, this.sessionInfo);
if (toDeviceRequest.getPersisted()) {
RpcStatus status;
if (toDeviceRequest.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(toDeviceRequest.getRequestId())
.setRequestIdLSB(toDeviceRequest.getRequestIdLSB())
.setRequestIdMSB(toDeviceRequest.getRequestIdMSB())
.setStatus(status.name())
.build();
transportService.process(sessionInfo, responseMsg, TransportServiceCallback.EMPTY);
}
transportService.process(sessionInfo, toDeviceRequest, false, TransportServiceCallback.EMPTY);
}
@Override

View File

@ -0,0 +1,22 @@
/**
* Copyright © 2016-2021 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.transport.lwm2m.server.client;
public class LwM2MAuthException extends RuntimeException {
private static final long serialVersionUID = 4202690897971364044L;
}

View File

@ -32,6 +32,8 @@ import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
@ -79,6 +81,9 @@ public class LwM2mClient implements Cloneable {
@Getter
private String deviceProfileName;
@Getter
private PowerMode powerMode;
@Getter
private String identity;
@Getter
@ -121,6 +126,7 @@ public class LwM2mClient implements Cloneable {
this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
this.deviceName = session.getDeviceName();
this.deviceProfileName = session.getDeviceType();
this.powerMode = credentials.getDeviceInfo().getPowerMode();
}
public void lock() {
@ -140,6 +146,7 @@ public class LwM2mClient implements Cloneable {
builder.setDeviceName(deviceName);
deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder));
this.session = builder.build();
this.powerMode = ((Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration()).getPowerMode();
}
public void onDeviceProfileUpdate(DeviceProfile deviceProfile) {

View File

@ -37,10 +37,10 @@ import org.eclipse.leshan.server.registration.Registration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
@ -83,8 +83,6 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
import org.thingsboard.server.transport.lwm2m.server.ota.firmware.LwM2MFirmwareUpdateStrategy;
import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareUpdateStrategy;
import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@ -203,30 +201,25 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
executor.submit(() -> {
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
try {
log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
if (lwM2MClient != null) {
Optional<SessionInfoProto> oldSessionInfo = this.clientContext.register(lwM2MClient, registration);
if (oldSessionInfo.isPresent()) {
log.info("[{}] Closing old session: {}", registration.getEndpoint(), new UUID(oldSessionInfo.get().getSessionIdMSB(), oldSessionInfo.get().getSessionIdLSB()));
closeSession(oldSessionInfo.get());
}
logService.log(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());
SessionInfoProto sessionInfo = lwM2MClient.getSession();
transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));
log.warn("40) sessionId [{}] Registering rpc subscription after Registration client", new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
.setSessionInfo(sessionInfo)
.setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
.setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
.setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
.build();
transportService.process(msg, null);
this.initClientTelemetry(lwM2MClient);
this.initAttributes(lwM2MClient);
otaService.init(lwM2MClient);
} else {
log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), null);
log.debug("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
Optional<SessionInfoProto> oldSessionInfo = this.clientContext.register(lwM2MClient, registration);
if (oldSessionInfo.isPresent()) {
log.info("[{}] Closing old session: {}", registration.getEndpoint(), new UUID(oldSessionInfo.get().getSessionIdMSB(), oldSessionInfo.get().getSessionIdLSB()));
closeSession(oldSessionInfo.get());
}
logService.log(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());
SessionInfoProto sessionInfo = lwM2MClient.getSession();
transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));
TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
.setSessionInfo(sessionInfo)
.setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
.setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
.setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
.build();
transportService.process(msg, null);
this.initClientTelemetry(lwM2MClient);
this.initAttributes(lwM2MClient);
otaService.init(lwM2MClient);
} catch (LwM2MClientStateException stateException) {
if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) {
log.info("[{}] retry registration due to race condition: [{}].", registration.getEndpoint(), stateException.getState());
@ -410,6 +403,27 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
logService.log(clientContext.getClientByEndpoint(registration.getEndpoint()), LOG_LWM2M_INFO + ": Client is awake!");
//TODO: associate endpointId with device information.
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
if (LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
Lwm2mDeviceProfileTransportConfiguration deviceProfile = clientContext.getProfile(lwM2MClient.getProfileId());
PowerMode powerMode = lwM2MClient.getPowerMode();
if (powerMode == null) {
powerMode = deviceProfile.getClientLwM2mSettings().getPowerMode();
}
if (powerMode.equals(PowerMode.PSM) || powerMode.equals(PowerMode.E_DRX)) {
initAttributes(lwM2MClient);
TransportProtos.TransportToDeviceActorMsg toDeviceActorMsg = TransportProtos.TransportToDeviceActorMsg
.newBuilder()
.setSessionInfo(lwM2MClient.getSession())
.setSendPendingRPC(TransportProtos.SendPendingRPCMsg.newBuilder().build())
.build();
transportService.process(toDeviceActorMsg, TransportServiceCallback.EMPTY);
}
}
}
/**
@ -709,7 +723,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
this.updateResourcesValue(client, resource, path + "/" + resId);
});
}
}
//TODO: review and optimize the logic to minimize number of the requests to device.
@ -920,16 +933,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
}
}
private TransportProtos.GetOtaPackageRequestMsg createOtaPackageRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) {
return TransportProtos.GetOtaPackageRequestMsg.newBuilder()
.setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
.setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
.setTenantIdMSB(sessionInfo.getTenantIdMSB())
.setTenantIdLSB(sessionInfo.getTenantIdLSB())
.setType(nameFwSW)
.build();
}
private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getProfileId());
return profile.getObserveAttr().getKeyName();

View File

@ -50,7 +50,6 @@ import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.MqttTopics;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.msg.EncryptionUtil;
import org.thingsboard.server.common.msg.tools.TbRateLimitsException;
import org.thingsboard.server.common.transport.SessionMsgListener;
@ -819,25 +818,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
.ifPresent(payload -> {
ChannelFuture channelFuture = deviceSessionCtx.getChannel().writeAndFlush(payload);
if (rpcRequest.getPersisted()) {
channelFuture.addListener(future -> {
RpcStatus status;
Throwable t = future.cause();
if (t != null) {
log.error("Failed delivering RPC command to device!", t);
status = RpcStatus.FAILED;
} else if (rpcRequest.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg msg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(rpcRequest.getRequestId())
.setRequestIdLSB(rpcRequest.getRequestIdLSB())
.setRequestIdMSB(rpcRequest.getRequestIdMSB())
.setStatus(status.name())
.build();
transportService.process(deviceSessionCtx.getSessionInfo(), msg, TransportServiceCallback.EMPTY);
});
channelFuture.addListener(future ->
transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequest,
future.cause() != null, TransportServiceCallback.EMPTY)
);
}
});
} catch (Exception e) {

View File

@ -18,7 +18,6 @@ package org.thingsboard.server.transport.mqtt.session;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.transport.SessionMsgListener;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.common.transport.TransportServiceCallback;
@ -100,25 +99,9 @@ public class GatewayDeviceSessionCtx extends MqttDeviceAwareSessionContext imple
payload -> {
ChannelFuture channelFuture = parent.writeAndFlush(payload);
if (request.getPersisted()) {
channelFuture.addListener(future -> {
RpcStatus status;
Throwable t = future.cause();
if (t != null) {
log.error("Failed delivering RPC command to device!", t);
status = RpcStatus.FAILED;
} else if (request.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg msg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(request.getRequestId())
.setRequestIdLSB(request.getRequestIdLSB())
.setRequestIdMSB(request.getRequestIdMSB())
.setStatus(status.name())
.build();
transportService.process(getSessionInfo(), msg, TransportServiceCallback.EMPTY);
});
channelFuture.addListener(future ->
transportService.process(getSessionInfo(), request, future.cause() != null, TransportServiceCallback.EMPTY)
);
}
}
);

View File

@ -26,7 +26,6 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.data.SnmpDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.transport.SessionMsgListener;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
@ -140,22 +139,8 @@ public class DeviceSessionContext extends DeviceAwareSessionContext implements S
@Override
public void onToDeviceRpcRequest(ToDeviceRpcRequestMsg toDeviceRequest) {
snmpTransportContext.getSnmpTransportService().onToDeviceRpcRequest(this, toDeviceRequest);
if (toDeviceRequest.getPersisted()) {
RpcStatus status;
if (toDeviceRequest.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(toDeviceRequest.getRequestId())
.setRequestIdLSB(toDeviceRequest.getRequestIdLSB())
.setRequestIdMSB(toDeviceRequest.getRequestIdMSB())
.setStatus(status.name())
.build();
snmpTransportContext.getTransportService().process(getSessionInfo(), responseMsg, TransportServiceCallback.EMPTY);
}
snmpTransportContext.getSnmpTransportService().onToDeviceRpcRequest(this, toDeviceRequest);
snmpTransportContext.getTransportService().process(getSessionInfo(), toDeviceRequest, false, TransportServiceCallback.EMPTY);
}
@Override

View File

@ -21,7 +21,6 @@ import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGateway
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.common.transport.service.SessionMetaData;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceCredentialsRequestMsg;
@ -30,9 +29,9 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetDeviceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOtaPackageRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOtaPackageResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRequestMsg;
@ -50,8 +49,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCredRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
@ -110,7 +109,7 @@ public interface TransportService {
void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback);
void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDevicePersistedRpcResponseMsg msg, TransportServiceCallback<Void> callback);
void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, boolean isFailedRpc, TransportServiceCallback<Void> callback);
void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback);

View File

@ -16,6 +16,7 @@
package org.thingsboard.server.common.transport.auth;
import lombok.Data;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
@ -30,6 +31,7 @@ public class TransportDeviceInfo {
private DeviceId deviceId;
private String deviceName;
private String deviceType;
private PowerMode powerMode;
private String additionalInfo;
}

View File

@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
@ -42,6 +43,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.rpc.RpcStatus;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.ServiceQueue;
@ -439,6 +441,9 @@ public class DefaultTransportService implements TransportService {
tdi.setAdditionalInfo(di.getAdditionalInfo());
tdi.setDeviceName(di.getDeviceName());
tdi.setDeviceType(di.getDeviceType());
if (di.getPowerMode() != null) {
tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));
}
return tdi;
}
@ -558,11 +563,30 @@ public class DefaultTransportService implements TransportService {
}
@Override
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDevicePersistedRpcResponseMsg msg, TransportServiceCallback<Void> callback) {
if (checkLimits(sessionInfo, msg, callback)) {
reportActivityInternal(sessionInfo);
sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPersistedRpcResponseMsg(msg).build(),
new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));
public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, boolean isFailedRpc, TransportServiceCallback<Void> callback) {
if (msg.getPersisted()) {
RpcStatus status;
if (isFailedRpc) {
status = RpcStatus.FAILED;
} else if (msg.getOneway()) {
status = RpcStatus.SUCCESSFUL;
} else {
status = RpcStatus.DELIVERED;
}
TransportProtos.ToDevicePersistedRpcResponseMsg responseMsg = TransportProtos.ToDevicePersistedRpcResponseMsg.newBuilder()
.setRequestId(msg.getRequestId())
.setRequestIdLSB(msg.getRequestIdLSB())
.setRequestIdMSB(msg.getRequestIdMSB())
.setStatus(status.name())
.build();
if (checkLimits(sessionInfo, responseMsg, callback)) {
reportActivityInternal(sessionInfo);
sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPersistedRpcResponseMsg(responseMsg).build(),
new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY));
}
}
}

View File

@ -151,13 +151,12 @@
</mat-form-field>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>device-profile.lwm2m.power-mode</legend>
<legend class="group-title" translate>device-profile.power-saving-mode</legend>
<mat-form-field class="mat-block" fxFlex>
<mat-label> </mat-label>
<mat-select formControlName="powerMode">
<mat-option *ngFor="let powerMode of powerModeLwM2MTypes"
[value]="powerMode">
{{ powerModeLwM2MNamesMap.get(powerModeLwM2MType[powerMode]) }}
<mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
{{ powerModeTranslationMap.get(powerMod) | translate}}
</mat-option>
</mat-select>
</mat-form-field>

View File

@ -32,7 +32,7 @@ import {
ModelValue,
ObjectLwM2M,
OBSERVE,
OBSERVE_ATTR_TELEMETRY, powerMode, powerModeNames,
OBSERVE_ATTR_TELEMETRY, PowerMode, PowerModeTranslationMap,
RESOURCES,
TELEMETRY
} from './lwm2m-profile-config.models';
@ -72,9 +72,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
sortFunction: (key: string, value: object) => object;
isFwUpdateStrategy: boolean;
isSwUpdateStrategy: boolean;
powerModeLwM2MType = powerMode;
powerModeLwM2MTypes = Object.keys(powerMode);
powerModeLwM2MNamesMap = powerModeNames;
powerMods = Object.values(PowerMode);
powerModeTranslationMap = PowerModeTranslationMap;
get required(): boolean {
return this.requiredValue;
@ -208,7 +207,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
private updateWriteValue = (value: ModelValue): void => {
const fwResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateResource) ?
this.configurationValue.clientLwM2mSettings.fwUpdateResource : '';
const swResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateResource) ?
const swResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.swUpdateResource) ?
this.configurationValue.clientLwM2mSettings.swUpdateResource : '';
this.lwm2mDeviceProfileFormGroup.patchValue({
objectIds: value,

View File

@ -128,17 +128,17 @@ export const securityConfigModeNames = new Map<securityConfigMode, string>(
]
);
export enum powerMode {
export enum PowerMode {
PSM = 'PSM',
DRX = 'DRX',
E_DRX = 'E_DRX'
}
export const powerModeNames = new Map<powerMode, string>(
export const PowerModeTranslationMap = new Map<PowerMode, string>(
[
[powerMode.PSM, 'Power Saving Mode (PSM)'],
[powerMode.DRX, 'Discontinuous Reception (DRX)'],
[powerMode.E_DRX, 'Extended Discontinuous Reception (eDRX)']
[PowerMode.PSM, 'device-profile.power-saving-mode-type.psm'],
[PowerMode.DRX, 'device-profile.power-saving-mode-type.drx'],
[PowerMode.E_DRX, 'device-profile.power-saving-mode-type.edrx']
]
);
@ -187,7 +187,7 @@ export interface ClientLwM2mSettings {
swUpdateStrategy: number;
fwUpdateResource: string;
swUpdateResource: string;
powerMode: powerMode;
powerMode: PowerMode;
}
export interface ObservableAttributes {
@ -260,7 +260,7 @@ function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSettings {
swUpdateStrategy: 1,
fwUpdateResource: DEFAULT_FW_UPDATE_RESOURCE,
swUpdateResource: DEFAULT_SW_UPDATE_RESOURCE,
powerMode: powerMode.DRX
powerMode: PowerMode.DRX
};
}

View File

@ -29,12 +29,12 @@
formControlName="configuration">
</tb-mqtt-device-transport-configuration>
</ng-template>
<!--ng-template [ngSwitchCase]="deviceTransportType.LWM2M">
<ng-template [ngSwitchCase]="deviceTransportType.LWM2M">
<tb-lwm2m-device-transport-configuration
[required]="required"
formControlName="configuration">
</tb-lwm2m-device-transport-configuration>
</ng-template-->
</ng-template>
<ng-template [ngSwitchCase]="deviceTransportType.COAP">
<tb-coap-device-transport-configuration
[required]="required"

View File

@ -16,9 +16,13 @@
-->
<form [formGroup]="lwm2mDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;">
<!--tb-json-object-edit
[required]="required"
label="{{ 'device-profile.transport-type-lwm2m' | translate }}"
formControlName="configuration">
</tb-json-object-edit-->
<mat-form-field class="mat-block" fxFlex>
<mat-label translate>device-profile.power-saving-mode</mat-label>
<mat-select formControlName="powerMode">
<mat-option [value]="null">{{ "device-profile.power-saving-mode-type.default" | translate }}</mat-option>
<mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
{{ powerModeTranslationMap.get(powerMod) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</form>

View File

@ -23,6 +23,7 @@ import {
DeviceTransportConfiguration,
DeviceTransportType, Lwm2mDeviceTransportConfiguration
} from '@shared/models/device.models';
import {PowerMode, PowerModeTranslationMap} from "@home/components/profile/device/lwm2m/lwm2m-profile-config.models";
@Component({
selector: 'tb-lwm2m-device-transport-configuration',
@ -37,6 +38,8 @@ import {
export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit {
lwm2mDeviceTransportConfigurationFormGroup: FormGroup;
powerMods = Object.values(PowerMode);
powerModeTranslationMap = PowerModeTranslationMap;
private requiredValue: boolean;
get required(): boolean {
@ -65,7 +68,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
ngOnInit() {
this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
configuration: [null, Validators.required]
powerMode: [null]
});
this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
@ -82,13 +85,13 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
}
writeValue(value: Lwm2mDeviceTransportConfiguration | null): void {
this.lwm2mDeviceTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
}
private updateModel() {
let configuration: DeviceTransportConfiguration = null;
if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) {
configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue().configuration;
configuration = this.lwm2mDeviceTransportConfigurationFormGroup.getRawValue();
// configuration.type = DeviceTransportType.LWM2M;
}
this.propagateChange(configuration);

View File

@ -200,7 +200,7 @@ export const deviceTransportTypeConfigurationInfoMap = new Map<DeviceTransportTy
DeviceTransportType.LWM2M,
{
hasProfileConfiguration: true,
hasDeviceConfiguration: false,
hasDeviceConfiguration: true,
}
],
[

View File

@ -1213,6 +1213,13 @@
"export-failed-error": "Unable to export device profile: {{error}}",
"device-profile-file": "Device profile file",
"invalid-device-profile-file-error": "Unable to import device profile: Invalid device profile data structure.",
"power-saving-mode": "Power Saving Mode",
"power-saving-mode-type": {
"default": "Use device profile power saving mode",
"psm": "Power Saving Mode (PSM)",
"drx": "Discontinuous Reception (DRX)",
"edrx": "Extended Discontinuous Reception (eDRX)"
},
"lwm2m": {
"object-list": "Object list",
"object-list-empty": "No objects selected.",