Lwm2m: backEnd: add saveDeviceWithCredential
This commit is contained in:
		
							parent
							
								
									ca46f5fb75
								
							
						
					
					
						commit
						1150d4e4f3
					
				@ -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(),
 | 
			
		||||
 | 
			
		||||
@ -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<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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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<DeviceId> 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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 <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){
 | 
			
		||||
        LinkedList<String> linkedListOut = new LinkedList<>();
 | 
			
		||||
        LinkedList<String> linkedList = new LinkedList<String>((Arrays.asList(s.split(" "))));
 | 
			
		||||
 | 
			
		||||
@ -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 <b>String Single-Instance Resource</b> 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 <b>String Single-Instance Resource</b> 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);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -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<TransportProtos.KeyValueProto>();
 | 
			
		||||
                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<String> 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<Integer, ?> values, String path) {
 | 
			
		||||
        ResultIds resultIds = new ResultIds(path);
 | 
			
		||||
        // #1
 | 
			
		||||
        LwM2MClient lwM2MClient = lwM2mInMemorySecurityStore.getLwM2MClient(registration.getId());
 | 
			
		||||
        ModelObject modelObject = lwM2MClient.getModelObjects().get(resultIds.getObjectId());
 | 
			
		||||
        Map<Integer, LwM2mObjectInstance> instancesModelObject = modelObject.getInstances();
 | 
			
		||||
        LwM2mObjectInstance instanceOld = (instancesModelObject.get(resultIds.instanceId) != null) ? instancesModelObject.get(resultIds.instanceId) : null;
 | 
			
		||||
        Map<Integer, LwM2mResource> 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<Integer, LwM2mResource> 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<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;
 | 
			
		||||
                // #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<Integer, LwM2mResource> 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<String> 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<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,
 | 
			
		||||
                                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<String> 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();
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,6 @@ public class LwM2mServerListener {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void registered(Registration registration, Registration previousReg,
 | 
			
		||||
                               Collection<Observation> 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<Observation> 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");
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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<String, TransportProtos.TsKvProto> delayedRequests;
 | 
			
		||||
    private Set<Integer> delayedRequestsId;
 | 
			
		||||
    private Map<String, LwM2mResponse> responses;
 | 
			
		||||
    private final LwM2mValueConverterImpl converter;
 | 
			
		||||
 | 
			
		||||
    public Object clone() throws CloneNotSupportedException {
 | 
			
		||||
        return super.clone();
 | 
			
		||||
@ -81,11 +82,13 @@ public class LwM2MClient implements Cloneable {
 | 
			
		||||
         * Key <objectId>, response<Value -> 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<ObjectModel>) 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;
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -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<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) {
 | 
			
		||||
        Map<String, String> params = new HashMap<>();
 | 
			
		||||
        params.put("type", type);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user