From 55e8a4540adcc183b91404944eda213bf7f9769c Mon Sep 17 00:00:00 2001 From: Swoq Date: Tue, 28 Sep 2021 13:15:31 +0300 Subject: [PATCH 1/3] Swagger API docs for Device Controller --- .../server/controller/DeviceController.java | 165 +++++++++++++++--- 1 file changed, 144 insertions(+), 21 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 2bb23ccae7..8724625c1f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -19,15 +19,11 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import io.swagger.annotations.Example; -import io.swagger.annotations.ExampleProperty; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -97,17 +93,35 @@ import static org.thingsboard.server.controller.EdgeController.EDGE_ID; @RequiredArgsConstructor @Slf4j public class DeviceController extends BaseController { - public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; private final DeviceBulkImportService deviceBulkImportService; + public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String DEVICE_PROFILE_ID_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + private static final String DEVICE_ID = "deviceId"; private static final String DEVICE_NAME = "deviceName"; private static final String TENANT_ID = "tenantId"; - + private final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page"; + private final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0"; + private final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; + private final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The search is performed by device special field 'textSearch' represented by device name"; + private final String SORT_PROPERTY_DESCRIPTION = "Property of device to sort by"; + private final String SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, label, type"; + private final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESCENDING (DESC)"; + private final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC"; + private final String DEVICE_INFO_DESCRIPTION = "Device Info is an object which are an extension of default Device object. " + + "Apart from Device object, Device Info provides additional information such as customer name and device profile name. "; + + @ApiOperation(value = "Get Device (getDeviceById)", + notes = "If device with given Id exists in the system it will be present in the response, otherwise an empty object will be provided") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) @ResponseBody - public Device getDeviceById(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + public Device getDeviceById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -117,10 +131,12 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Device Info (getDeviceInfoById)", notes = DEVICE_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET) @ResponseBody - public DeviceInfo getDeviceInfoById(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + public DeviceInfo getDeviceInfoById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -132,7 +148,7 @@ public class DeviceController extends BaseController { @ApiOperation(value = "Create Or Update Device (saveDevice)", notes = "Platform generates random device Id and credentials (access token) during device creation. " + "The device id will be present in the response. " + - "Specify the device id when you would like to update the device. Referencing non-existing device Id will cause error.") + "Specify the device id when you would like to update the device. Referencing non-existing device Id will cause an error.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device", method = RequestMethod.POST) @ResponseBody @@ -175,10 +191,13 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Delete device (deleteDevice)", + notes = "Referencing non-existing device Id will cause an error.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteDevice(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + public void deleteDevice(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -204,10 +223,14 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Assign device to customer (assignDeviceToCustomer)", + notes = "Creates assignment of the device to customer. Customer will be able to query device afterwards.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToCustomer(@PathVariable("customerId") String strCustomerId, + public Device assignDeviceToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @PathVariable("customerId") String strCustomerId, + @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(DEVICE_ID, strDeviceId); @@ -242,7 +265,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/customer/device/{deviceId}", method = RequestMethod.DELETE) @ResponseBody public Device unassignDeviceFromCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) - @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -278,7 +301,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/customer/public/device/{deviceId}", method = RequestMethod.POST) @ResponseBody public Device assignDeviceToPublicCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) - @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -299,10 +322,13 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Device Credentials (getDeviceCredentialsByDeviceId)", + notes = "If during device creation there wasn't specified any credentials, platform generates random 'ACCESS_TOKEN' credentials.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/{deviceId}/credentials", method = RequestMethod.GET) @ResponseBody - public DeviceCredentials getDeviceCredentialsByDeviceId(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { + public DeviceCredentials getDeviceCredentialsByDeviceId(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); try { DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -350,15 +376,24 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Tenant Devices (getEdgeDevices)", + notes = "Returns a page (representation of a bunch) of devices in the possession of tenant. " + + "You can specify number of parameters to filter the result set of devices. ") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDevices( + @ApiParam(value = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, + @ApiParam(value = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, + @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @RequestParam(required = false) String sortOrder) throws ThingsboardException { try { TenantId tenantId = getCurrentUser().getTenantId(); @@ -373,17 +408,28 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Tenant Device Infos (getTenantDeviceInfos)", + notes = "Returns a page (representation of a bunch) of devices info objects in the possession of tenant. " + + "You can specify number of parameters to filter the result set. " + DEVICE_INFO_DESCRIPTION) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDeviceInfos( + @ApiParam(value = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, + @ApiParam(value = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, + @ApiParam(value = DEVICE_PROFILE_ID_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, + @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, - @RequestParam(required = false) String sortOrder) throws ThingsboardException { + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @RequestParam(required = false) String sortOrder + ) throws ThingsboardException { try { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -400,6 +446,9 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Tenant Device (getTenantDevice)", + notes = "Requested device must be in the possession of user that perform request. " + + "In the Thingsboard platform Device name is an unique property of device. So it can be used to identify the device.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) @ResponseBody @@ -413,16 +462,26 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Customer Devices (getCustomerDevices)", + notes = "Returns a page (representation of a bunch) of devices objects in the possession of customer. " + + "You can specify number of parameters to filter the result set. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerDevices( + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, + @ApiParam(value = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, + @ApiParam(value = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, + @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); try { @@ -440,17 +499,28 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Customer Device Infos (getCustomerDeviceInfos)", + notes = "Returns a page (representation of a bunch) of devices info objects in the possession of customer. " + + "You can specify number of parameters to filter the result set. " + DEVICE_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerDeviceInfos( + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, + @ApiParam(value = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, + @ApiParam(value = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, + @ApiParam(value = DEVICE_PROFILE_ID_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, + @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); try { @@ -471,10 +541,13 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Devices By Ids (getDevicesByIds)", + notes = "Requested devices must be in the possession of tenant or customer that performs request. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) @ResponseBody public List getDevicesByIds( + @ApiParam(value = "A list of devices ids, separated by comma ','") @RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException { checkArrayParameter("deviceIds", strDeviceIds); try { @@ -521,6 +594,8 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get Device Types (getDeviceTypes)", + notes = "Returns all device profile names of all devices in the possession of user that is performing request.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/types", method = RequestMethod.GET) @ResponseBody @@ -535,10 +610,19 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Claim device (claimDevice)", + notes = "Claiming makes it possible to assign a device to the specific customer using device/server side claiming data (in the form of secret key)." + + "To make this happen you have to provide unique device name and optional claiming data (it is needed only for device-side claiming)." + + "Once device is claimed, the customer becomes its owner and customer users may access device data as well as control the device. \n" + + "In order to enable claiming devices feature a system parameter security.claim.allowClaimingByDefault should be set to true, " + + "otherwise a server-side claimingAllowed attribute with the value true is obligatory for provisioned devices. \n" + + "See official documentation for more details regarding claiming.") @PreAuthorize("hasAuthority('CUSTOMER_USER')") @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.POST) @ResponseBody - public DeferredResult claimDevice(@PathVariable(DEVICE_NAME) String deviceName, + public DeferredResult claimDevice(@ApiParam(value = "Unique name of the device which is going to be claimed") + @PathVariable(DEVICE_NAME) String deviceName, + @ApiParam(value = "Claiming request which can optionally contain secret key") @RequestBody(required = false) ClaimRequest claimRequest) throws ThingsboardException { checkParameter(DEVICE_NAME, deviceName); try { @@ -589,10 +673,13 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Reclaim device (reClaimDevice)", + notes = "Reclaiming means the device will be unassigned from the customer and the device will be available for claiming again.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public DeferredResult reClaimDevice(@PathVariable(DEVICE_NAME) String deviceName) throws ThingsboardException { + public DeferredResult reClaimDevice(@ApiParam(value = "Unique name of the device which is going to be reclaimed") + @PathVariable(DEVICE_NAME) String deviceName) throws ThingsboardException { checkParameter(DEVICE_NAME, deviceName); try { final DeferredResult deferredResult = new DeferredResult<>(); @@ -640,10 +727,14 @@ public class DeviceController extends BaseController { return DataConstants.DEFAULT_SECRET_KEY; } + @ApiOperation(value = "Assign device to tenant (assignDeviceToTenant)", + notes = "Creates assignment of the device to tenant. Thereafter tenant will be able to reassign the device to a customer.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToTenant(@PathVariable(TENANT_ID) String strTenantId, + public Device assignDeviceToTenant(@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + @PathVariable(TENANT_ID) String strTenantId, + @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); checkParameter(DEVICE_ID, strDeviceId); @@ -690,10 +781,17 @@ public class DeviceController extends BaseController { return metaData; } + @ApiOperation(value = "Assign device to edge (assignDeviceToEdge)", + notes = "Creates assignment of an existing device to an instance of The ThingsBoard Edge. " + + "The ThingsBoard Edge is a ThingsBoard’s software product for edge computing. " + + "It allows bringing data analysis and management to the edge, while seamlessly synchronizing with ThingsBoard CE/PE server (cloud). " + + "See official documentation for more details regarding provisioning the edge on ThingsBoard server") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToEdge(@PathVariable(EDGE_ID) String strEdgeId, + public Device assignDeviceToEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) + @PathVariable(EDGE_ID) String strEdgeId, + @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); @@ -724,10 +822,14 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Unassign device from edge (unassignDeviceFromEdge)", + notes = "Clears assignment of the device to the edge") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE) @ResponseBody - public Device unassignDeviceFromEdge(@PathVariable(EDGE_ID) String strEdgeId, + public Device unassignDeviceFromEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) + @PathVariable(EDGE_ID) String strEdgeId, + @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); @@ -758,18 +860,30 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)", + notes = "Returns a page (representation of a bunch) of devices assigned to edge. " + + "You can specify number of parameters to filter the result set of devices. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeDevices( + @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, + @ApiParam(value = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, + @ApiParam(value = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, + @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @RequestParam(required = false) String sortOrder, + @ApiParam(value = "Timestamp. Devices with creation time before it won't be queried") @RequestParam(required = false) Long startTime, + @ApiParam(value = "Timestamp. Devices with creation time after it won't be queried") @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); try { @@ -801,10 +915,17 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Count devices by device profile (countByDeviceProfileAndEmptyOtaPackage)", + notes = "The Thingsboard platform gives an ability to load OTA (over-the-air) packages to devices. " + + "It can be done in two different ways: device scope or device profile scope." + + "In the response you will find the number of devices with specified device profile, but without previously defined device scope OTA package. " + + "It can be useful when you want to define number of devices that will be affected with future OTA package") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody - public Long countByDeviceProfileAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType, + public Long countByDeviceProfileAndEmptyOtaPackage(@ApiParam(value = "OTA package type", allowableValues = "FIRMWARE, SOFTWARE") + @PathVariable("otaPackageType") String otaPackageType, + @ApiParam(value = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'") @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { checkParameter("OtaPackageType", otaPackageType); checkParameter("DeviceProfileId", deviceProfileId); @@ -818,6 +939,8 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)", + notes = "There's an ability to import the bulk of devices using the only .csv file.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/device/bulk_import") public BulkImportResult processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception { From bcac3aaeedd50ebbf91dd2c3dfa38a1c08321247 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 11 Oct 2021 14:57:36 +0300 Subject: [PATCH 2/3] Swagger improvements --- .../server/controller/BaseController.java | 21 ++++++++ .../server/controller/DeviceController.java | 54 +++++++------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f320b8eafa..ef4efdc6a8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -153,6 +153,27 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @TbCoreComponent public abstract class BaseController { + /*Swagger UI description*/ + public static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. "; + public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String DEVICE_PROFILE_ID_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + public static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + + protected final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page"; + protected final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0"; + protected final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; + protected final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The search is performed by device special field 'textSearch' represented by device name"; + protected final String SORT_PROPERTY_DESCRIPTION = "Property of device to sort by"; + protected final String SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, label, type"; + protected final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESCENDING (DESC)"; + protected final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC"; + protected final String DEVICE_INFO_DESCRIPTION = "Device Info is an object which are an extension of default Device object. " + + "Apart from Device object, Device Info provides additional information such as customer name and device profile name. "; + + + public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; protected static final String DEFAULT_DASHBOARD = "defaultDashboardId"; protected static final String HOME_DASHBOARD = "homeDashboardId"; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 8724625c1f..e0cc34e043 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -93,27 +93,12 @@ import static org.thingsboard.server.controller.EdgeController.EDGE_ID; @RequiredArgsConstructor @Slf4j public class DeviceController extends BaseController { - private final DeviceBulkImportService deviceBulkImportService; - public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; - public static final String DEVICE_PROFILE_ID_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; - public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; - public static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; - public static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; - - private static final String DEVICE_ID = "deviceId"; - private static final String DEVICE_NAME = "deviceName"; - private static final String TENANT_ID = "tenantId"; - private final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page"; - private final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0"; - private final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; - private final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The search is performed by device special field 'textSearch' represented by device name"; - private final String SORT_PROPERTY_DESCRIPTION = "Property of device to sort by"; - private final String SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, label, type"; - private final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESCENDING (DESC)"; - private final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC"; - private final String DEVICE_INFO_DESCRIPTION = "Device Info is an object which are an extension of default Device object. " + - "Apart from Device object, Device Info provides additional information such as customer name and device profile name. "; + protected static final String DEVICE_ID = "deviceId"; + protected static final String DEVICE_NAME = "deviceName"; + protected static final String TENANT_ID = "tenantId"; + + private final DeviceBulkImportService deviceBulkImportService; @ApiOperation(value = "Get Device (getDeviceById)", notes = "If device with given Id exists in the system it will be present in the response, otherwise an empty object will be provided") @@ -377,7 +362,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Tenant Devices (getEdgeDevices)", - notes = "Returns a page (representation of a bunch) of devices in the possession of tenant. " + + notes = "Returns a page of devices owned by tenant. " + "You can specify number of parameters to filter the result set of devices. ") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @@ -409,8 +394,8 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Tenant Device Infos (getTenantDeviceInfos)", - notes = "Returns a page (representation of a bunch) of devices info objects in the possession of tenant. " + - "You can specify number of parameters to filter the result set. " + DEVICE_INFO_DESCRIPTION) + notes = "Returns a page of devices info objects owned by tenant. " + + PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -447,8 +432,8 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Tenant Device (getTenantDevice)", - notes = "Requested device must be in the possession of user that perform request. " + - "In the Thingsboard platform Device name is an unique property of device. So it can be used to identify the device.") + notes = "Requested device must be owned by tenant of customer that the user belongs to. " + + "Device name is an unique property of device. So it can be used to identify the device.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) @ResponseBody @@ -463,8 +448,8 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Customer Devices (getCustomerDevices)", - notes = "Returns a page (representation of a bunch) of devices objects in the possession of customer. " + - "You can specify number of parameters to filter the result set. ") + notes = "Returns a page of devices objects assigned to customer. " + + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -500,8 +485,8 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Customer Device Infos (getCustomerDeviceInfos)", - notes = "Returns a page (representation of a bunch) of devices info objects in the possession of customer. " + - "You can specify number of parameters to filter the result set. " + DEVICE_INFO_DESCRIPTION) + notes = "Returns a page of devices info objects assigned to customer. " + + PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -782,10 +767,9 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Assign device to edge (assignDeviceToEdge)", - notes = "Creates assignment of an existing device to an instance of The ThingsBoard Edge. " + - "The ThingsBoard Edge is a ThingsBoard’s software product for edge computing. " + - "It allows bringing data analysis and management to the edge, while seamlessly synchronizing with ThingsBoard CE/PE server (cloud). " + - "See official documentation for more details regarding provisioning the edge on ThingsBoard server") + notes = "Creates assignment of an existing device to an instance of The Edge. " + + "The Edge is a software product for edge computing. " + + "It allows bringing data analysis and management to the edge, while seamlessly synchronizing with the platform server (cloud). ") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody @@ -861,7 +845,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)", - notes = "Returns a page (representation of a bunch) of devices assigned to edge. " + + notes = "Returns a page of devices assigned to edge. " + "You can specify number of parameters to filter the result set of devices. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @@ -916,7 +900,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Count devices by device profile (countByDeviceProfileAndEmptyOtaPackage)", - notes = "The Thingsboard platform gives an ability to load OTA (over-the-air) packages to devices. " + + notes = "The platform gives an ability to load OTA (over-the-air) packages to devices. " + "It can be done in two different ways: device scope or device profile scope." + "In the response you will find the number of devices with specified device profile, but without previously defined device scope OTA package. " + "It can be useful when you want to define number of devices that will be affected with future OTA package") From d6370ed64d4baa1610a0fb215f707366167791ec Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 11 Oct 2021 15:47:33 +0300 Subject: [PATCH 3/3] Documentation for PageData, DeviceSearchQuery and DeviceInfo --- .../server/controller/BaseController.java | 4 +++- .../server/controller/DeviceController.java | 12 ++++++++---- .../thingsboard/server/common/data/DeviceInfo.java | 6 ++++++ .../server/common/data/device/DeviceSearchQuery.java | 6 ++++++ .../server/common/data/page/PageData.java | 7 +++++++ .../data/relation/RelationsSearchParameters.java | 9 +++++++++ 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index ef4efdc6a8..f70232911b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -154,7 +154,9 @@ import static org.thingsboard.server.dao.service.Validator.validateId; public abstract class BaseController { /*Swagger UI description*/ - public static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. "; + public static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. " + + "The result is wrapped with PageData object that allows you to iterate over result set using pagination. " + + "See the 'Model' tab of the Response Class for more details. "; public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; public static final String DEVICE_PROFILE_ID_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index e0cc34e043..179f3da508 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -363,7 +363,7 @@ public class DeviceController extends BaseController { @ApiOperation(value = "Get Tenant Devices (getEdgeDevices)", notes = "Returns a page of devices owned by tenant. " + - "You can specify number of parameters to filter the result set of devices. ") + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -527,7 +527,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Devices By Ids (getDevicesByIds)", - notes = "Requested devices must be in the possession of tenant or customer that performs request. ") + notes = "Requested devices must be owned by tenant or assigned to customer which user is performing the request. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) @ResponseBody @@ -555,6 +555,10 @@ public class DeviceController extends BaseController { } } + @ApiOperation(value = "Find related devices (findByQuery)", + notes = "Returns all devices that are related to the specific entity. " + + "The entity id, relation type, device types, depth of the search, and other query parameters defined using complex 'DeviceSearchQuery' object. " + + "See 'Model' tab of the Parameters for more info.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices", method = RequestMethod.POST) @ResponseBody @@ -580,7 +584,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Device Types (getDeviceTypes)", - notes = "Returns all device profile names of all devices in the possession of user that is performing request.") + notes = "Returns a set of unique device profile names based on devices that are either owned by the tenant or assigned to the customer which user is performing the request.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/types", method = RequestMethod.GET) @ResponseBody @@ -846,7 +850,7 @@ public class DeviceController extends BaseController { @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)", notes = "Returns a page of devices assigned to edge. " + - "You can specify number of parameters to filter the result set of devices. ") + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java index 7730ea635b..be872cc059 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java @@ -15,14 +15,20 @@ */ package org.thingsboard.server.common.data; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.thingsboard.server.common.data.id.DeviceId; +@ApiModel @Data public class DeviceInfo extends Device { + @ApiModelProperty(position = 13, value = "Title of the Customer that owns the device.", readOnly = true) private String customerTitle; + @ApiModelProperty(position = 14, value = "Indicates special 'Public' Customer that is auto-generated to use the devices on public dashboards.", readOnly = true) private boolean customerIsPublic; + @ApiModelProperty(position = 15, value = "Name of the corresponding Device Profile.", readOnly = true) private String deviceProfileName; public DeviceInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java index 9143fdfece..6449cf6729 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.common.data.device; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -25,11 +27,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import java.util.Collections; import java.util.List; +@ApiModel @Data public class DeviceSearchQuery { + @ApiModelProperty(position = 3, value = "Main search parameters.") private RelationsSearchParameters parameters; + @ApiModelProperty(position = 1, value = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').") private String relationType; + @ApiModelProperty(position = 2, value = "Array of device types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').") private List deviceTypes; public EntityRelationsQuery toEntitySearchQuery() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java index 6ffbce4d3d..4b0ace9f68 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java @@ -17,12 +17,15 @@ package org.thingsboard.server.common.data.page; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; +@ApiModel public class PageData { private final List data; @@ -45,18 +48,22 @@ public class PageData { this.hasNext = hasNext; } + @ApiModelProperty(position = 1, value = "Array of the entities.", readOnly = true) public List getData() { return data; } + @ApiModelProperty(position = 2, value = "Total number of available pages. Calculated based on the 'pageSize' request parameter and total number of entities that match search criteria.", readOnly = true) public int getTotalPages() { return totalPages; } + @ApiModelProperty(position = 3, value = "Total number of elements in all available pages.", readOnly = true) public long getTotalElements() { return totalElements; } + @ApiModelProperty(position = 4, value = "'false' value indicates the end of the result set.", readOnly = true) @JsonProperty("hasNext") public boolean hasNext() { return hasNext; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java index f44337ff29..f195840f3b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.common.data.relation; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.EntityType; @@ -26,15 +28,22 @@ import java.util.UUID; /** * Created by ashvayka on 03.05.17. */ +@ApiModel @Data @AllArgsConstructor public class RelationsSearchParameters { + @ApiModelProperty(position = 1, value = "Root entity id to start search from.") private UUID rootId; + @ApiModelProperty(position = 2, value = "Type of the root entity.") private EntityType rootType; + @ApiModelProperty(position = 3, value = "Type of the root entity.") private EntitySearchDirection direction; + @ApiModelProperty(position = 4, value = "Type of the relation.") private RelationTypeGroup relationTypeGroup; + @ApiModelProperty(position = 5, value = "Maximum level of the search depth.") private int maxLevel = 1; + @ApiModelProperty(position = 6, value = "Fetch entities that match the last level of search. Useful to find Devices that are strictly 'maxLevel' relations away from the root entity.") private boolean fetchLastLevelOnly; public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) {