RPC v2 to switch from 409 to 504 error code
This commit is contained in:
		
							parent
							
								
									940c81b095
								
							
						
					
					
						commit
						65ad86bedb
					
				@ -5,7 +5,7 @@
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
@ -16,7 +16,6 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
@ -26,13 +25,12 @@ import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
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.springframework.web.context.request.async.DeferredResult;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.rule.engine.api.RpcError;
 | 
			
		||||
import org.thingsboard.server.common.data.DataConstants;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
@ -59,20 +57,15 @@ import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
import org.thingsboard.server.service.telemetry.exception.ToErrorResponseEntity;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by ashvayka on 22.03.18.
 | 
			
		||||
 */
 | 
			
		||||
@RestController
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@RequestMapping(TbUrlConstants.RPC_URL_PREFIX)
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RpcController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    protected final ObjectMapper jsonMapper = new ObjectMapper();
 | 
			
		||||
public abstract class AbstractRpcController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private TbCoreDeviceRpcService deviceRpcService;
 | 
			
		||||
@ -81,75 +74,15 @@ public class RpcController extends BaseController {
 | 
			
		||||
    private AccessValidator accessValidator;
 | 
			
		||||
 | 
			
		||||
    @Value("${server.rest.server_side_rpc.min_timeout:5000}")
 | 
			
		||||
    private long minTimeout;
 | 
			
		||||
    protected long minTimeout;
 | 
			
		||||
 | 
			
		||||
    @Value("${server.rest.server_side_rpc.default_timeout:10000}")
 | 
			
		||||
    private long defaultTimeout;
 | 
			
		||||
    protected long defaultTimeout;
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public Rpc getPersistedRpc(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
 | 
			
		||||
        checkParameter("RpcId", strRpc);
 | 
			
		||||
    protected DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody, HttpStatus timeoutStatus) throws ThingsboardException {
 | 
			
		||||
        try {
 | 
			
		||||
            RpcId rpcId = new RpcId(UUID.fromString(strRpc));
 | 
			
		||||
            return checkRpcId(rpcId, Operation.READ);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public PageData<Rpc> getPersistedRpcByDevice(@PathVariable("deviceId") String strDeviceId,
 | 
			
		||||
                                                 @RequestParam int pageSize,
 | 
			
		||||
                                                 @RequestParam int page,
 | 
			
		||||
                                                 @RequestParam RpcStatus rpcStatus,
 | 
			
		||||
                                                 @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                 @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
 | 
			
		||||
        checkParameter("DeviceId", strDeviceId);
 | 
			
		||||
        try {
 | 
			
		||||
            TenantId tenantId = getCurrentUser().getTenantId();
 | 
			
		||||
            PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
 | 
			
		||||
            DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId));
 | 
			
		||||
            return checkNotNull(rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
 | 
			
		||||
        checkParameter("RpcId", strRpc);
 | 
			
		||||
        try {
 | 
			
		||||
            rpcService.deleteRpc(getTenantId(), new RpcId(UUID.fromString(strRpc)));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody) throws ThingsboardException {
 | 
			
		||||
        try {
 | 
			
		||||
            JsonNode rpcRequestBody = jsonMapper.readTree(requestBody);
 | 
			
		||||
            ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), jsonMapper.writeValueAsString(rpcRequestBody.get("params")));
 | 
			
		||||
            JsonNode rpcRequestBody = JacksonUtil.toJsonNode(requestBody);
 | 
			
		||||
            ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), JacksonUtil.toString(rpcRequestBody.get("params")));
 | 
			
		||||
            SecurityUser currentUser = getCurrentUser();
 | 
			
		||||
            TenantId tenantId = currentUser.getTenantId();
 | 
			
		||||
            final DeferredResult<ResponseEntity> response = new DeferredResult<>();
 | 
			
		||||
@ -157,7 +90,7 @@ public class RpcController extends BaseController {
 | 
			
		||||
            long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout);
 | 
			
		||||
            UUID rpcRequestUUID = rpcRequestBody.has("requestUUID") ? UUID.fromString(rpcRequestBody.get("requestUUID").asText()) : UUID.randomUUID();
 | 
			
		||||
            boolean persisted = rpcRequestBody.has(DataConstants.PERSISTENT) && rpcRequestBody.get(DataConstants.PERSISTENT).asBoolean();
 | 
			
		||||
            accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() {
 | 
			
		||||
            accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<>() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onSuccess(@Nullable DeferredResult<ResponseEntity> result) {
 | 
			
		||||
                    ToDeviceRpcRequest rpcRequest = new ToDeviceRpcRequest(rpcRequestUUID,
 | 
			
		||||
@ -168,7 +101,7 @@ public class RpcController extends BaseController {
 | 
			
		||||
                            body,
 | 
			
		||||
                            persisted
 | 
			
		||||
                    );
 | 
			
		||||
                    deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse), currentUser);
 | 
			
		||||
                    deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse, timeoutStatus), currentUser);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
@ -184,12 +117,12 @@ public class RpcController extends BaseController {
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
            return response;
 | 
			
		||||
        } catch (IOException ioe) {
 | 
			
		||||
        } catch (IllegalArgumentException ioe) {
 | 
			
		||||
            throw new ThingsboardException("Invalid request body", ioe, ThingsboardErrorCode.BAD_REQUEST_PARAMS);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response) {
 | 
			
		||||
    public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response, HttpStatus timeoutStatus) {
 | 
			
		||||
        Optional<RpcError> rpcError = response.getError();
 | 
			
		||||
        DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter();
 | 
			
		||||
        if (rpcError.isPresent()) {
 | 
			
		||||
@ -197,13 +130,13 @@ public class RpcController extends BaseController {
 | 
			
		||||
            RpcError error = rpcError.get();
 | 
			
		||||
            switch (error) {
 | 
			
		||||
                case TIMEOUT:
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT));
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(timeoutStatus));
 | 
			
		||||
                    break;
 | 
			
		||||
                case NO_ACTIVE_CONNECTION:
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(HttpStatus.CONFLICT));
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(HttpStatus.REQUEST_TIMEOUT));
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(timeoutStatus));
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@ -212,8 +145,8 @@ public class RpcController extends BaseController {
 | 
			
		||||
                String data = responseData.get();
 | 
			
		||||
                try {
 | 
			
		||||
                    logRpcCall(rpcRequest, rpcError, null);
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(jsonMapper.readTree(data), HttpStatus.OK));
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(JacksonUtil.toJsonNode(data), HttpStatus.OK));
 | 
			
		||||
                } catch (IllegalArgumentException e) {
 | 
			
		||||
                    log.debug("Failed to decode device response: {}", data, e);
 | 
			
		||||
                    logRpcCall(rpcRequest, rpcError, e);
 | 
			
		||||
                    responseWriter.setResult(new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE));
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
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.ResponseBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.context.request.async.DeferredResult;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@RequestMapping(TbUrlConstants.RPC_V1_URL_PREFIX)
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RpcV1Controller extends AbstractRpcController {
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,93 @@
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
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.springframework.web.context.request.async.DeferredResult;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RpcId;
 | 
			
		||||
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.rpc.Rpc;
 | 
			
		||||
import org.thingsboard.server.common.data.rpc.RpcStatus;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@RequestMapping(TbUrlConstants.RPC_V2_URL_PREFIX)
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class RpcV2Controller extends AbstractRpcController {
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
 | 
			
		||||
        return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public Rpc getPersistedRpc(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
 | 
			
		||||
        checkParameter("RpcId", strRpc);
 | 
			
		||||
        try {
 | 
			
		||||
            RpcId rpcId = new RpcId(UUID.fromString(strRpc));
 | 
			
		||||
            return checkRpcId(rpcId, Operation.READ);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public PageData<Rpc> getPersistedRpcByDevice(@PathVariable("deviceId") String strDeviceId,
 | 
			
		||||
                                                 @RequestParam int pageSize,
 | 
			
		||||
                                                 @RequestParam int page,
 | 
			
		||||
                                                 @RequestParam RpcStatus rpcStatus,
 | 
			
		||||
                                                 @RequestParam(required = false) String textSearch,
 | 
			
		||||
                                                 @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
 | 
			
		||||
        checkParameter("DeviceId", strDeviceId);
 | 
			
		||||
        try {
 | 
			
		||||
            TenantId tenantId = getCurrentUser().getTenantId();
 | 
			
		||||
            PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
 | 
			
		||||
            DeviceId deviceId = new DeviceId(UUID.fromString(strDeviceId));
 | 
			
		||||
            return checkNotNull(rpcService.findAllByDeviceIdAndStatus(tenantId, deviceId, rpcStatus, pageLink));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
 | 
			
		||||
    @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE)
 | 
			
		||||
    @ResponseBody
 | 
			
		||||
    public void deleteResource(@PathVariable("rpcId") String strRpc) throws ThingsboardException {
 | 
			
		||||
        checkParameter("RpcId", strRpc);
 | 
			
		||||
        try {
 | 
			
		||||
            rpcService.deleteRpc(getTenantId(), new RpcId(UUID.fromString(strRpc)));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -20,5 +20,6 @@ package org.thingsboard.server.controller;
 | 
			
		||||
 */
 | 
			
		||||
public class TbUrlConstants {
 | 
			
		||||
    public static final String TELEMETRY_URL_PREFIX = "/api/plugins/telemetry";
 | 
			
		||||
    public static final String RPC_URL_PREFIX = "/api/plugins/rpc";
 | 
			
		||||
    public static final String RPC_V1_URL_PREFIX = "/api/plugins/rpc";
 | 
			
		||||
    public static final String RPC_V2_URL_PREFIX = "/api/rpc";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409),
 | 
			
		||||
        doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(504),
 | 
			
		||||
                asyncContextTimeoutToUseRpcPlugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}";
 | 
			
		||||
        String nonExistentDeviceId = Uuids.timeBased().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
        String result = doPostAsync("/api/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
                status().isNotFound());
 | 
			
		||||
        Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result);
 | 
			
		||||
    }
 | 
			
		||||
@ -62,7 +62,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409),
 | 
			
		||||
        doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(504),
 | 
			
		||||
                asyncContextTimeoutToUseRpcPlugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ public abstract class AbstractCoapServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}";
 | 
			
		||||
        String nonExistentDeviceId = Uuids.timeBased().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
        String result = doPostAsync("/api/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
                status().isNotFound());
 | 
			
		||||
        Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
 | 
			
		||||
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
 | 
			
		||||
@ -99,14 +99,14 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        String actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
 | 
			
		||||
        validateTwoWayStateChangedNotification(callback, 1, expectedResponseResult, actualResult);
 | 
			
		||||
 | 
			
		||||
        latch = new CountDownLatch(1);
 | 
			
		||||
 | 
			
		||||
        actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
 | 
			
		||||
        validateTwoWayStateChangedNotification(callback, 2, expectedResponseResult, actualResult);
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"24\",\"value\": 1},\"timeout\": 6000}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(409),
 | 
			
		||||
        doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().is(504),
 | 
			
		||||
                asyncContextTimeoutToUseRpcPlugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"25\",\"value\": 1}}";
 | 
			
		||||
        String nonExistentDeviceId = Uuids.timeBased().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
        String result = doPostAsync("/api/rpc/oneway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
                status().isNotFound());
 | 
			
		||||
        Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result);
 | 
			
		||||
    }
 | 
			
		||||
