Lwm2m: backEnd: add saveDeviceWithCredential

This commit is contained in:
nickAS21 2020-12-22 16:23:03 +02:00
parent ca46f5fb75
commit 1150d4e4f3
12 changed files with 313 additions and 161 deletions

View File

@ -278,7 +278,6 @@ public class DeviceController extends BaseController {
try { try {
Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS);
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials));
//log.info("0 LwM2M CredentialsUpdate start)
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null); tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null);
logEntityAction(device.getId(), device, logEntityAction(device.getId(), device,
device.getCustomerId(), device.getCustomerId(),

View File

@ -15,17 +15,32 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize; 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.exception.ThingsboardException;
import org.thingsboard.server.common.data.lwm2m.LwM2mObject; import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; 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.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Resource;
import java.util.List; import java.util.List;
import java.util.Map;
@Slf4j @Slf4j
@RestController @RestController
@ -72,4 +87,40 @@ public class DeviceLwm2mController extends BaseController {
throw handleException(e); 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<Class<?>, 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);
}
}
} }

View File

@ -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.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; 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 org.thingsboard.server.dao.device.provision.ProvisionRequest;
import java.util.List; import java.util.List;
@ -45,6 +46,8 @@ public interface DeviceService {
Device saveDeviceWithAccessToken(Device device, String accessToken); Device saveDeviceWithAccessToken(Device device, String accessToken);
Device saveDeviceWithCredentials(Device device, DeviceCredentials deviceCredentials);
Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId); Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, CustomerId customerId);
Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId); Device unassignDeviceFromCustomer(TenantId tenantId, DeviceId deviceId);

View File

@ -20,7 +20,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.device.data.DeviceData; 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.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.DeviceProfileId;
@ -64,6 +63,17 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.setDeviceData(device.getDeviceData()); 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() { public TenantId getTenantId() {
return tenantId; return tenantId;
} }

View File

