Commit 9e9072decf644b4fc94d0db4a9f248cdcdd862d6

Authored by Igor Kulikov
2 parents 0e279c50 4443fbcb

Merge branch 'master' of github.com:thingsboard/thingsboard

@@ -17,7 +17,6 @@ package org.thingsboard.server.controller; @@ -17,7 +17,6 @@ package org.thingsboard.server.controller;
17 17
18 public class ControllerConstants { 18 public class ControllerConstants {
19 19
20 -  
21 protected static final String NEW_LINE = "\n\n"; 20 protected static final String NEW_LINE = "\n\n";
22 protected static final int DEFAULT_PAGE_SIZE = 1000; 21 protected static final int DEFAULT_PAGE_SIZE = 1000;
23 protected static final String ENTITY_TYPE = "entityType"; 22 protected static final String ENTITY_TYPE = "entityType";
@@ -32,6 +31,7 @@ public class ControllerConstants { @@ -32,6 +31,7 @@ public class ControllerConstants {
32 protected static final String DASHBOARD_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 31 protected static final String DASHBOARD_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
33 protected static final String RPC_ID_PARAM_DESCRIPTION = "A string value representing the rpc id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 32 protected static final String RPC_ID_PARAM_DESCRIPTION = "A string value representing the rpc id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
34 protected static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 33 protected static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
  34 + protected static final String ENTITY_VIEW_ID_PARAM_DESCRIPTION = "A string value representing the entity view id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
35 protected static final String DEVICE_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 35 protected static final String DEVICE_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
36 protected static final String TENANT_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the tenant profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 36 protected static final String TENANT_PROFILE_ID_PARAM_DESCRIPTION = "A string value representing the tenant profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
37 protected static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; 37 protected static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
@@ -56,6 +56,7 @@ public class ControllerConstants { @@ -56,6 +56,7 @@ public class ControllerConstants {
56 protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page"; 56 protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";
57 protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0"; 57 protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";
58 protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; 58 protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile";
  59 + protected static final String ENTITY_VIEW_TYPE_DESCRIPTION = "Entity View type";
59 protected static final String ASSET_TYPE_DESCRIPTION = "Asset type"; 60 protected static final String ASSET_TYPE_DESCRIPTION = "Asset type";
60 protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'"; 61 protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'";
61 protected static final String RULE_CHAIN_TYPE_DESCRIPTION = "Rule chain type (CORE or EDGE)"; 62 protected static final String RULE_CHAIN_TYPE_DESCRIPTION = "Rule chain type (CORE or EDGE)";
@@ -64,6 +65,7 @@ public class ControllerConstants { @@ -64,6 +65,7 @@ public class ControllerConstants {
64 protected static final String WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the widget bundle title."; 65 protected static final String WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the widget bundle title.";
65 protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty."; 66 protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty.";
66 protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name."; 67 protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";
  68 + protected static final String ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the entity view name.";
67 protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email."; 69 protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email.";
68 protected static final String TENANT_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant name."; 70 protected static final String TENANT_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant name.";
69 protected static final String TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant profile name."; 71 protected static final String TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant profile name.";
@@ -78,6 +80,8 @@ public class ControllerConstants { @@ -78,6 +80,8 @@ public class ControllerConstants {
78 protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city"; 80 protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city";
79 protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response"; 81 protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response";
80 protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle"; 82 protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle";
  83 + protected static final String ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type";
  84 + protected static final String ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, customerTitle";
81 protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email"; 85 protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email";
82 protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email"; 86 protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email";
83 protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault"; 87 protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault";
@@ -172,6 +176,46 @@ public class ControllerConstants { @@ -172,6 +176,46 @@ public class ControllerConstants {
172 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{\n" + 176 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{\n" +
173 " \"eventType\":\"DEBUG_RULE_CHAIN\",\n" + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END; 177 " \"eventType\":\"DEBUG_RULE_CHAIN\",\n" + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
174 178
  179 + protected static final String IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION = "A Boolean value representing the Server SecurityInfo for future Bootstrap client mode settings. Values: 'true' for Bootstrap Server; 'false' for Lwm2m Server. ";
  180 +
  181 + protected static final String DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION =
  182 + "{\n" +
  183 + " \"device\": {\n" +
  184 + " \"name\": \"LwRpk00000000\",\n" +
  185 + " \"type\": \"lwm2mProfileRpk\"\n" +
  186 + " },\n" +
  187 + " \"credentials\": {\n" +
  188 + " \"id\": \"null\",\n" +
  189 + " \"createdTime\": 0,\n" +
  190 + " \"deviceId\": \"null\",\n" +
  191 + " \"credentialsType\": \"LWM2M_CREDENTIALS\",\n" +
  192 + " \"credentialsId\": \"LwRpk00000000\",\n" +
  193 + " \"credentialsValue\": {\n" +
  194 + " \"client\": {\n" +
  195 + " \"endpoint\": \"LwRpk00000000\",\n" +
  196 + " \"securityConfigClientMode\": \"RPK\",\n" +
  197 + " \"key\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\"\n" +
  198 + " },\n" +
  199 + " \"bootstrap\": {\n" +
  200 + " \"bootstrapServer\": {\n" +
  201 + " \"securityMode\": \"RPK\",\n" +
  202 + " \"clientPublicKeyOrId\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +
  203 + " \"clientSecretKey\": \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"\n" +
  204 + " },\n" +
  205 + " \"lwm2mServer\": {\n" +
  206 + " \"securityMode\": \"RPK\",\n" +
  207 + " \"clientPublicKeyOrId\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUEBxNl/RcYJNm8mk91CyVXoIJiROYDlXcSSqK6e5bDHwOW4ZiN2lNnXalyF0Jxw8MbAytnDMERXyAja5VEMeVQ==\",\n" +
  208 + " \"clientSecretKey\": \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgd9GAx7yZW37autew5KZykn4IgRpge/tZSjnudnZJnMahRANCAARQQHE2X9Fxgk2byaT3ULJVeggmJE5gOVdxJKorp7lsMfA5bhmI3aU2ddqXIXQnHDwxsDK2cMwRFfICNrlUQx5V\"\n" +
  209 + " }\n" +
  210 + " }\n" +
  211 + " }\n" +
  212 + " }\n" +
  213 + "}";
  214 +
  215 + protected static final String DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN =
  216 + MARKDOWN_CODE_BLOCK_START + DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION + MARKDOWN_CODE_BLOCK_END;
  217 +
  218 +
175 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE + 219 protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
176 "Provides a hint about the data type of the entity field that is defined in the filter key. " + 220 "Provides a hint about the data type of the entity field that is defined in the filter key. " +
177 "The value type impacts the list of possible operations that you may use in the corresponding predicate. For example, you may use 'STARTS_WITH' or 'END_WITH', but you can't use 'GREATER_OR_EQUAL' for string values." + 221 "The value type impacts the list of possible operations that you may use in the corresponding predicate. For example, you may use 'STARTS_WITH' or 'END_WITH', but you can't use 'GREATER_OR_EQUAL' for string values." +
@@ -1359,4 +1403,11 @@ public class ControllerConstants { @@ -1359,4 +1403,11 @@ public class ControllerConstants {
1359 1403
1360 protected static final String DEVICE_PROFILE_ID = "deviceProfileId"; 1404 protected static final String DEVICE_PROFILE_ID = "deviceProfileId";
1361 1405
  1406 + protected static final String MODEL_DESCRIPTION = "See the 'Model' tab for more details.";
  1407 + protected static final String ENTITY_VIEW_DESCRIPTION = "Entity Views limit the degree of exposure of the Device or Asset telemetry and attributes to the Customers. " +
  1408 + "Every Entity View references exactly one entity (device or asset) and defines telemetry and attribute keys that will be visible to the assigned Customer. " +
  1409 + "As a Tenant Administrator you are able to create multiple EVs per Device or Asset and assign them to different Customers. ";
  1410 + protected static final String ENTITY_VIEW_INFO_DESCRIPTION = "Entity Views Info extends the Entity View with customer title and 'is public' flag. " + ENTITY_VIEW_DESCRIPTION;
  1411 +
  1412 +
1362 } 1413 }
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
  18 +import com.fasterxml.jackson.databind.ObjectMapper;
18 import com.google.common.util.concurrent.FutureCallback; 19 import com.google.common.util.concurrent.FutureCallback;
19 import com.google.common.util.concurrent.Futures; 20 import com.google.common.util.concurrent.Futures;
20 import com.google.common.util.concurrent.ListenableFuture; 21 import com.google.common.util.concurrent.ListenableFuture;
@@ -46,6 +47,7 @@ import org.thingsboard.server.common.data.Device; @@ -46,6 +47,7 @@ import org.thingsboard.server.common.data.Device;
46 import org.thingsboard.server.common.data.DeviceInfo; 47 import org.thingsboard.server.common.data.DeviceInfo;
47 import org.thingsboard.server.common.data.EntitySubtype; 48 import org.thingsboard.server.common.data.EntitySubtype;
48 import org.thingsboard.server.common.data.EntityType; 49 import org.thingsboard.server.common.data.EntityType;
  50 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
49 import org.thingsboard.server.common.data.Tenant; 51 import org.thingsboard.server.common.data.Tenant;
50 import org.thingsboard.server.common.data.audit.ActionType; 52 import org.thingsboard.server.common.data.audit.ActionType;
51 import org.thingsboard.server.common.data.device.DeviceSearchQuery; 53 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
@@ -83,10 +85,12 @@ import javax.annotation.Nullable; @@ -83,10 +85,12 @@ import javax.annotation.Nullable;
83 import java.io.IOException; 85 import java.io.IOException;
84 import java.util.ArrayList; 86 import java.util.ArrayList;
85 import java.util.List; 87 import java.util.List;
  88 +import java.util.Map;
86 import java.util.UUID; 89 import java.util.UUID;
87 import java.util.stream.Collectors; 90 import java.util.stream.Collectors;
88 91
89 import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH; 92 import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH;
  93 +import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID;
90 import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; 94 import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION;
91 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION; 95 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION;
92 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION; 96 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION;
@@ -95,6 +99,8 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFI @@ -95,6 +99,8 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFI
95 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES; 99 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES;
96 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION; 100 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION;
97 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION; 101 import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION;
  102 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION;
  103 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN;
98 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION; 104 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
99 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION; 105 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
100 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION; 106 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION;
@@ -197,7 +203,37 @@ public class DeviceController extends BaseController { @@ -197,7 +203,37 @@ public class DeviceController extends BaseController {
197 null, created ? ActionType.ADDED : ActionType.UPDATED, e); 203 null, created ? ActionType.ADDED : ActionType.UPDATED, e);
198 throw handleException(e); 204 throw handleException(e);
199 } 205 }
  206 + }
200 207
  208 + @ApiOperation(value = "Create Device (saveDevice) with credentials ",
  209 + notes = "Create or update the Device. When creating device, platform generates Device Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  210 + "Requires to provide the Device Credentials object as well. Useful to create device and credentials in one request. " +
  211 + "You may find the example of LwM2M device and RPK credentials below: \n\n" +
  212 + DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN +
  213 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
  214 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  215 + @RequestMapping(value = "/device-with-credentials", method = RequestMethod.POST)
  216 + @ResponseBody
  217 + public Device saveDeviceWithCredentials(@ApiParam(value = "The JSON object with device and credentials. See method description above for example.")
  218 + @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials) throws ThingsboardException {
  219 + Device device = checkNotNull(deviceAndCredentials.getDevice());
  220 + DeviceCredentials credentials = checkNotNull(deviceAndCredentials.getCredentials());
  221 + try {
  222 + device.setTenantId(getCurrentUser().getTenantId());
  223 + checkEntity(device.getId(), device, Resource.DEVICE);
  224 + Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials);
  225 + checkNotNull(savedDevice);
  226 + tbClusterService.onDeviceUpdated(savedDevice, device);
  227 + logEntityAction(savedDevice.getId(), savedDevice,
  228 + savedDevice.getCustomerId(),
  229 + device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
  230 +
  231 + return savedDevice;
  232 + } catch (Exception e) {
  233 + logEntityAction(emptyId(EntityType.DEVICE), device,
  234 + null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
  235 + throw handleException(e);
  236 + }
201 } 237 }
202 238
203 private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated, SecurityUser user) { 239 private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated, SecurityUser user) {
@@ -492,7 +528,7 @@ public class DeviceController extends BaseController { @@ -492,7 +528,7 @@ public class DeviceController extends BaseController {
492 @ResponseBody 528 @ResponseBody
493 public PageData<Device> getCustomerDevices( 529 public PageData<Device> getCustomerDevices(
494 @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) 530 @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
495 - @PathVariable("customerId") String strCustomerId, 531 + @PathVariable(CUSTOMER_ID) String strCustomerId,
496 @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) 532 @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
497 @RequestParam int pageSize, 533 @RequestParam int pageSize,
498 @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) 534 @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.MoreExecutors; 21 import com.google.common.util.concurrent.MoreExecutors;
22 import com.google.common.util.concurrent.SettableFuture; 22 import com.google.common.util.concurrent.SettableFuture;
23 import io.swagger.annotations.ApiOperation; 23 import io.swagger.annotations.ApiOperation;
  24 +import io.swagger.annotations.ApiParam;
24 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
25 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.http.HttpStatus; 27 import org.springframework.http.HttpStatus;
@@ -74,7 +75,7 @@ import java.util.concurrent.ExecutionException; @@ -74,7 +75,7 @@ import java.util.concurrent.ExecutionException;
74 import java.util.stream.Collectors; 75 import java.util.stream.Collectors;
75 76
76 import static org.apache.commons.lang3.StringUtils.isBlank; 77 import static org.apache.commons.lang3.StringUtils.isBlank;
77 -import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; 78 +import static org.thingsboard.server.controller.ControllerConstants.*;
78 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION; 79 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
79 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION; 80 import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION;
80 import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION; 81 import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION;
@@ -95,10 +96,16 @@ public class EntityViewController extends BaseController { @@ -95,10 +96,16 @@ public class EntityViewController extends BaseController {
95 @Autowired 96 @Autowired
96 private TimeseriesService tsService; 97 private TimeseriesService tsService;
97 98
  99 + @ApiOperation(value = "Get entity view (getEntityViewById)",
  100 + notes = "Fetch the EntityView object based on the provided entity view id. "
  101 + + ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  102 + produces = MediaType.APPLICATION_JSON_VALUE)
98 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 103 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
99 @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) 104 @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET)
100 @ResponseBody 105 @ResponseBody
101 - public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 106 + public EntityView getEntityViewById(
  107 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  108 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
102 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 109 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
103 try { 110 try {
104 return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ); 111 return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ);
@@ -107,10 +114,16 @@ public class EntityViewController extends BaseController { @@ -107,10 +114,16 @@ public class EntityViewController extends BaseController {
107 } 114 }
108 } 115 }
109 116
  117 + @ApiOperation(value = "Get Entity View info (getEntityViewInfoById)",
  118 + notes = "Fetch the Entity View info object based on the provided Entity View Id. "
  119 + + ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  120 + produces = MediaType.APPLICATION_JSON_VALUE)
110 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 121 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
111 @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET) 122 @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET)
112 @ResponseBody 123 @ResponseBody
113 - public EntityViewInfo getEntityViewInfoById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 124 + public EntityViewInfo getEntityViewInfoById(
  125 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  126 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
114 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 127 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
115 try { 128 try {
116 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); 129 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
@@ -120,10 +133,15 @@ public class EntityViewController extends BaseController { @@ -120,10 +133,15 @@ public class EntityViewController extends BaseController {
120 } 133 }
121 } 134 }
122 135
  136 + @ApiOperation(value = "Save or update entity view (saveEntityView)",
  137 + notes = ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION,
  138 + produces = MediaType.APPLICATION_JSON_VALUE)
123 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 139 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
124 @RequestMapping(value = "/entityView", method = RequestMethod.POST) 140 @RequestMapping(value = "/entityView", method = RequestMethod.POST)
125 @ResponseBody 141 @ResponseBody
126 - public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { 142 + public EntityView saveEntityView(
  143 + @ApiParam(value = "A JSON object representing the entity view.")
  144 + @RequestBody EntityView entityView) throws ThingsboardException {
127 try { 145 try {
128 entityView.setTenantId(getCurrentUser().getTenantId()); 146 entityView.setTenantId(getCurrentUser().getTenantId());
129 147
@@ -357,10 +375,15 @@ public class EntityViewController extends BaseController { @@ -357,10 +375,15 @@ public class EntityViewController extends BaseController {
357 keys); 375 keys);
358 } 376 }
359 377
  378 + @ApiOperation(value = "Delete entity view (deleteEntityView)",
  379 + notes = "Delete the EntityView object based on the provided entity view id. "
  380 + + TENANT_AUTHORITY_PARAGRAPH)
360 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 381 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
361 @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE) 382 @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE)
362 @ResponseStatus(value = HttpStatus.OK) 383 @ResponseStatus(value = HttpStatus.OK)
363 - public void deleteEntityView(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 384 + public void deleteEntityView(
  385 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  386 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
364 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 387 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
365 try { 388 try {
366 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); 389 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
@@ -382,10 +405,14 @@ public class EntityViewController extends BaseController { @@ -382,10 +405,14 @@ public class EntityViewController extends BaseController {
382 } 405 }
383 } 406 }
384 407
  408 + @ApiOperation(value = "Get Entity View by name (getTenantEntityView)",
  409 + notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH,
  410 + produces = MediaType.APPLICATION_JSON_VALUE)
385 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 411 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
386 @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET) 412 @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET)
387 @ResponseBody 413 @ResponseBody
388 public EntityView getTenantEntityView( 414 public EntityView getTenantEntityView(
  415 + @ApiParam(value = "Entity View name")
389 @RequestParam String entityViewName) throws ThingsboardException { 416 @RequestParam String entityViewName) throws ThingsboardException {
390 try { 417 try {
391 TenantId tenantId = getCurrentUser().getTenantId(); 418 TenantId tenantId = getCurrentUser().getTenantId();
@@ -395,11 +422,16 @@ public class EntityViewController extends BaseController { @@ -395,11 +422,16 @@ public class EntityViewController extends BaseController {
395 } 422 }
396 } 423 }
397 424
  425 + @ApiOperation(value = "Assign Entity View to customer (assignEntityViewToCustomer)",
  426 + notes = "Creates assignment of the Entity View to customer. Customer will be able to query Entity View afterwards." + TENANT_AUTHORITY_PARAGRAPH)
398 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 427 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
399 @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST) 428 @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST)
400 @ResponseBody 429 @ResponseBody
401 - public EntityView assignEntityViewToCustomer(@PathVariable(CUSTOMER_ID) String strCustomerId,  
402 - @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 430 + public EntityView assignEntityViewToCustomer(
  431 + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
  432 + @PathVariable(CUSTOMER_ID) String strCustomerId,
  433 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  434 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
403 checkParameter(CUSTOMER_ID, strCustomerId); 435 checkParameter(CUSTOMER_ID, strCustomerId);
404 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 436 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
405 try { 437 try {
@@ -426,10 +458,14 @@ public class EntityViewController extends BaseController { @@ -426,10 +458,14 @@ public class EntityViewController extends BaseController {
426 } 458 }
427 } 459 }
428 460
  461 + @ApiOperation(value = "Unassign Entity View from customer (unassignEntityViewFromCustomer)",
  462 + notes = "Clears assignment of the Entity View to customer. Customer will not be able to query Entity View afterwards." + TENANT_AUTHORITY_PARAGRAPH)
429 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 463 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
430 @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE) 464 @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE)
431 @ResponseBody 465 @ResponseBody
432 - public EntityView unassignEntityViewFromCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 466 + public EntityView unassignEntityViewFromCustomer(
  467 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  468 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
433 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 469 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
434 try { 470 try {
435 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); 471 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
@@ -455,18 +491,28 @@ public class EntityViewController extends BaseController { @@ -455,18 +491,28 @@ public class EntityViewController extends BaseController {
455 } 491 }
456 } 492 }
457 493
  494 + @ApiOperation(value = "Get Customer Entity Views (getCustomerEntityViews)",
  495 + notes = "Returns a page of Entity View objects assigned to customer. " +
  496 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
458 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 497 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
459 @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) 498 @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET)
460 @ResponseBody 499 @ResponseBody
461 public PageData<EntityView> getCustomerEntityViews( 500 public PageData<EntityView> getCustomerEntityViews(
462 - @PathVariable("customerId") String strCustomerId, 501 + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
  502 + @PathVariable(CUSTOMER_ID) String strCustomerId,
  503 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
463 @RequestParam int pageSize, 504 @RequestParam int pageSize,
  505 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
464 @RequestParam int page, 506 @RequestParam int page,
  507 + @ApiParam(value = ENTITY_VIEW_TYPE)
465 @RequestParam(required = false) String type, 508 @RequestParam(required = false) String type,
  509 + @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION)
466 @RequestParam(required = false) String textSearch, 510 @RequestParam(required = false) String textSearch,
  511 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES)
467 @RequestParam(required = false) String sortProperty, 512 @RequestParam(required = false) String sortProperty,
  513 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
468 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 514 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
469 - checkParameter("customerId", strCustomerId); 515 + checkParameter(CUSTOMER_ID, strCustomerId);
470 try { 516 try {
471 TenantId tenantId = getCurrentUser().getTenantId(); 517 TenantId tenantId = getCurrentUser().getTenantId();
472 CustomerId customerId = new CustomerId(toUUID(strCustomerId)); 518 CustomerId customerId = new CustomerId(toUUID(strCustomerId));
@@ -482,16 +528,26 @@ public class EntityViewController extends BaseController { @@ -482,16 +528,26 @@ public class EntityViewController extends BaseController {
482 } 528 }
483 } 529 }
484 530
  531 + @ApiOperation(value = "Get Customer Entity View info (getCustomerEntityViewInfos)",
  532 + notes = "Returns a page of Entity View info objects assigned to customer. " + ENTITY_VIEW_DESCRIPTION +
  533 + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
485 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 534 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
486 @RequestMapping(value = "/customer/{customerId}/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 535 @RequestMapping(value = "/customer/{customerId}/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
487 @ResponseBody 536 @ResponseBody
488 public PageData<EntityViewInfo> getCustomerEntityViewInfos( 537 public PageData<EntityViewInfo> getCustomerEntityViewInfos(
489 - @PathVariable("customerId") String strCustomerId, 538 + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
  539 + @PathVariable(CUSTOMER_ID) String strCustomerId,
  540 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
490 @RequestParam int pageSize, 541 @RequestParam int pageSize,
  542 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
491 @RequestParam int page, 543 @RequestParam int page,
  544 + @ApiParam(value = ENTITY_VIEW_TYPE)
492 @RequestParam(required = false) String type, 545 @RequestParam(required = false) String type,
  546 + @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION)
493 @RequestParam(required = false) String textSearch, 547 @RequestParam(required = false) String textSearch,
  548 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES)
494 @RequestParam(required = false) String sortProperty, 549 @RequestParam(required = false) String sortProperty,
  550 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
495 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 551 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
496 checkParameter("customerId", strCustomerId); 552 checkParameter("customerId", strCustomerId);
497 try { 553 try {
@@ -509,15 +565,24 @@ public class EntityViewController extends BaseController { @@ -509,15 +565,24 @@ public class EntityViewController extends BaseController {
509 } 565 }
510 } 566 }
511 567
  568 + @ApiOperation(value = "Get Tenant Entity Views (getTenantEntityViews)",
  569 + notes = "Returns a page of entity views owned by tenant. " + ENTITY_VIEW_DESCRIPTION +
  570 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
512 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 571 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
513 @RequestMapping(value = "/tenant/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) 572 @RequestMapping(value = "/tenant/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET)
514 @ResponseBody 573 @ResponseBody
515 public PageData<EntityView> getTenantEntityViews( 574 public PageData<EntityView> getTenantEntityViews(
  575 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
516 @RequestParam int pageSize, 576 @RequestParam int pageSize,
  577 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
517 @RequestParam int page, 578 @RequestParam int page,
  579 + @ApiParam(value = ENTITY_VIEW_TYPE)
518 @RequestParam(required = false) String type, 580 @RequestParam(required = false) String type,
  581 + @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION)
519 @RequestParam(required = false) String textSearch, 582 @RequestParam(required = false) String textSearch,
  583 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES)
520 @RequestParam(required = false) String sortProperty, 584 @RequestParam(required = false) String sortProperty,
  585 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
521 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 586 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
522 try { 587 try {
523 TenantId tenantId = getCurrentUser().getTenantId(); 588 TenantId tenantId = getCurrentUser().getTenantId();
@@ -533,15 +598,24 @@ public class EntityViewController extends BaseController { @@ -533,15 +598,24 @@ public class EntityViewController extends BaseController {
533 } 598 }
534 } 599 }
535 600
  601 + @ApiOperation(value = "Get Tenant Entity Views (getTenantEntityViews)",
  602 + notes = "Returns a page of entity views info owned by tenant. " + ENTITY_VIEW_DESCRIPTION +
  603 + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
536 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 604 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
537 @RequestMapping(value = "/tenant/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) 605 @RequestMapping(value = "/tenant/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
538 @ResponseBody 606 @ResponseBody
539 public PageData<EntityViewInfo> getTenantEntityViewInfos( 607 public PageData<EntityViewInfo> getTenantEntityViewInfos(
  608 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
540 @RequestParam int pageSize, 609 @RequestParam int pageSize,
  610 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
541 @RequestParam int page, 611 @RequestParam int page,
  612 + @ApiParam(value = ENTITY_VIEW_TYPE)
542 @RequestParam(required = false) String type, 613 @RequestParam(required = false) String type,
  614 + @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION)
543 @RequestParam(required = false) String textSearch, 615 @RequestParam(required = false) String textSearch,
  616 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES)
544 @RequestParam(required = false) String sortProperty, 617 @RequestParam(required = false) String sortProperty,
  618 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
545 @RequestParam(required = false) String sortOrder) throws ThingsboardException { 619 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
546 try { 620 try {
547 TenantId tenantId = getCurrentUser().getTenantId(); 621 TenantId tenantId = getCurrentUser().getTenantId();
@@ -556,10 +630,16 @@ public class EntityViewController extends BaseController { @@ -556,10 +630,16 @@ public class EntityViewController extends BaseController {
556 } 630 }
557 } 631 }
558 632
  633 + @ApiOperation(value = "Find related entity views (findByQuery)",
  634 + notes = "Returns all entity views that are related to the specific entity. " +
  635 + "The entity id, relation type, entity view types, depth of the search, and other query parameters defined using complex 'EntityViewSearchQuery' object. " +
  636 + "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
559 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 637 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
560 @RequestMapping(value = "/entityViews", method = RequestMethod.POST) 638 @RequestMapping(value = "/entityViews", method = RequestMethod.POST)
561 @ResponseBody 639 @ResponseBody
562 - public List<EntityView> findByQuery(@RequestBody EntityViewSearchQuery query) throws ThingsboardException { 640 + public List<EntityView> findByQuery(
  641 + @ApiParam(value = "The entity view search query JSON")
  642 + @RequestBody EntityViewSearchQuery query) throws ThingsboardException {
563 checkNotNull(query); 643 checkNotNull(query);
564 checkNotNull(query.getParameters()); 644 checkNotNull(query.getParameters());
565 checkNotNull(query.getEntityViewTypes()); 645 checkNotNull(query.getEntityViewTypes());
@@ -580,6 +660,9 @@ public class EntityViewController extends BaseController { @@ -580,6 +660,9 @@ public class EntityViewController extends BaseController {
580 } 660 }
581 } 661 }
582 662
  663 + @ApiOperation(value = "Get Entity View Types (getEntityViewTypes)",
  664 + notes = "Returns a set of unique entity view types based on entity views that are either owned by the tenant or assigned to the customer which user is performing the request."
  665 + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
583 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 666 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
584 @RequestMapping(value = "/entityView/types", method = RequestMethod.GET) 667 @RequestMapping(value = "/entityView/types", method = RequestMethod.GET)
585 @ResponseBody 668 @ResponseBody
@@ -594,10 +677,16 @@ public class EntityViewController extends BaseController { @@ -594,10 +677,16 @@ public class EntityViewController extends BaseController {
594 } 677 }
595 } 678 }
596 679
  680 + @ApiOperation(value = "Make entity view publicly available (assignEntityViewToPublicCustomer)",
  681 + notes = "Entity View will be available for non-authorized (not logged-in) users. " +
  682 + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
  683 + "However, users that are logged-in and belong to different tenant will not be able to access the entity view." + TENANT_AUTHORITY_PARAGRAPH)
597 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 684 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
598 @RequestMapping(value = "/customer/public/entityView/{entityViewId}", method = RequestMethod.POST) 685 @RequestMapping(value = "/customer/public/entityView/{entityViewId}", method = RequestMethod.POST)
599 @ResponseBody 686 @ResponseBody
600 - public EntityView assignEntityViewToPublicCustomer(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { 687 + public EntityView assignEntityViewToPublicCustomer(
  688 + @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION)
  689 + @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException {
601 checkParameter(ENTITY_VIEW_ID, strEntityViewId); 690 checkParameter(ENTITY_VIEW_ID, strEntityViewId);
602 try { 691 try {
603 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); 692 EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId));
@@ -16,7 +16,10 @@ @@ -16,7 +16,10 @@
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
  19 +import io.swagger.annotations.ApiOperation;
  20 +import io.swagger.annotations.ApiParam;
19 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
  22 +import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.security.access.prepost.PreAuthorize; 23 import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.PathVariable; 24 import org.springframework.web.bind.annotation.PathVariable;
22 import org.springframework.web.bind.annotation.RequestBody; 25 import org.springframework.web.bind.annotation.RequestBody;
@@ -26,6 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody; @@ -26,6 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
26 import org.springframework.web.bind.annotation.RestController; 29 import org.springframework.web.bind.annotation.RestController;
27 import org.thingsboard.server.common.data.Device; 30 import org.thingsboard.server.common.data.Device;
28 import org.thingsboard.server.common.data.EntityType; 31 import org.thingsboard.server.common.data.EntityType;
  32 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
29 import org.thingsboard.server.common.data.audit.ActionType; 33 import org.thingsboard.server.common.data.audit.ActionType;
30 import org.thingsboard.server.common.data.exception.ThingsboardException; 34 import org.thingsboard.server.common.data.exception.ThingsboardException;
31 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig; 35 import org.thingsboard.server.common.data.lwm2m.ServerSecurityConfig;
@@ -35,16 +39,32 @@ import org.thingsboard.server.service.security.permission.Resource; @@ -35,16 +39,32 @@ import org.thingsboard.server.service.security.permission.Resource;
35 39
36 import java.util.Map; 40 import java.util.Map;
37 41
  42 +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION;
  43 +import static org.thingsboard.server.controller.ControllerConstants.IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION;
  44 +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
  45 +
38 @Slf4j 46 @Slf4j
39 @RestController 47 @RestController
40 @TbCoreComponent 48 @TbCoreComponent
41 @RequestMapping("/api") 49 @RequestMapping("/api")
42 public class Lwm2mController extends BaseController { 50 public class Lwm2mController extends BaseController {
43 51
  52 + @Autowired
  53 + private DeviceController deviceController;
  54 +
  55 + public static final String IS_BOOTSTRAP_SERVER = "isBootstrapServer";
  56 +
  57 +
  58 + @ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)",
  59 + notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " +
  60 + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH,
  61 + produces = "application/json")
44 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 62 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
45 @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET) 63 @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET)
46 @ResponseBody 64 @ResponseBody
47 - public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(@PathVariable("isBootstrapServer") boolean bootstrapServer) throws ThingsboardException { 65 + public ServerSecurityConfig getLwm2mBootstrapSecurityInfo(
  66 + @ApiParam(value = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION)
  67 + @PathVariable(IS_BOOTSTRAP_SERVER) boolean bootstrapServer) throws ThingsboardException {
48 try { 68 try {
49 return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(bootstrapServer); 69 return lwM2MServerSecurityInfoRepository.getServerSecurityInfo(bootstrapServer);
50 } catch (Exception e) { 70 } catch (Exception e) {
@@ -52,28 +72,14 @@ public class Lwm2mController extends BaseController { @@ -52,28 +72,14 @@ public class Lwm2mController extends BaseController {
52 } 72 }
53 } 73 }
54 74
  75 + @ApiOperation(hidden = true, value = "Save device with credentials (Deprecated)")
55 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 76 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
56 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST) 77 @RequestMapping(value = "/lwm2m/device-credentials", method = RequestMethod.POST)
57 @ResponseBody 78 @ResponseBody
58 - public Device saveDeviceWithCredentials(@RequestBody (required=false) Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException { 79 + public Device saveDeviceWithCredentials(@RequestBody Map<Class<?>, Object> deviceWithDeviceCredentials) throws ThingsboardException {
59 ObjectMapper mapper = new ObjectMapper(); 80 ObjectMapper mapper = new ObjectMapper();
60 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class)); 81 Device device = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(Device.class), Device.class));
61 - DeviceCredentials credentials = checkNotNull(mapper.convertValue( deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));  
62 - try {  
63 - device.setTenantId(getCurrentUser().getTenantId());  
64 - checkEntity(device.getId(), device, Resource.DEVICE);  
65 - Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials);  
66 - checkNotNull(savedDevice);  
67 - tbClusterService.onDeviceUpdated(savedDevice, device);  
68 - logEntityAction(savedDevice.getId(), savedDevice,  
69 - savedDevice.getCustomerId(),  
70 - device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);  
71 -  
72 - return savedDevice;  
73 - } catch (Exception e) {  
74 - logEntityAction(emptyId(EntityType.DEVICE), device,  
75 - null, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);  
76 - throw handleException(e);  
77 - } 82 + DeviceCredentials credentials = checkNotNull(mapper.convertValue(deviceWithDeviceCredentials.get(DeviceCredentials.class), DeviceCredentials.class));
  83 + return deviceController.saveDeviceWithCredentials(new SaveDeviceWithCredentialsRequest(device, credentials));
78 } 84 }
79 } 85 }
@@ -92,10 +92,10 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen @@ -92,10 +92,10 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
92 return this; 92 return this;
93 } 93 }
94 94
95 - @ApiModelProperty(position = 1, value = "JSON object with the device Id. " +  
96 - "Specify this field to update the device. " +  
97 - "Referencing non-existing device Id will cause error. " +  
98 - "Omit this field to create new device." ) 95 + @ApiModelProperty(position = 1, value = "JSON object with the Device Id. " +
  96 + "Specify this field to update the Device. " +
  97 + "Referencing non-existing Device Id will cause error. " +
  98 + "Omit this field to create new Device." )
99 @Override 99 @Override
100 public DeviceId getId() { 100 public DeviceId getId() {
101 return super.getId(); 101 return super.getId();
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.AllArgsConstructor; 20 import lombok.AllArgsConstructor;
19 import lombok.Data; 21 import lombok.Data;
20 import lombok.EqualsAndHashCode; 22 import lombok.EqualsAndHashCode;
@@ -37,15 +39,21 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> @@ -37,15 +39,21 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId>
37 39
38 private static final long serialVersionUID = 5582010124562018986L; 40 private static final long serialVersionUID = 5582010124562018986L;
39 41
  42 + @ApiModelProperty(position = 7, required = true, value = "JSON object with the referenced Entity Id (Device or Asset).")
40 private EntityId entityId; 43 private EntityId entityId;
41 private TenantId tenantId; 44 private TenantId tenantId;
42 private CustomerId customerId; 45 private CustomerId customerId;
43 @NoXss 46 @NoXss
  47 + @ApiModelProperty(position = 5, required = true, value = "Entity View name", example = "A4B72CCDFF33")
44 private String name; 48 private String name;
45 @NoXss 49 @NoXss
  50 + @ApiModelProperty(position = 6, required = true, value = "Device Profile Name", example = "Temperature Sensor")
46 private String type; 51 private String type;
  52 + @ApiModelProperty(position = 8, required = true, value = "Set of telemetry and attribute keys to expose via Entity View.")
47 private TelemetryEntityView keys; 53 private TelemetryEntityView keys;
  54 + @ApiModelProperty(position = 9, value = "Represents the start time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;")
48 private long startTimeMs; 55 private long startTimeMs;
  56 + @ApiModelProperty(position = 10, value = "Represents the end time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;")
49 private long endTimeMs; 57 private long endTimeMs;
50 58
51 public EntityView() { 59 public EntityView() {
@@ -73,6 +81,7 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> @@ -73,6 +81,7 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId>
73 return getName() /*What the ...*/; 81 return getName() /*What the ...*/;
74 } 82 }
75 83
  84 + @ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignEntityViewToCustomer' to change the Customer Id.", readOnly = true)
76 @Override 85 @Override
77 public CustomerId getCustomerId() { 86 public CustomerId getCustomerId() {
78 return customerId; 87 return customerId;
@@ -83,8 +92,31 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> @@ -83,8 +92,31 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId>
83 return name; 92 return name;
84 } 93 }
85 94
  95 + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", readOnly = true)
86 @Override 96 @Override
87 public TenantId getTenantId() { 97 public TenantId getTenantId() {
88 return tenantId; 98 return tenantId;
89 } 99 }
  100 +
  101 + @ApiModelProperty(position = 1, value = "JSON object with the Entity View Id. " +
  102 + "Specify this field to update the Entity View. " +
  103 + "Referencing non-existing Entity View Id will cause error. " +
  104 + "Omit this field to create new Entity View." )
  105 + @Override
  106 + public EntityViewId getId() {
  107 + return super.getId();
  108 + }
  109 +
  110 + @ApiModelProperty(position = 2, value = "Timestamp of the Entity View creation, in milliseconds", example = "1609459200000", readOnly = true)
  111 + @Override
  112 + public long getCreatedTime() {
  113 + return super.getCreatedTime();
  114 + }
  115 +
  116 + @ApiModelProperty(position = 11, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode")
  117 + @Override
  118 + public JsonNode getAdditionalInfo() {
  119 + return super.getAdditionalInfo();
  120 + }
  121 +
90 } 122 }
@@ -15,13 +15,16 @@ @@ -15,13 +15,16 @@
15 */ 15 */
16 package org.thingsboard.server.common.data; 16 package org.thingsboard.server.common.data;
17 17
  18 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 19 import lombok.Data;
19 import org.thingsboard.server.common.data.id.EntityViewId; 20 import org.thingsboard.server.common.data.id.EntityViewId;
20 21
21 @Data 22 @Data
22 public class EntityViewInfo extends EntityView { 23 public class EntityViewInfo extends EntityView {
23 24
  25 + @ApiModelProperty(position = 12, value = "Title of the Customer that owns the entity view.", readOnly = true)
24 private String customerTitle; 26 private String customerTitle;
  27 + @ApiModelProperty(position = 13, value = "Indicates special 'Public' Customer that is auto-generated to use the entity view on public dashboards.", readOnly = true)
25 private boolean customerIsPublic; 28 private boolean customerIsPublic;
26 29
27 public EntityViewInfo() { 30 public EntityViewInfo() {
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
  20 +import lombok.Data;
  21 +import org.thingsboard.server.common.data.security.DeviceCredentials;
  22 +
  23 +@ApiModel
  24 +@Data
  25 +public class SaveDeviceWithCredentialsRequest {
  26 +
  27 + @ApiModelProperty(position = 1, value = "The JSON with device entity.", required = true)
  28 + private final Device device;
  29 + @ApiModelProperty(position = 2, value = "The JSON with credentials entity.", required = true)
  30 + private final DeviceCredentials credentials;
  31 +
  32 +}
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.entityview; 16 package org.thingsboard.server.common.data.entityview;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import org.thingsboard.server.common.data.EntityType; 21 import org.thingsboard.server.common.data.EntityType;
20 import org.thingsboard.server.common.data.relation.EntityRelation; 22 import org.thingsboard.server.common.data.relation.EntityRelation;
@@ -25,11 +27,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters; @@ -25,11 +27,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
25 import java.util.Collections; 27 import java.util.Collections;
26 import java.util.List; 28 import java.util.List;
27 29
  30 +@ApiModel
28 @Data 31 @Data
29 public class EntityViewSearchQuery { 32 public class EntityViewSearchQuery {
30 33
  34 + @ApiModelProperty(position = 3, value = "Main search parameters.")
31 private RelationsSearchParameters parameters; 35 private RelationsSearchParameters parameters;
  36 + @ApiModelProperty(position = 1, value = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').")
32 private String relationType; 37 private String relationType;
  38 + @ApiModelProperty(position = 2, value = "Array of entity view types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').")
33 private List<String> entityViewTypes; 39 private List<String> entityViewTypes;
34 40
35 public EntityRelationsQuery toEntitySearchQuery() { 41 public EntityRelationsQuery toEntitySearchQuery() {
@@ -15,17 +15,30 @@ @@ -15,17 +15,30 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.lwm2m; 16 package org.thingsboard.server.common.data.lwm2m;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 21
  22 +@ApiModel
20 @Data 23 @Data
21 public class ServerSecurityConfig { 24 public class ServerSecurityConfig {
  25 + @ApiModelProperty(position = 1, value = "Is Bootstrap Server", example = "true", readOnly = true)
  26 + boolean bootstrapServerIs = true;
  27 + @ApiModelProperty(position = 2, value = "Host for 'No Security' mode", example = "0.0.0.0", readOnly = true)
22 String host; 28 String host;
23 - String securityHost; 29 + @ApiModelProperty(position = 3, value = "Port for 'No Security' mode", example = "5687", readOnly = true)
24 Integer port; 30 Integer port;
  31 + @ApiModelProperty(position = 4, value = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", readOnly = true)
  32 + String securityHost;
  33 + @ApiModelProperty(position = 5, value = "Port for 'Security' mode (DTLS)", example = "5688", readOnly = true)
25 Integer securityPort; 34 Integer securityPort;
26 - String serverPublicKey;  
27 - boolean bootstrapServerIs = true;  
28 - Integer clientHoldOffTime = 1; 35 + @ApiModelProperty(position = 5, value = "Server short Id", example = "111", readOnly = true)
29 Integer serverId = 111; 36 Integer serverId = 111;
  37 + @ApiModelProperty(position = 7, value = "Client Hold Off Time", example = "1", readOnly = true)
  38 + Integer clientHoldOffTime = 1;
  39 + @ApiModelProperty(position = 8, value = "Server Public Key (base64 encoded)", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" +
  40 + "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", readOnly = true)
  41 + String serverPublicKey;
  42 + @ApiModelProperty(position = 9, value = "Bootstrap Server Account Timeout", example = "0", readOnly = true)
30 Integer bootstrapServerAccountTimeout = 0; 43 Integer bootstrapServerAccountTimeout = 0;
31 } 44 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.objects; 16 package org.thingsboard.server.common.data.objects;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import lombok.NoArgsConstructor; 21 import lombok.NoArgsConstructor;
20 22
@@ -26,11 +28,15 @@ import java.util.List; @@ -26,11 +28,15 @@ import java.util.List;
26 * Created by Victor Basanets on 9/05/2017. 28 * Created by Victor Basanets on 9/05/2017.
27 */ 29 */
28 @Data 30 @Data
  31 +@ApiModel
29 @NoArgsConstructor 32 @NoArgsConstructor
30 public class AttributesEntityView implements Serializable { 33 public class AttributesEntityView implements Serializable {
31 34
  35 + @ApiModelProperty(position = 1, required = true, value = "List of client-side attribute keys to expose", example = "currentConfiguration")
32 private List<String> cs = new ArrayList<>(); 36 private List<String> cs = new ArrayList<>();
  37 + @ApiModelProperty(position = 3, required = true, value = "List of server-side attribute keys to expose", example = "model")
33 private List<String> ss = new ArrayList<>(); 38 private List<String> ss = new ArrayList<>();
  39 + @ApiModelProperty(position = 2, required = true, value = "List of shared attribute keys to expose", example = "targetConfiguration")
34 private List<String> sh = new ArrayList<>(); 40 private List<String> sh = new ArrayList<>();
35 41
36 public AttributesEntityView(List<String> cs, 42 public AttributesEntityView(List<String> cs,
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.common.data.objects; 16 package org.thingsboard.server.common.data.objects;
17 17
  18 +import io.swagger.annotations.ApiModel;
  19 +import io.swagger.annotations.ApiModelProperty;
18 import lombok.Data; 20 import lombok.Data;
19 import lombok.NoArgsConstructor; 21 import lombok.NoArgsConstructor;
20 22
@@ -25,11 +27,14 @@ import java.util.List; @@ -25,11 +27,14 @@ import java.util.List;
25 /** 27 /**
26 * Created by Victor Basanets on 9/05/2017. 28 * Created by Victor Basanets on 9/05/2017.
27 */ 29 */
  30 +@ApiModel
28 @Data 31 @Data
29 @NoArgsConstructor 32 @NoArgsConstructor
30 public class TelemetryEntityView implements Serializable { 33 public class TelemetryEntityView implements Serializable {
31 34
  35 + @ApiModelProperty(position = 1, required = true, value = "List of time-series data keys to expose", example = "temperature, humidity")
32 private List<String> timeseries; 36 private List<String> timeseries;
  37 + @ApiModelProperty(position = 2, required = true, value = "JSON object with attributes to expose")
33 private AttributesEntityView attributes; 38 private AttributesEntityView attributes;
34 39
35 public TelemetryEntityView(List<String> timeseries, AttributesEntityView attributes) { 40 public TelemetryEntityView(List<String> timeseries, AttributesEntityView attributes) {
@@ -57,6 +57,7 @@ import org.thingsboard.server.common.data.EntityViewInfo; @@ -57,6 +57,7 @@ import org.thingsboard.server.common.data.EntityViewInfo;
57 import org.thingsboard.server.common.data.Event; 57 import org.thingsboard.server.common.data.Event;
58 import org.thingsboard.server.common.data.OtaPackage; 58 import org.thingsboard.server.common.data.OtaPackage;
59 import org.thingsboard.server.common.data.OtaPackageInfo; 59 import org.thingsboard.server.common.data.OtaPackageInfo;
  60 +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest;
60 import org.thingsboard.server.common.data.TbResource; 61 import org.thingsboard.server.common.data.TbResource;
61 import org.thingsboard.server.common.data.TbResourceInfo; 62 import org.thingsboard.server.common.data.TbResourceInfo;
62 import org.thingsboard.server.common.data.Tenant; 63 import org.thingsboard.server.common.data.Tenant;
@@ -1131,11 +1132,8 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1131,11 +1132,8 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1131 1132
1132 public Optional<Device> saveDeviceWithCredentials(Device device, DeviceCredentials credentials) { 1133 public Optional<Device> saveDeviceWithCredentials(Device device, DeviceCredentials credentials) {
1133 try { 1134 try {
1134 - Map<Class<?>, Object> deviceCredentials = new ConcurrentHashMap<>();  
1135 - deviceCredentials.put(Device.class, device);  
1136 - deviceCredentials.put(DeviceCredentials.class, credentials);  
1137 -// return restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class).getBody();  
1138 - ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/lwm2m/device-credentials", deviceCredentials, Device.class); 1135 + SaveDeviceWithCredentialsRequest request = new SaveDeviceWithCredentialsRequest(device, credentials);
  1136 + ResponseEntity<Device> deviceOpt = restTemplate.postForEntity(baseURL + "/api/device-with-credentials", request, Device.class);
1139 return Optional.ofNullable(deviceOpt.getBody()); 1137 return Optional.ofNullable(deviceOpt.getBody());
1140 } catch (HttpClientErrorException exception) { 1138 } catch (HttpClientErrorException exception) {
1141 if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { 1139 if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
@@ -1146,7 +1144,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1146,7 +1144,6 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1146 } 1144 }
1147 } 1145 }
1148 1146
1149 -  
1150 public PageData<Device> getTenantDevices(String type, PageLink pageLink) { 1147 public PageData<Device> getTenantDevices(String type, PageLink pageLink) {
1151 Map<String, String> params = new HashMap<>(); 1148 Map<String, String> params = new HashMap<>();
1152 params.put("type", type); 1149 params.put("type", type);