@ -65,7 +65,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"27\",\"value\": 1},\"timeout\": 6000}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(409),
 | 
			
		||||
        doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().is(504),
 | 
			
		||||
                asyncContextTimeoutToUseRpcPlugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,7 @@ public abstract class AbstractMqttServerSideRpcDefaultIntegrationTest extends Ab
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"28\",\"value\": 1}}";
 | 
			
		||||
        String nonExistentDeviceId = Uuids.timeBased().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
        String result = doPostAsync("/api/rpc/twoway/" + nonExistentDeviceId, setGpioRequest, String.class,
 | 
			
		||||
                status().isNotFound());
 | 
			
		||||
        Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
 | 
			
		||||
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        Assert.assertTrue(StringUtils.isEmpty(result));
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
        assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
 | 
			
		||||
@ -95,7 +95,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String expected = "{\"value1\":\"A\",\"value2\":\"B\"}";
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
        Assert.assertEquals(expected, result);
 | 
			
		||||
@ -130,7 +130,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
 | 
			
		||||
 | 
			
		||||
        String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        Assert.assertTrue(StringUtils.isEmpty(result));
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
        assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
 | 
			
		||||
@ -156,7 +156,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractM
 | 
			
		||||
 | 
			
		||||
        String setGpioRequest = "{\"method\": \"toggle_gpio\", \"params\": {\"pin\":1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
        String expected = "{\"success\":true}";
 | 
			
		||||
        assertEquals(expected, result);
 | 
			
		||||
 | 
			
		||||
