diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index e2db45884f..68a016bf4e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -278,7 +278,6 @@ public class DeviceController extends BaseController { try { Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); - //log.info("0 LwM2M CredentialsUpdate start) tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null); logEntityAction(device.getId(), device, device.getCustomerId(), diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceLwm2mController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceLwm2mController.java index 76915fbed1..c38a163af9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceLwm2mController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceLwm2mController.java @@ -15,17 +15,32 @@ */ package org.thingsboard.server.controller; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.lwm2m.LwM2mObject; import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.security.permission.Resource; import java.util.List; +import java.util.Map; @Slf4j @RestController @@ -72,4 +87,40 @@ public class DeviceLwm2mController extends BaseController { throw handleException(e); } } + + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST) + @ResponseBody + public Device saveDeviceWithCredentials(@RequestBody (required=false) Map, Object> deviceWithDeviceCredentials) throws ThingsboardException { + ObjectMapper mapper = new ObjectMapper(); + Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); + DeviceCredentials credentials = checkNotNull(mapper.convertValue( deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class)); + try { + device.setTenantId(getCurrentUser().getTenantId()); + checkEntity(device.getId(), device, Resource.DEVICE); + Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials); + checkNotNull(savedDevice); + + tbClusterService.onDeviceChange(savedDevice, null); + tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(), + savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null); + tbClusterService.onEntityStateChange(savedDevice.getTenantId(), savedDevice.getId(), + device.getId() == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); + + logEntityAction(savedDevice.getId(), savedDevice, + savedDevice.getCustomerId(), + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); + + if (device.getId() == null) { + deviceStateService.onDeviceAdded(savedDevice); + } else { + deviceStateService.onDeviceUpdated(savedDevice); + } + return savedDevice; + } catch (Exception e) { + logEntityAction(emptyId(EntityType.DEVICE), device, + null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); + throw handleException(e); + } + } } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java index 715313538d..a54bb7af7e 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import java.util.List; @@ -45,6 +46,8 @@ public interface DeviceService { Device saveDeviceWithAccessToken(Device device, String accessToken); + Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials); + Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId); Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java index ca8e5f5575..64c608ecb8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java @@ -20,7 +20,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.device.data.DeviceData; -import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; @@ -64,6 +63,17 @@ public class Device extends SearchTextBasedWithAdditionalInfo implemen this.setDeviceData(device.getDeviceData()); } + public Device updateDevice(Device device) { + this.tenantId = device.getTenantId(); + this.customerId = device.getCustomerId(); + this.name = device.getName(); + this.type = device.getType(); + this.label = device.getLabel(); + this.deviceProfileId = device.getDeviceProfileId(); + this.setDeviceData(device.getDeviceData()); + return this; + } + public TenantId getTenantId() { return tenantId; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java index 814cac6d9f..d37b429101 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportHandler.java @@ -45,15 +45,9 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; import javax.annotation.PostConstruct; import java.io.File; import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.Optional; @Slf4j @@ -127,14 +121,19 @@ public class LwM2MTransportHandler{ @PostConstruct public void init() { - LwM2mServerListener lwM2mServerListener = new LwM2mServerListener(lhServerCert, service); - this.lhServerCert.getRegistrationService().addListener(lwM2mServerListener.registrationListener); - this.lhServerCert.getPresenceService().addListener(lwM2mServerListener.presenceListener); - this.lhServerCert.getObservationService().addListener(lwM2mServerListener.observationListener); - lwM2mServerListener = new LwM2mServerListener(lhServerNoSecPskRpk, service); - this.lhServerNoSecPskRpk.getRegistrationService().addListener(lwM2mServerListener.registrationListener); - this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener); - this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener); + try { + LwM2mServerListener lwM2mServerListener = new LwM2mServerListener(lhServerCert, service); + this.lhServerCert.getRegistrationService().addListener(lwM2mServerListener.registrationListener); + this.lhServerCert.getPresenceService().addListener(lwM2mServerListener.presenceListener); + this.lhServerCert.getObservationService().addListener(lwM2mServerListener.observationListener); + lwM2mServerListener = new LwM2mServerListener(lhServerNoSecPskRpk, service); + this.lhServerNoSecPskRpk.getRegistrationService().addListener(lwM2mServerListener.registrationListener); + this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener); + this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener); + } + catch (java.lang.NullPointerException e) { + log.error("init [{}]", e.toString()); + } } public static NetworkConfig getCoapConfig() { @@ -150,7 +149,8 @@ public class LwM2MTransportHandler{ return coapConfig; } - public static String getValueTypeToString (Object value, ResourceModel.Type type) { + public static String getValueTypeToString (Object value, ResourceModel.Type type, int val) { + try{ switch (type) { case STRING: // String case OBJLNK: // ObjectLink @@ -160,16 +160,21 @@ public class LwM2MTransportHandler{ case BOOLEAN: // Boolean return Boolean.toString((Boolean) value); case FLOAT: // Double - return Double.toString((Float)value); + return Double.toString((Double) value); case TIME: // Date - String DATE_FORMAT = "MMM d, yyyy HH:mm a"; - DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); - return formatter.format(new Date(Integer.toUnsignedLong((Integer) value))); + return Long.toString(((Date) value).getTime()); +// String DATE_FORMAT = "MMM d, yyyy HH:mm a"; +// DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); +// return formatter.format(new Date(Integer.toUnsignedLong((Integer) value))); case OPAQUE: // byte[] value, base64 return Hex.encodeHexString((byte[])value); default: return null; } + } catch (Exception e) { + log.error(e.getStackTrace().toString()); + return null; + } } public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) { @@ -305,28 +310,6 @@ public class LwM2MTransportHandler{ } } - /** - * Equals to Map for values - * @param map1 - - * @param map2 - - * @param - - * @return - true if equals - */ - public static > boolean mapsEquals(Map map1, Map map2) { - List values1 = new ArrayList<>(map1.values()); - List values2 = new ArrayList<>(map2.values()); - Collections.sort(values1); - Collections.sort(values2); - return values1.equals(values2); - } - - public static String convertCamelCase (String str) { - str = str.toLowerCase().replace("/[^a-z ]+/g", " "); - str = str.replace("/^(.)|\\s(.)/g", "$1"); - str = str.replace("/[^a-zA-Z]+/g", ""); - return str; - } - public static String splitCamelCaseString(String s){ LinkedList linkedListOut = new LinkedList<>(); LinkedList linkedList = new LinkedList((Arrays.asList(s.split(" ")))); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java index 40edf09986..576415da31 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportRequest.java @@ -20,6 +20,7 @@ import org.eclipse.californium.core.coap.Response; import org.eclipse.leshan.core.attributes.Attribute; import org.eclipse.leshan.core.attributes.AttributeSet; import org.eclipse.leshan.core.model.ResourceModel; +import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.observation.Observation; @@ -50,6 +51,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; +import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PostConstruct; import java.util.ArrayList; @@ -79,16 +81,17 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandle public class LwM2MTransportRequest { private final ExecutorService executorService; private static final String RESPONSE_CHANNEL = "THINGSBOARD_RESP"; + private final LwM2mValueConverterImpl converter; @Autowired LwM2MTransportService service; public LwM2MTransportRequest() { + this.converter = new LwM2mValueConverterImpl(); executorService = Executors.newCachedThreadPool( new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); } - @PostConstruct public void init() { } @@ -115,12 +118,12 @@ public class LwM2MTransportRequest { */ public void sendAllRequest(LeshanServer lwServer, Registration registration, String target, String typeOper, String contentFormatParam, LwM2MClient lwM2MClient, Observation observation, Object params, long timeoutInMs, boolean isDelayedUpdate) { - ResultIds resultIds = new ResultIds(target); + LwM2mPath resultIds = new LwM2mPath(target); if (registration != null && resultIds.getObjectId() >= 0) { DownlinkRequest request = null; ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; - ResourceModel resource = (resultIds.resourceId >= 0) ? (lwM2MClient != null) ? - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.resourceId) : null : null; + ResourceModel resource = (resultIds.getResourceId() !=null && lwM2MClient != null) ? + lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()) : null; ResourceModel.Type resType = (resource == null) ? null : resource.type; boolean resMultiple = (resource == null) ? false : resource.multiple; timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; @@ -132,10 +135,10 @@ public class LwM2MTransportRequest { request = new DiscoverRequest(target); break; case GET_TYPE_OPER_OBSERVE: - if (resultIds.getResourceId() >= 0) { - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId()); - } else if (resultIds.getInstanceId() >= 0) { - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId()); + if (resultIds.isResource()) { + request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); + } else if (resultIds.isObjectInstance()) { + request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId()); } else if (resultIds.getObjectId() >= 0) { request = new ObserveRequest(resultIds.getObjectId()); } @@ -145,7 +148,8 @@ public class LwM2MTransportRequest { break; case POST_TYPE_OPER_EXECUTE: if (params != null && !resMultiple) { - request = new ExecuteRequest(target, LwM2MTransportHandler.getValueTypeToString(params, resType)); +// request = new ExecuteRequest(target, LwM2MTransportHandler.getValueTypeToString(params, resType)); + request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resType, ResourceModel.Type.STRING, resultIds)); } else { request = new ExecuteRequest(target); } @@ -153,11 +157,11 @@ public class LwM2MTransportRequest { case POST_TYPE_OPER_WRITE_REPLACE: // Request to write a String Single-Instance Resource using the TLV content format. if (contentFormat.equals(ContentFormat.TLV) && !resMultiple) { - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), params, resType, registration); + request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resType, registration); } // Mode.REPLACE && Request to write a String Single-Instance Resource using the given content format (TEXT, TLV, JSON) else if (!contentFormat.equals(ContentFormat.TLV) && !resMultiple) { - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), params, resType, registration); + request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resType, registration); } break; case PUT_TYPE_OPER_WRITE_UPDATE: @@ -202,10 +206,10 @@ public class LwM2MTransportRequest { Attribute pmin = new Attribute(MINIMUM_PERIOD, Integer.toUnsignedLong(Integer.valueOf("1"))); Attribute[] attrs = {pmin}; AttributeSet attrSet = new AttributeSet(attrs); - if (resultIds.getResourceId() >= 0) { - request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), attrSet); - } else if (resultIds.getInstanceId() >= 0) { - request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), attrSet); + if (resultIds.isResource()) { + request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), attrSet); + } else if (resultIds.isObjectInstance()) { + request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), attrSet); } else if (resultIds.getObjectId() >= 0) { request = new WriteAttributesRequest(resultIds.getObjectId(), attrSet); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java index 06cf04a88a..861afa02a8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportService.java @@ -64,7 +64,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.Set; @@ -186,9 +185,9 @@ public class LwM2MTransportService { if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) { this.syncSessionsAndProfiles(); } - log.info("Client: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType()); + log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType()); } else { - log.error("Client: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); + log.error("Client close session: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); } } @@ -242,15 +241,15 @@ public class LwM2MTransportService { private void setLwM2MClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) { // #1 Arrays.stream(registration.getObjectLinks()).forEach(url -> { - ResultIds pathIds = new ResultIds(url.getUrl()); - if (pathIds.instanceId > -1 && pathIds.resourceId == -1) { + LwM2mPath pathIds = new LwM2mPath(url.getUrl()); + if (pathIds.isObjectInstance() && !pathIds.isResource()) { lwM2MClient.getPendingRequests().add(url.getUrl()); } }); // #2 Arrays.stream(registration.getObjectLinks()).forEach(url -> { - ResultIds pathIds = new ResultIds(url.getUrl()); - if (pathIds.instanceId > -1 && pathIds.resourceId == -1) { + LwM2mPath pathIds = new LwM2mPath(url.getUrl()); + if (pathIds.isObjectInstance() && !pathIds.isResource()) { lwM2MTransportRequest.sendAllRequest(lwServer, registration, url.getUrl(), GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), lwM2MClient, null, null, this.context.getCtxServer().getTimeout(), false); } @@ -361,10 +360,10 @@ public class LwM2MTransportService { } }); // #2.1 - lwM2MClient.getDelayedRequests().forEach((k, v)->{ + lwM2MClient.getDelayedRequests().forEach((k, v) -> { List listV = new ArrayList(); listV.add(v.getKv()); - this.putDelayedUpdateResourcesClient (lwM2MClient, lwM2MClient.getResourceValue(k), getJsonObject(listV).get(v.getKv().getKey()), k); + this.putDelayedUpdateResourcesClient(lwM2MClient, lwM2MClient.getResourceValue(k), getJsonObject(listV).get(v.getKv().getKey()), k); System.out.printf(" k: %s, v: %s%n, v1: %s%n", k, v.getKv().getStringV(), lwM2MClient.getResourceValue(k)); }); lwM2MClient.getDelayedRequestsId().remove(attributesResponse.getRequestId()); @@ -374,7 +373,7 @@ public class LwM2MTransportService { } } - private void putDelayedUpdateResourcesClient (LwM2MClient lwM2MClient, Object valueOld, Object valueNew, String path){ + private void putDelayedUpdateResourcesClient(LwM2MClient lwM2MClient, Object valueOld, Object valueNew, String path) { if (!valueOld.toString().equals(valueNew.toString())) { lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, ContentFormat.TLV.getName(), lwM2MClient, null, valueNew, this.context.getCtxServer().getTimeout(), @@ -465,18 +464,20 @@ public class LwM2MTransportService { private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set path) { AttrTelemetryObserveValue attrTelemetryObserveValue = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()); attrTelemetryObserveValue.getPostAttributeProfile().forEach(p -> { - ResultIds pathIds = new ResultIds(p.getAsString().toString()); - if (pathIds.getResourceId() > -1) { +// ResultIds pathIds = new ResultIds(p.getAsString().toString()); + LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); + if (pathIds.isResource()) { if (path == null || path.contains(p.getAsString())) { - this.addParameters(p.getAsString().toString(), attributes, registration); + this.addParameters(p.getAsString().toString(), attributes, registration, "attributes"); } } }); attrTelemetryObserveValue.getPostTelemetryProfile().forEach(p -> { - ResultIds pathIds = new ResultIds(p.getAsString().toString()); - if (pathIds.getResourceId() > -1) { +// ResultIds pathIds = new ResultIds(p.getAsString().toString()); + LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString()); + if (pathIds.isResource()) { if (path == null || path.contains(p.getAsString())) { - this.addParameters(p.getAsString().toString(), telemetry, registration); + this.addParameters(p.getAsString().toString(), telemetry, registration, "telemetry"); } } }); @@ -486,13 +487,19 @@ public class LwM2MTransportService { * @param parameters - JsonObject attributes/telemetry * @param registration - Registration LwM2M Client */ - private void addParameters(String path, JsonObject parameters, Registration registration) { + private void addParameters(String path, JsonObject parameters, Registration registration, String nameParam) { JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()).getPostKeyNameProfile(); String resName = String.valueOf(names.get(path)); if (resName != null && !resName.isEmpty()) { - String resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path); - if (resValue != null) { - parameters.addProperty(resName, resValue); + String resValue = null; + try { + resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path); + if (resValue != null) { +// log.info("addParameters Path: [{}] ResValue : [{}] nameParam [{}]", path, lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path), nameParam); + parameters.addProperty(resName, resValue); + } + } catch (Exception e) { + log.error(e.getStackTrace().toString()); } } } @@ -629,42 +636,73 @@ public class LwM2MTransportService { * @param path - resource */ private void onObservationSetResourcesValue(Registration registration, Object value, Map values, String path) { - ResultIds resultIds = new ResultIds(path); - // #1 - LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); - ModelObject modelObject = lwM2MClient.getModelObjects().get(resultIds.getObjectId()); - Map instancesModelObject = modelObject.getInstances(); - LwM2mObjectInstance instanceOld = (instancesModelObject.get(resultIds.instanceId) != null) ? instancesModelObject.get(resultIds.instanceId) : null; - Map resourcesOld = (instanceOld != null) ? instanceOld.getResources() : null; - LwM2mResource resourceOld = (resourcesOld != null && resourcesOld.get(resultIds.getResourceId()) != null) ? resourcesOld.get(resultIds.getResourceId()) : null; - // #2 - LwM2mResource resourceNew; - if (Objects.requireNonNull(resourceOld).isMultiInstances()) { - resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resourceOld.getType()); - } else { - resourceNew = LwM2mSingleResource.newResource(resultIds.getResourceId(), value, resourceOld.getType()); - } - //#3 - Map resourcesNew = new HashMap<>(resourcesOld); - // #4 - resourcesNew.remove(resourceOld); - // #5 - resourcesNew.put(resultIds.getResourceId(), resourceNew); - // #6 - LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.instanceId, resourcesNew.values()); - // #7 - CountDownLatch respLatch = new CountDownLatch(1); - lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.instanceId); - instancesModelObject.put(resultIds.instanceId, instanceNew); - respLatch.countDown(); try { - respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - ex.printStackTrace(); + CountDownLatch respLatch = new CountDownLatch(1); + try { + // #1 + LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); + LwM2mPath resultIds = new LwM2mPath(path); + log.warn("#0 nameDevice: [{}] resultIds: [{}] value: [{}], values: [{}] ", lwM2MClient.getDeviceName(), resultIds, value, values); + ResourceModel.Type resType = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).type; + Map instancesModelObject = (lwM2MClient.getModelObjects().get(resultIds.getObjectId()) != null) ? lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances() : null; + Map resourcesOld = null; + try { + CountDownLatch respResLatch = new CountDownLatch(1); + try { + resourcesOld = (instancesModelObject != null && + instancesModelObject.get(resultIds.getObjectInstanceId()) != null && + instancesModelObject.get(resultIds.getObjectInstanceId()).getResources() != null) ? instancesModelObject.get(resultIds.getObjectInstanceId()).getResources() : null; + + } finally { + respResLatch.countDown(); + } + try { + respResLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + ex.printStackTrace(); + log.error("#1_2 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); + } + } catch (Exception e) { + e.printStackTrace(); + log.error("#1_2_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); + } + LwM2mResource resourceOld = (resourcesOld != null && resourcesOld.get(resultIds.getResourceId()) != null) ? resourcesOld.get(resultIds.getResourceId()) : null; + // #2 + LwM2mResource resourceNew = null; + if ((resourceOld != null && resourceOld.isMultiInstances() && !resourceOld.getValues().equals(values)) || + (resourceOld == null && value == null)) { + resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resType); + } else if ((resourceOld != null && !resourceOld.isMultiInstances() && !resourceOld.getValue().equals(values)) || + (resourceOld == null && value != null)) { + resourceNew = LwM2mSingleResource.newResource(resultIds.getResourceId(), value, resType); + } + if (resourceNew != null) { + //#3 + Map resourcesNew = (resourcesOld == null) ? new HashMap<>() : new HashMap<>(resourcesOld); + // #4 + if ((resourceOld != null)) resourcesNew.remove(resourceOld); + // #5 + resourcesNew.put(resultIds.getResourceId(), resourceNew); + // #6 + LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.getObjectInstanceId(), resourcesNew.values()); + // #7 + lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.getObjectInstanceId()); + instancesModelObject.put(resultIds.getObjectInstanceId(), instanceNew); + Set paths = new HashSet<>(); + paths.add(path); + this.updateAttrTelemetry(registration, false, paths); + } + } finally { + respLatch.countDown(); + } + try { + respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + ex.printStackTrace(); + log.error("#1_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value); + } + } catch (Exception ignored) { } - Set paths = new HashSet<>(); - paths.add(path); - this.updateAttrTelemetry(registration, false, paths); } /** @@ -696,7 +734,7 @@ public class LwM2MTransportService { lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, ContentFormat.TLV.getName(), lwM2MClient, null, value, this.context.getCtxServer().getTimeout(), false); - log.info("[{}] path onAttributeUpdate", path); +// log.info("[{}] path onAttributeUpdate", path); } else { log.error(LOG_LW2M_ERROR + ": Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); String logMsg = String.format(LOG_LW2M_ERROR + ": attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", path, value); @@ -728,7 +766,7 @@ public class LwM2MTransportService { /** * @param profile - - * @param path - + * @param path - * @return true if path isPresent in postAttributeProfile */ private boolean validatePathInAttrProfile(AttrTelemetryObserveValue profile, String path) { @@ -738,7 +776,7 @@ public class LwM2MTransportService { /** * @param profile - - * @param path - + * @param path - * @return true if path isPresent in postAttributeProfile */ private boolean validatePathInTelemetryProfile(AttrTelemetryObserveValue profile, String path) { @@ -793,9 +831,10 @@ public class LwM2MTransportService { * @param request - */ public void onAttributeUpdateOk(Registration registration, String path, WriteRequest request, boolean isDelayedUpdate) { - ResultIds resultIds = new ResultIds(path); +// ResultIds resultIds = new ResultIds(path); + LwM2mPath resultIds = new LwM2mPath(path); LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); - LwM2mResource resource = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances().get(resultIds.getInstanceId()).getResource(resultIds.getResourceId()); + LwM2mResource resource = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances().get(resultIds.getObjectInstanceId()).getResource(resultIds.getResourceId()); if (resource.isMultiInstances()) { this.onObservationSetResourcesValue(registration, null, ((LwM2mSingleResource) request.getNode()).getValues(), path); } else { @@ -996,9 +1035,10 @@ public class LwM2MTransportService { */ private void updateResourceValueObserve(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, Set targets, String typeOper) { targets.forEach(target -> { - ResultIds pathIds = new ResultIds(target); - if (pathIds.resourceId >= 0 && lwM2MClient.getModelObjects().get(pathIds.getObjectId()) - .getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) { +// ResultIds pathIds = new ResultIds(target); + LwM2mPath pathIds = new LwM2mPath(target); + if (pathIds.isResource() && lwM2MClient.getModelObjects().get(pathIds.getObjectId()) + .getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) { if (GET_TYPE_OPER_READ.equals(typeOper)) { lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout(), @@ -1024,9 +1064,10 @@ public class LwM2MTransportService { private ResourceValue getResourceValue(LwM2MClient lwM2MClient, String path) { ResourceValue resourceValue = null; - ResultIds pathIds = new ResultIds(path); - if (pathIds.getResourceId() > -1) { - LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId()); +// ResultIds pathIds = new ResultIds(path); + LwM2mPath pathIds = new LwM2mPath(path); + if (pathIds.isResource()) { + LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()); if (resource.isMultiInstances()) { if (resource.getValues().size() > 0) { resourceValue = new ResourceValue(); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java index 4d63da3580..ea440a33d0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mServerListener.java @@ -44,7 +44,6 @@ public class LwM2mServerListener { @Override public void registered(Registration registration, Registration previousReg, Collection previousObsersations) { - service.onRegistered(lhServer, registration, previousObsersations); } @@ -54,6 +53,7 @@ public class LwM2mServerListener { @Override public void updated(RegistrationUpdate update, Registration updatedRegistration, Registration previousRegistration) { + log.info("updated"); service.updatedReg(lhServer, updatedRegistration); } @@ -63,6 +63,7 @@ public class LwM2mServerListener { @Override public void unregistered(Registration registration, Collection observations, boolean expired, Registration newReg) { + log.info("unregistered"); service.unReg(registration, observations); } @@ -71,11 +72,13 @@ public class LwM2mServerListener { public final PresenceListener presenceListener = new PresenceListener() { @Override public void onSleeping(Registration registration) { + log.info("onSleeping"); service.onSleepingDev(registration); } @Override public void onAwake(Registration registration) { + log.info("onAwake"); service.onAwakeDev(registration); } }; @@ -92,8 +95,10 @@ public class LwM2mServerListener { if (registration != null) { try { service.onObservationResponse(registration, observation.getPath().toString(), response); - } catch (java.lang.NullPointerException e) { - log.error(e.toString()); + } catch (Exception e) { + e.printStackTrace(); + log.error("onResponse"); + } } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java index 5fd63fa53f..4c0f314bc1 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2MClient.java @@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.node.LwM2mObjectInstance; +import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.core.response.LwM2mResponse; import org.eclipse.leshan.core.response.ReadResponse; import org.eclipse.leshan.core.util.Hex; @@ -29,12 +30,11 @@ import org.eclipse.leshan.server.security.SecurityInfo; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportService; -import org.thingsboard.server.transport.lwm2m.server.ResultIds; +import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; -import java.util.UUID; import java.util.Map; import java.util.Set; -import java.util.Collection; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -61,6 +61,7 @@ public class LwM2MClient implements Cloneable { private Map delayedRequests; private Set delayedRequestsId; private Map responses; + private final LwM2mValueConverterImpl converter; public Object clone() throws CloneNotSupportedException { return super.clone(); @@ -81,11 +82,13 @@ public class LwM2MClient implements Cloneable { * Key , response instance -> resources: value...> */ this.responses = new ConcurrentHashMap<>(); + this.converter = new LwM2mValueConverterImpl(); } /** - * Fill with data -> Model client - * @param path - + * Fill with data -> Model client + * + * @param path - * @param response - */ public void onSuccessHandler(String path, LwM2mResponse response) { @@ -99,9 +102,9 @@ public class LwM2MClient implements Cloneable { private void initValue() { this.responses.forEach((key, resp) -> { - ResultIds pathIds = new ResultIds(key); - if (pathIds.getObjectId() > -1) { - ObjectModel objectModel = ((Collection) this.lwServer.getModelProvider().getObjectModel(registration).getObjectModels()).stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0); + LwM2mPath pathIds = new LwM2mPath(key); + if (pathIds.isObject() || pathIds.isObjectInstance() || pathIds.isResource()) { + ObjectModel objectModel = this.lwServer.getModelProvider().getObjectModel(registration).getObjectModels().stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0); if (this.modelObjects.get(pathIds.getObjectId()) != null) { this.modelObjects.get(pathIds.getObjectId()).getInstances().put(((ReadResponse) resp).getContent().getId(), (LwM2mObjectInstance) ((ReadResponse) resp).getContent()); } else { @@ -122,30 +125,39 @@ public class LwM2MClient implements Cloneable { } public ResourceModel.Operations getOperation(String path) { - ResultIds resultIds = new ResultIds(path); - return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).operations : ResourceModel.Operations.NONE; + LwM2mPath resultIds = new LwM2mPath(path); + return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? + this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).operations : + ResourceModel.Operations.NONE; } - public String getResourceName (String path) { - ResultIds resultIds = new ResultIds(path); + public String getResourceName(String path) { + LwM2mPath resultIds = new LwM2mPath(path); return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).name : ""; } /** * @param path - path resource * @return - value of Resource or null - */public String getResourceValue(String path) { + */ + public String getResourceValue(String path) { String resValue = null; - ResultIds pathIds = new ResultIds(path); + LwM2mPath pathIds = new LwM2mPath(path); ModelObject modelObject = this.getModelObjects().get(pathIds.getObjectId()); - if (modelObject != null && modelObject.getInstances().get(pathIds.getInstanceId()) != null) { - LwM2mObjectInstance instance = modelObject.getInstances().get(pathIds.getInstanceId()); + + if (modelObject != null && modelObject.getInstances().get(pathIds.getObjectInstanceId()) != null) { + LwM2mObjectInstance instance = modelObject.getInstances().get(pathIds.getObjectInstanceId()); if (instance.getResource(pathIds.getResourceId()) != null) { - resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ? - Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() : - (instance.getResource(pathIds.getResourceId()).isMultiInstances()) ? - instance.getResource(pathIds.getResourceId()).getValues().toString() : - instance.getResource(pathIds.getResourceId()).getValue().toString(); + try { + resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ? + Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() : + (instance.getResource(pathIds.getResourceId()).isMultiInstances()) ? + instance.getResource(pathIds.getResourceId()).getValues().toString() : +// getValueTypeToString(instance.getResource(pathIds.getResourceId()).getValue(), instance.getResource(pathIds.getResourceId()).getType()); + (String) converter.convertValue(instance.getResource(pathIds.getResourceId()).getValue(), instance.getResource(pathIds.getResourceId()).getType(), ResourceModel.Type.STRING, pathIds); + } catch (Exception e) { + log.warn("getResourceValue [{}]", e.getStackTrace().toString()); + } } } return resValue; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ModelObject.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ModelObject.java index 03dcc5013f..fb0ce90e78 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ModelObject.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/ModelObject.java @@ -21,7 +21,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance; import java.util.Map; @Data -public class ModelObject { +public class ModelObject implements Cloneable { /** * model one on all instance * for each instance only id resource with parameters of resources (observe, attr, telemetry) @@ -38,4 +38,8 @@ public class ModelObject { LwM2mObjectInstance instance = this.instances.get(id); return this.instances.remove(id, instance); } + + public ModelObject clone() throws CloneNotSupportedException { + return (ModelObject) super.clone(); + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index 9024ed0ee2..a35691160c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -177,10 +177,40 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe return doSaveDevice(device, null); } + @CacheEvict(cacheNames = DEVICE_CACHE, key = "{#device.tenantId, #device.name}") + @Override + public Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials) { + if (device.getId() == null) { + Device deviceWithName = this.findDeviceByTenantIdAndName(device.getTenantId(), device.getName()); + device = deviceWithName == null ? device : deviceWithName.updateDevice(device); + } + Device savedDevice = this.saveDeviceWithoutCredentials(device); + deviceCredentials.setDeviceId(savedDevice.getId()); + if (device.getId() == null) { + deviceCredentials = deviceCredentialsService.createDeviceCredentials(savedDevice.getTenantId(), deviceCredentials); + } + else { + deviceCredentials.setId(deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), savedDevice.getId()).getId()); + deviceCredentials = deviceCredentialsService.updateDeviceCredentials(device.getTenantId(), deviceCredentials); + } + return savedDevice; + } + private Device doSaveDevice(Device device, String accessToken) { + Device savedDevice = this.saveDeviceWithoutCredentials(device); + if (device.getId() == null) { + DeviceCredentials deviceCredentials = new DeviceCredentials(); + deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId())); + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); + deviceCredentials.setCredentialsId(!StringUtils.isEmpty(accessToken) ? accessToken : RandomStringUtils.randomAlphanumeric(20)); + deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials); + } + return savedDevice; + } + + private Device saveDeviceWithoutCredentials(Device device) { log.trace("Executing saveDevice [{}]", device); deviceValidator.validate(device, Device::getTenantId); - Device savedDevice; try { DeviceProfile deviceProfile; if (device.getDeviceProfileId() == null) { @@ -198,8 +228,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe } device.setType(deviceProfile.getName()); device.setDeviceData(syncDeviceData(deviceProfile, device.getDeviceData())); - - savedDevice = deviceDao.save(device.getTenantId(), device); + return deviceDao.save(device.getTenantId(), device); } catch (Exception t) { ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_name_unq_key")) { @@ -208,14 +237,6 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe throw t; } } - if (device.getId() == null) { - DeviceCredentials deviceCredentials = new DeviceCredentials(); - deviceCredentials.setDeviceId(new DeviceId(savedDevice.getUuidId())); - deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); - deviceCredentials.setCredentialsId(!StringUtils.isEmpty(accessToken) ? accessToken : RandomStringUtils.randomAlphanumeric(20)); - deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials); - } - return savedDevice; } private DeviceData syncDeviceData(DeviceProfile deviceProfile, DeviceData deviceData) { @@ -530,7 +551,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @Override protected void validateCreate(TenantId tenantId, Device device) { DefaultTenantProfileConfiguration profileConfiguration = - (DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration(); + (DefaultTenantProfileConfiguration) tenantProfileCache.get(tenantId).getProfileData().getConfiguration(); long maxDevices = profileConfiguration.getMaxDevices(); validateNumberOfEntitiesPerTenant(tenantId, deviceDao, maxDevices, EntityType.DEVICE); } diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index e79bb2b713..17fd9c83c5 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -121,6 +121,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -1091,6 +1092,24 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { return restTemplate.postForEntity(baseURL + "/api/device/credentials", deviceCredentials, DeviceCredentials.class).getBody(); } + public Optional saveDeviceWithCredentials(Device device, DeviceCredentials credentials) { + try { + Map, Object> deviceCredentials = new ConcurrentHashMap<>(); + deviceCredentials.put(Device.class, device); + deviceCredentials.put(DeviceCredentials.class, credentials); +// return restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class).getBody(); + ResponseEntity deviceOpt = restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class); + return Optional.ofNullable(deviceOpt.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public PageData getTenantDevices(String type, PageLink pageLink) { Map params = new HashMap<>(); params.put("type", type);