@ -45,15 +45,9 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
@Slf4j @Slf4j
@ -127,6 +121,7 @@ public class LwM2MTransportHandler{
@PostConstruct @PostConstruct
public void init() { public void init() {
try {
LwM2mServerListener lwM2mServerListener = new LwM2mServerListener(lhServerCert, service); LwM2mServerListener lwM2mServerListener = new LwM2mServerListener(lhServerCert, service);
this.lhServerCert.getRegistrationService().addListener(lwM2mServerListener.registrationListener); this.lhServerCert.getRegistrationService().addListener(lwM2mServerListener.registrationListener);
this.lhServerCert.getPresenceService().addListener(lwM2mServerListener.presenceListener); this.lhServerCert.getPresenceService().addListener(lwM2mServerListener.presenceListener);
@ -136,6 +131,10 @@ public class LwM2MTransportHandler{
this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener); this.lhServerNoSecPskRpk.getPresenceService().addListener(lwM2mServerListener.presenceListener);
this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener); this.lhServerNoSecPskRpk.getObservationService().addListener(lwM2mServerListener.observationListener);
} }
catch (java.lang.NullPointerException e) {
log.error("init [{}]", e.toString());
}
}
public static NetworkConfig getCoapConfig() { public static NetworkConfig getCoapConfig() {
NetworkConfig coapConfig; NetworkConfig coapConfig;
@ -150,7 +149,8 @@ public class LwM2MTransportHandler{
return coapConfig; 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) { switch (type) {
case STRING: // String case STRING: // String
case OBJLNK: // ObjectLink case OBJLNK: // ObjectLink
@ -160,16 +160,21 @@ public class LwM2MTransportHandler{
case BOOLEAN: // Boolean case BOOLEAN: // Boolean
return Boolean.toString((Boolean) value); return Boolean.toString((Boolean) value);
case FLOAT: // Double case FLOAT: // Double
return Double.toString((Float)value); return Double.toString((Double) value);
case TIME: // Date case TIME: // Date
String DATE_FORMAT = "MMM d, yyyy HH:mm a"; return Long.toString(((Date) value).getTime());
DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); // String DATE_FORMAT = "MMM d, yyyy HH:mm a";
return formatter.format(new Date(Integer.toUnsignedLong((Integer) value))); // DateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
// return formatter.format(new Date(Integer.toUnsignedLong((Integer) value)));
case OPAQUE: // byte[] value, base64 case OPAQUE: // byte[] value, base64
return Hex.encodeHexString((byte[])value); return Hex.encodeHexString((byte[])value);
default: default:
return null; return null;
} }
} catch (Exception e) {
log.error(e.getStackTrace().toString());
return null;
}
} }
public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) { public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) {
@ -305,28 +310,6 @@ public class LwM2MTransportHandler{
} }
} }
/**
* Equals to Map for values
* @param map1 -
* @param map2 -
* @param <V> -
* @return - true if equals
*/
public static <V extends Comparable<V>> boolean mapsEquals(Map<?,V> map1, Map<?,V> map2) {
List<V> values1 = new ArrayList<>(map1.values());
List<V> 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){ public static String splitCamelCaseString(String s){
LinkedList<String> linkedListOut = new LinkedList<>(); LinkedList<String> linkedListOut = new LinkedList<>();
LinkedList<String> linkedList = new LinkedList<String>((Arrays.asList(s.split(" ")))); LinkedList<String> linkedList = new LinkedList<String>((Arrays.asList(s.split(" "))));

View File

@ -20,6 +20,7 @@ import org.eclipse.californium.core.coap.Response;
import org.eclipse.leshan.core.attributes.Attribute; import org.eclipse.leshan.core.attributes.Attribute;
import org.eclipse.leshan.core.attributes.AttributeSet; import org.eclipse.leshan.core.attributes.AttributeSet;
import org.eclipse.leshan.core.model.ResourceModel; 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.LwM2mSingleResource;
import org.eclipse.leshan.core.node.ObjectLink; import org.eclipse.leshan.core.node.ObjectLink;
import org.eclipse.leshan.core.observation.Observation; 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.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClient;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.ArrayList; import java.util.ArrayList;
@ -79,16 +81,17 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandle
public class LwM2MTransportRequest { public class LwM2MTransportRequest {
private final ExecutorService executorService; private final ExecutorService executorService;
private static final String RESPONSE_CHANNEL = "THINGSBOARD_RESP"; private static final String RESPONSE_CHANNEL = "THINGSBOARD_RESP";
private final LwM2mValueConverterImpl converter;
@Autowired @Autowired
LwM2MTransportService service; LwM2MTransportService service;
public LwM2MTransportRequest() { public LwM2MTransportRequest() {
this.converter = new LwM2mValueConverterImpl();
executorService = Executors.newCachedThreadPool( executorService = Executors.newCachedThreadPool(
new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
} }
@PostConstruct @PostConstruct
public void init() { public void init() {
} }
@ -115,12 +118,12 @@ public class LwM2MTransportRequest {
*/ */
public void sendAllRequest(LeshanServer lwServer, Registration registration, String target, String typeOper, String contentFormatParam, public void sendAllRequest(LeshanServer lwServer, Registration registration, String target, String typeOper, String contentFormatParam,
LwM2MClient lwM2MClient, Observation observation, Object params, long timeoutInMs, boolean isDelayedUpdate) { 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) { if (registration != null && resultIds.getObjectId() >= 0) {
DownlinkRequest request = null; DownlinkRequest request = null;
ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;
ResourceModel resource = (resultIds.resourceId >= 0) ? (lwM2MClient != null) ? ResourceModel resource = (resultIds.getResourceId() !=null && lwM2MClient != null) ?
lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.resourceId) : null : null; lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()) : null;
ResourceModel.Type resType = (resource == null) ? null : resource.type; ResourceModel.Type resType = (resource == null) ? null : resource.type;
boolean resMultiple = (resource == null) ? false : resource.multiple; boolean resMultiple = (resource == null) ? false : resource.multiple;
timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
@ -132,10 +135,10 @@ public class LwM2MTransportRequest {
request = new DiscoverRequest(target); request = new DiscoverRequest(target);
break; break;
case GET_TYPE_OPER_OBSERVE: case GET_TYPE_OPER_OBSERVE:
if (resultIds.getResourceId() >= 0) { if (resultIds.isResource()) {
request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId()); request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
} else if (resultIds.getInstanceId() >= 0) { } else if (resultIds.isObjectInstance()) {
request = new ObserveRequest(resultIds.getObjectId(), resultIds.getInstanceId()); request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId());
} else if (resultIds.getObjectId() >= 0) { } else if (resultIds.getObjectId() >= 0) {
request = new ObserveRequest(resultIds.getObjectId()); request = new ObserveRequest(resultIds.getObjectId());
} }
@ -145,7 +148,8 @@ public class LwM2MTransportRequest {
break; break;
case POST_TYPE_OPER_EXECUTE: case POST_TYPE_OPER_EXECUTE:
if (params != null && !resMultiple) { 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 { } else {
request = new ExecuteRequest(target); request = new ExecuteRequest(target);
} }
@ -153,11 +157,11 @@ public class LwM2MTransportRequest {
case POST_TYPE_OPER_WRITE_REPLACE: case POST_TYPE_OPER_WRITE_REPLACE:
// Request to write a <b>String Single-Instance Resource</b> using the TLV content format. // Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
if (contentFormat.equals(ContentFormat.TLV) && !resMultiple) { 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 <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON) // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON)
else if (!contentFormat.equals(ContentFormat.TLV) && !resMultiple) { 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; break;
case PUT_TYPE_OPER_WRITE_UPDATE: 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 pmin = new Attribute(MINIMUM_PERIOD, Integer.toUnsignedLong(Integer.valueOf("1")));
Attribute[] attrs = {pmin}; Attribute[] attrs = {pmin};
AttributeSet attrSet = new AttributeSet(attrs); AttributeSet attrSet = new AttributeSet(attrs);
if (resultIds.getResourceId() >= 0) { if (resultIds.isResource()) {
request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), resultIds.getResourceId(), attrSet); request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(), attrSet);
} else if (resultIds.getInstanceId() >= 0) { } else if (resultIds.isObjectInstance()) {
request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getInstanceId(), attrSet); request = new WriteAttributesRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), attrSet);
} else if (resultIds.getObjectId() >= 0) { } else if (resultIds.getObjectId() >= 0) {
request = new WriteAttributesRequest(resultIds.getObjectId(), attrSet); request = new WriteAttributesRequest(resultIds.getObjectId(), attrSet);
} }

View File

@ -64,7 +64,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
@ -186,9 +185,9 @@ public class LwM2MTransportService {
if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) { if (lwM2mInMemorySecurityStore.getProfiles().size() > 0) {
this.syncSessionsAndProfiles(); 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 { } 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) { private void setLwM2MClient(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient) {
// #1 // #1
Arrays.stream(registration.getObjectLinks()).forEach(url -> { Arrays.stream(registration.getObjectLinks()).forEach(url -> {
ResultIds pathIds = new ResultIds(url.getUrl()); LwM2mPath pathIds = new LwM2mPath(url.getUrl());
if (pathIds.instanceId > -1 && pathIds.resourceId == -1) { if (pathIds.isObjectInstance() && !pathIds.isResource()) {
lwM2MClient.getPendingRequests().add(url.getUrl()); lwM2MClient.getPendingRequests().add(url.getUrl());
} }
}); });
// #2 // #2
Arrays.stream(registration.getObjectLinks()).forEach(url -> { Arrays.stream(registration.getObjectLinks()).forEach(url -> {
ResultIds pathIds = new ResultIds(url.getUrl()); LwM2mPath pathIds = new LwM2mPath(url.getUrl());
if (pathIds.instanceId > -1 && pathIds.resourceId == -1) { if (pathIds.isObjectInstance() && !pathIds.isResource()) {
lwM2MTransportRequest.sendAllRequest(lwServer, registration, url.getUrl(), GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), lwM2MTransportRequest.sendAllRequest(lwServer, registration, url.getUrl(), GET_TYPE_OPER_READ, ContentFormat.TLV.getName(),
lwM2MClient, null, null, this.context.getCtxServer().getTimeout(), false); lwM2MClient, null, null, this.context.getCtxServer().getTimeout(), false);
} }
@ -465,18 +464,20 @@ public class LwM2MTransportService {
private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) { private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) {
AttrTelemetryObserveValue attrTelemetryObserveValue = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()); AttrTelemetryObserveValue attrTelemetryObserveValue = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid());
attrTelemetryObserveValue.getPostAttributeProfile().forEach(p -> { attrTelemetryObserveValue.getPostAttributeProfile().forEach(p -> {
ResultIds pathIds = new ResultIds(p.getAsString().toString()); // ResultIds pathIds = new ResultIds(p.getAsString().toString());
if (pathIds.getResourceId() > -1) { LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString());
if (pathIds.isResource()) {
if (path == null || path.contains(p.getAsString())) { 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 -> { attrTelemetryObserveValue.getPostTelemetryProfile().forEach(p -> {
ResultIds pathIds = new ResultIds(p.getAsString().toString()); // ResultIds pathIds = new ResultIds(p.getAsString().toString());
if (pathIds.getResourceId() > -1) { LwM2mPath pathIds = new LwM2mPath(p.getAsString().toString());
if (pathIds.isResource()) {
if (path == null || path.contains(p.getAsString())) { if (path == null || path.contains(p.getAsString())) {
this.addParameters(p.getAsString().toString(), telemetry, registration); this.addParameters(p.getAsString().toString(), telemetry, registration, "telemetry");
} }
} }
}); });
@ -486,14 +487,20 @@ public class LwM2MTransportService {
* @param parameters - JsonObject attributes/telemetry * @param parameters - JsonObject attributes/telemetry
* @param registration - Registration LwM2M Client * @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(); JsonObject names = lwM2mInMemorySecurityStore.getProfiles().get(lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getProfileUuid()).getPostKeyNameProfile();
String resName = String.valueOf(names.get(path)); String resName = String.valueOf(names.get(path));
if (resName != null && !resName.isEmpty()) { if (resName != null && !resName.isEmpty()) {
String resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path); String resValue = null;
try {
resValue = lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path);
if (resValue != null) { if (resValue != null) {
// log.info("addParameters Path: [{}] ResValue : [{}] nameParam [{}]", path, lwM2mInMemorySecurityStore.getSessions().get(registration.getId()).getResourceValue(path), nameParam);
parameters.addProperty(resName, resValue); parameters.addProperty(resName, resValue);
} }
} catch (Exception e) {
log.error(e.getStackTrace().toString());
}
} }
} }
@ -629,42 +636,73 @@ public class LwM2MTransportService {
* @param path - resource * @param path - resource
*/ */
private void onObservationSetResourcesValue(Registration registration, Object value, Map<Integer, ?> values, String path) { private void onObservationSetResourcesValue(Registration registration, Object value, Map<Integer, ?> values, String path) {
ResultIds resultIds = new ResultIds(path); try {
CountDownLatch respLatch = new CountDownLatch(1);
try {
// #1 // #1
LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId()); LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId());
ModelObject modelObject = lwM2MClient.getModelObjects().get(resultIds.getObjectId()); LwM2mPath resultIds = new LwM2mPath(path);
Map<Integer, LwM2mObjectInstance> instancesModelObject = modelObject.getInstances(); log.warn("#0 nameDevice: [{}] resultIds: [{}] value: [{}], values: [{}] ", lwM2MClient.getDeviceName(), resultIds, value, values);
LwM2mObjectInstance instanceOld = (instancesModelObject.get(resultIds.instanceId) != null) ? instancesModelObject.get(resultIds.instanceId) : null; ResourceModel.Type resType = lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).type;
Map<Integer, LwM2mResource> resourcesOld = (instanceOld != null) ? instanceOld.getResources() : null; Map<Integer, LwM2mObjectInstance> instancesModelObject = (lwM2MClient.getModelObjects().get(resultIds.getObjectId()) != null) ? lwM2MClient.getModelObjects().get(resultIds.getObjectId()).getInstances() : null;
Map<Integer, LwM2mResource> 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; LwM2mResource resourceOld = (resourcesOld != null && resourcesOld.get(resultIds.getResourceId()) != null) ? resourcesOld.get(resultIds.getResourceId()) : null;
// #2 // #2
LwM2mResource resourceNew; LwM2mResource resourceNew = null;
if (Objects.requireNonNull(resourceOld).isMultiInstances()) { if ((resourceOld != null && resourceOld.isMultiInstances() && !resourceOld.getValues().equals(values)) ||
resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resourceOld.getType()); (resourceOld == null && value == null)) {
} else { resourceNew = LwM2mMultipleResource.newResource(resultIds.getResourceId(), values, resType);
resourceNew = LwM2mSingleResource.newResource(resultIds.getResourceId(), value, resourceOld.getType()); } 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 //#3
Map<Integer, LwM2mResource> resourcesNew = new HashMap<>(resourcesOld); Map<Integer, LwM2mResource> resourcesNew = (resourcesOld == null) ? new HashMap<>() : new HashMap<>(resourcesOld);
// #4 // #4
resourcesNew.remove(resourceOld); if ((resourceOld != null)) resourcesNew.remove(resourceOld);
// #5 // #5
resourcesNew.put(resultIds.getResourceId(), resourceNew); resourcesNew.put(resultIds.getResourceId(), resourceNew);
// #6 // #6
LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.instanceId, resourcesNew.values()); LwM2mObjectInstance instanceNew = new LwM2mObjectInstance(resultIds.getObjectInstanceId(), resourcesNew.values());
// #7 // #7
CountDownLatch respLatch = new CountDownLatch(1); lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.getObjectInstanceId());
lwM2MClient.getModelObjects().get(resultIds.getObjectId()).removeInstance(resultIds.instanceId); instancesModelObject.put(resultIds.getObjectInstanceId(), instanceNew);
instancesModelObject.put(resultIds.instanceId, instanceNew); Set<String> paths = new HashSet<>();
paths.add(path);
this.updateAttrTelemetry(registration, false, paths);
}
} finally {
respLatch.countDown(); respLatch.countDown();
}
try { try {
respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); respLatch.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
ex.printStackTrace(); ex.printStackTrace();
log.error("#1_1 Update ResourcesValue after Observation in CountDownLatch is unsuccessfully path: [{}] value: [{}]", path, value);
}
} catch (Exception ignored) {
} }
Set<String> 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, lwM2MTransportRequest.sendAllRequest(lwM2MClient.getLwServer(), lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE,
ContentFormat.TLV.getName(), lwM2MClient, null, value, this.context.getCtxServer().getTimeout(), ContentFormat.TLV.getName(), lwM2MClient, null, value, this.context.getCtxServer().getTimeout(),
false); false);
log.info("[{}] path onAttributeUpdate", path); // log.info("[{}] path onAttributeUpdate", path);
} else { } else {
log.error(LOG_LW2M_ERROR + ": Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); 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); String logMsg = String.format(LOG_LW2M_ERROR + ": attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", path, value);
@ -793,9 +831,10 @@ public class LwM2MTransportService {
* @param request - * @param request -
*/ */
public void onAttributeUpdateOk(Registration registration, String path, WriteRequest request, boolean isDelayedUpdate) { 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()); 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()) { if (resource.isMultiInstances()) {
this.onObservationSetResourcesValue(registration, null, ((LwM2mSingleResource) request.getNode()).getValues(), path); this.onObservationSetResourcesValue(registration, null, ((LwM2mSingleResource) request.getNode()).getValues(), path);
} else { } else {
@ -996,9 +1035,10 @@ public class LwM2MTransportService {
*/ */
private void updateResourceValueObserve(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, Set<String> targets, String typeOper) { private void updateResourceValueObserve(LeshanServer lwServer, Registration registration, LwM2MClient lwM2MClient, Set<String> targets, String typeOper) {
targets.forEach(target -> { targets.forEach(target -> {
ResultIds pathIds = new ResultIds(target); // ResultIds pathIds = new ResultIds(target);
if (pathIds.resourceId >= 0 && lwM2MClient.getModelObjects().get(pathIds.getObjectId()) LwM2mPath pathIds = new LwM2mPath(target);
.getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) { if (pathIds.isResource() && lwM2MClient.getModelObjects().get(pathIds.getObjectId())
.getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId()).getValue() != null) {
if (GET_TYPE_OPER_READ.equals(typeOper)) { if (GET_TYPE_OPER_READ.equals(typeOper)) {
lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper, lwM2MTransportRequest.sendAllRequest(lwServer, registration, target, typeOper,
ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout(), ContentFormat.TLV.getName(), null, null, null, this.context.getCtxServer().getTimeout(),
@ -1024,9 +1064,10 @@ public class LwM2MTransportService {
private ResourceValue getResourceValue(LwM2MClient lwM2MClient, String path) { private ResourceValue getResourceValue(LwM2MClient lwM2MClient, String path) {
ResourceValue resourceValue = null; ResourceValue resourceValue = null;
ResultIds pathIds = new ResultIds(path); // ResultIds pathIds = new ResultIds(path);
if (pathIds.getResourceId() > -1) { LwM2mPath pathIds = new LwM2mPath(path);
LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getInstanceId()).getResource(pathIds.getResourceId()); if (pathIds.isResource()) {
LwM2mResource resource = lwM2MClient.getModelObjects().get(pathIds.getObjectId()).getInstances().get(pathIds.getObjectInstanceId()).getResource(pathIds.getResourceId());
if (resource.isMultiInstances()) { if (resource.isMultiInstances()) {
if (resource.getValues().size() > 0) { if (resource.getValues().size() > 0) {
resourceValue = new ResourceValue(); resourceValue = new ResourceValue();

View File

@ -44,7 +44,6 @@ public class LwM2mServerListener {
@Override @Override
public void registered(Registration registration, Registration previousReg, public void registered(Registration registration, Registration previousReg,
Collection<Observation> previousObsersations) { Collection<Observation> previousObsersations) {
service.onRegistered(lhServer, registration, previousObsersations); service.onRegistered(lhServer, registration, previousObsersations);
} }
@ -54,6 +53,7 @@ public class LwM2mServerListener {
@Override @Override
public void updated(RegistrationUpdate update, Registration updatedRegistration, public void updated(RegistrationUpdate update, Registration updatedRegistration,
Registration previousRegistration) { Registration previousRegistration) {
log.info("updated");
service.updatedReg(lhServer, updatedRegistration); service.updatedReg(lhServer, updatedRegistration);
} }
@ -63,6 +63,7 @@ public class LwM2mServerListener {
@Override @Override
public void unregistered(Registration registration, Collection<Observation> observations, boolean expired, public void unregistered(Registration registration, Collection<Observation> observations, boolean expired,
Registration newReg) { Registration newReg) {
log.info("unregistered");
service.unReg(registration, observations); service.unReg(registration, observations);
} }
@ -71,11 +72,13 @@ public class LwM2mServerListener {
public final PresenceListener presenceListener = new PresenceListener() { public final PresenceListener presenceListener = new PresenceListener() {
@Override @Override
public void onSleeping(Registration registration) { public void onSleeping(Registration registration) {
log.info("onSleeping");
service.onSleepingDev(registration); service.onSleepingDev(registration);
} }
@Override @Override
public void onAwake(Registration registration) { public void onAwake(Registration registration) {
log.info("onAwake");
service.onAwakeDev(registration); service.onAwakeDev(registration);
} }
}; };
@ -92,8 +95,10 @@ public class LwM2mServerListener {
if (registration != null) { if (registration != null) {
try { try {
service.onObservationResponse(registration, observation.getPath().toString(), response); service.onObservationResponse(registration, observation.getPath().toString(), response);
} catch (java.lang.NullPointerException e) { } catch (Exception e) {
log.error(e.toString()); e.printStackTrace();
log.error("onResponse");
} }
} }
} }

View File

@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.model.ObjectModel; import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel; import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mObjectInstance; 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.LwM2mResponse;
import org.eclipse.leshan.core.response.ReadResponse; import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.util.Hex; 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;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportService; 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.Map;
import java.util.Set; import java.util.Set;
import java.util.Collection; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -61,6 +61,7 @@ public class LwM2MClient implements Cloneable {
private Map<String, TransportProtos.TsKvProto> delayedRequests; private Map<String, TransportProtos.TsKvProto> delayedRequests;
private Set<Integer> delayedRequestsId; private Set<Integer> delayedRequestsId;
private Map<String, LwM2mResponse> responses; private Map<String, LwM2mResponse> responses;
private final LwM2mValueConverterImpl converter;
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
return super.clone(); return super.clone();
@ -81,10 +82,12 @@ public class LwM2MClient implements Cloneable {
* Key <objectId>, response<Value -> instance -> resources: value...> * Key <objectId>, response<Value -> instance -> resources: value...>
*/ */
this.responses = new ConcurrentHashMap<>(); this.responses = new ConcurrentHashMap<>();
this.converter = new LwM2mValueConverterImpl();
} }
/** /**
* Fill with data -> Model client * Fill with data -> Model client
*
* @param path - * @param path -
* @param response - * @param response -
*/ */
@ -99,9 +102,9 @@ public class LwM2MClient implements Cloneable {
private void initValue() { private void initValue() {
this.responses.forEach((key, resp) -> { this.responses.forEach((key, resp) -> {
ResultIds pathIds = new ResultIds(key); LwM2mPath pathIds = new LwM2mPath(key);
if (pathIds.getObjectId() > -1) { if (pathIds.isObject() || pathIds.isObjectInstance() || pathIds.isResource()) {
ObjectModel objectModel = ((Collection<ObjectModel>) this.lwServer.getModelProvider().getObjectModel(registration).getObjectModels()).stream().filter(v -> v.id == pathIds.getObjectId()).collect(Collectors.toList()).get(0); 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) { if (this.modelObjects.get(pathIds.getObjectId()) != null) {
this.modelObjects.get(pathIds.getObjectId()).getInstances().put(((ReadResponse) resp).getContent().getId(), (LwM2mObjectInstance) ((ReadResponse) resp).getContent()); this.modelObjects.get(pathIds.getObjectId()).getInstances().put(((ReadResponse) resp).getContent().getId(), (LwM2mObjectInstance) ((ReadResponse) resp).getContent());
} else { } else {
@ -122,30 +125,39 @@ public class LwM2MClient implements Cloneable {
} }
public ResourceModel.Operations getOperation(String path) { public ResourceModel.Operations getOperation(String path) {
ResultIds resultIds = new ResultIds(path); 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; 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) { public String getResourceName(String path) {
ResultIds resultIds = new ResultIds(path); LwM2mPath resultIds = new LwM2mPath(path);
return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).name : ""; return (this.getModelObjects().get(resultIds.getObjectId()) != null) ? this.getModelObjects().get(resultIds.getObjectId()).getObjectModel().resources.get(resultIds.getResourceId()).name : "";
} }
/** /**
* @param path - path resource * @param path - path resource
* @return - value of Resource or null * @return - value of Resource or null
*/public String getResourceValue(String path) { */
public String getResourceValue(String path) {
String resValue = null; String resValue = null;
ResultIds pathIds = new ResultIds(path); LwM2mPath pathIds = new LwM2mPath(path);
ModelObject modelObject = this.getModelObjects().get(pathIds.getObjectId()); 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) { if (instance.getResource(pathIds.getResourceId()) != null) {
try {
resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ? resValue = instance.getResource(pathIds.getResourceId()).getType() == OPAQUE ?
Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() : Hex.encodeHexString((byte[]) instance.getResource(pathIds.getResourceId()).getValue()).toLowerCase() :
(instance.getResource(pathIds.getResourceId()).isMultiInstances()) ? (instance.getResource(pathIds.getResourceId()).isMultiInstances()) ?
instance.getResource(pathIds.getResourceId()).getValues().toString() : instance.getResource(pathIds.getResourceId()).getValues().toString() :
instance.getResource(pathIds.getResourceId()).getValue().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; return resValue;

View File

@ -21,7 +21,7 @@ import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import java.util.Map; import java.util.Map;
@Data @Data
public class ModelObject { public class ModelObject implements Cloneable {
/** /**
* model one on all instance * model one on all instance
* for each instance only id resource with parameters of resources (observe, attr, telemetry) * 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); LwM2mObjectInstance instance = this.instances.get(id);
return this.instances.remove(id, instance); return this.instances.remove(id, instance);
} }
public ModelObject clone() throws CloneNotSupportedException {
return (ModelObject) super.clone();
}
} }

View File

@ -177,10 +177,40 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
return doSaveDevice(device, null); 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) { 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); log.trace("Executing saveDevice [{}]", device);
deviceValidator.validate(device, Device::getTenantId); deviceValidator.validate(device, Device::getTenantId);
Device savedDevice;
try { try {
DeviceProfile deviceProfile; DeviceProfile deviceProfile;
if (device.getDeviceProfileId() == null) { if (device.getDeviceProfileId() == null) {
@ -198,8 +228,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
} }
device.setType(deviceProfile.getName()); device.setType(deviceProfile.getName());
device.setDeviceData(syncDeviceData(deviceProfile, device.getDeviceData())); device.setDeviceData(syncDeviceData(deviceProfile, device.getDeviceData()));
return deviceDao.save(device.getTenantId(), device);
savedDevice = deviceDao.save(device.getTenantId(), device);
} catch (Exception t) { } catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_name_unq_key")) { 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; 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) { private DeviceData syncDeviceData(DeviceProfile deviceProfile, DeviceData deviceData) {

View File

@ -121,6 +121,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; 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(); return restTemplate.postForEntity(baseURL + "/api/device/credentials", deviceCredentials, DeviceCredentials.class).getBody();
} }
public Optional<Device> saveDeviceWithCredentials(Device device, DeviceCredentials credentials) {
try {
Map<Class<?>, 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<Device> 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<Device> getTenantDevices(String type, PageLink pageLink) { public PageData<Device> getTenantDevices(String type, PageLink pageLink) {
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put("type", type); params.put("type", type);