@ -131,7 +131,7 @@ public abstract class AbstractMqttServerSideRpcProtoIntegrationTest extends Abst
 | 
			
		||||
        String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
 | 
			
		||||
        String deviceId = savedDevice.getId().getId().toString();
 | 
			
		||||
 | 
			
		||||
        String result = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String result = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
 | 
			
		||||
        String expected = "{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}";
 | 
			
		||||
        latch.await(3, TimeUnit.SECONDS);
 | 
			
		||||
        Assert.assertEquals(expected, result);
 | 
			
		||||
 | 
			
		||||
@ -267,7 +267,7 @@ public class MqttClientTest extends AbstractContainerTest {
 | 
			
		||||
        ListenableFuture<ResponseEntity> future = service.submit(() -> {
 | 
			
		||||
            try {
 | 
			
		||||
                return restClient.getRestTemplate()
 | 
			
		||||
                        .postForEntity(HTTPS_URL + "/api/plugins/rpc/twoway/{deviceId}",
 | 
			
		||||
                        .postForEntity(HTTPS_URL + "/api/rpc/twoway/{deviceId}",
 | 
			
		||||
                                mapper.readTree(serverRpcPayload.toString()), String.class,
 | 
			
		||||
                                device.getId());
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
 | 
			
		||||
@ -263,7 +263,7 @@ public class MqttGatewayClientTest extends AbstractContainerTest {
 | 
			
		||||
        ListenableFuture<ResponseEntity> future = service.submit(() -> {
 | 
			
		||||
            try {
 | 
			
		||||
                return restClient.getRestTemplate()
 | 
			
		||||
                        .postForEntity(HTTPS_URL + "/api/plugins/rpc/twoway/{deviceId}",
 | 
			
		||||
                        .postForEntity(HTTPS_URL + "/api/rpc/twoway/{deviceId}",
 | 
			
		||||
                                mapper.readTree(serverRpcPayload.toString()), String.class,
 | 
			
		||||
                                createdDevice.getId());
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
 | 
			
		||||
@ -1811,12 +1811,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void handleOneWayDeviceRPCRequest(DeviceId deviceId, JsonNode requestBody) {
 | 
			
		||||
        restTemplate.postForLocation(baseURL + "/api/plugins/rpc/oneway/{deviceId}", requestBody, deviceId.getId());
 | 
			
		||||
        restTemplate.postForLocation(baseURL + "/api/rpc/oneway/{deviceId}", requestBody, deviceId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public JsonNode handleTwoWayDeviceRPCRequest(DeviceId deviceId, JsonNode requestBody) {
 | 
			
		||||
        return restTemplate.exchange(
 | 
			
		||||
                baseURL + "/api/plugins/rpc/twoway/{deviceId}",
 | 
			
		||||
                baseURL + "/api/rpc/twoway/{deviceId}",
 | 
			
		||||
                HttpMethod.POST,
 | 
			
		||||
                new HttpEntity<>(requestBody),
 | 
			
		||||
                new ParameterizedTypeReference<JsonNode>() {
 | 
			
		||||
 | 
			
		||||
@ -130,11 +130,11 @@ export class DeviceService {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public sendOneWayRpcCommand(deviceId: string, requestBody: any, config?: RequestConfig): Observable<any> {
 | 
			
		||||
    return this.http.post<Device>(`/api/plugins/rpc/oneway/${deviceId}`, requestBody, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
    return this.http.post<Device>(`/api/rpc/oneway/${deviceId}`, requestBody, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public sendTwoWayRpcCommand(deviceId: string, requestBody: any, config?: RequestConfig): Observable<any> {
 | 
			
		||||
    return this.http.post<Device>(`/api/plugins/rpc/twoway/${deviceId}`, requestBody, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
    return this.http.post<Device>(`/api/rpc/twoway/${deviceId}`, requestBody, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public findByQuery(query: DeviceSearchQuery,
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
 | 
			
		||||
 | 
			
		||||
  private internalUrlPrefixes = [
 | 
			
		||||
    '/api/auth/token',
 | 
			
		||||
    '/api/plugins/rpc'
 | 
			
		||||
    '/api/rpc'
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  private activeRequests = 0;
 | 
			
		||||
@ -142,7 +142,7 @@ export class GlobalHttpInterceptor implements HttpInterceptor {
 | 
			
		||||
      }
 | 
			
		||||
    } else if (errorResponse.status === 0 || errorResponse.status === -1) {
 | 
			
		||||
        this.showError('Unable to connect');
 | 
			
		||||
    } else if (!req.url.startsWith('/api/plugins/rpc')) {
 | 
			
		||||
    } else if (!req.url.startsWith('/api/plugins/rpc') && !req.url.startsWith('/api/rpc')) {
 | 
			
		||||
      if (errorResponse.status === 404) {
 | 
			
		||||
        if (!ignoreErrors) {
 | 
			
		||||
          this.showError(req.method + ': ' + req.url + '<br/>' +
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user