Commit 85b1cd0401e5de381af0188b842215fc83bb566a

Authored by Dima Landiak
1 parent 3c665ecd

added description to device profile controller

@@ -155,6 +155,8 @@ public abstract class BaseController { @@ -155,6 +155,8 @@ public abstract class BaseController {
155 155
156 /*Swagger UI description*/ 156 /*Swagger UI description*/
157 157
  158 + protected static final String NEW_LINE = "\n\n";
  159 +
158 public static final String CUSTOMER_ID = "customerId"; 160 public static final String CUSTOMER_ID = "customerId";
159 public static final String TENANT_ID = "tenantId"; 161 public static final String TENANT_ID = "tenantId";
160 public static final String DEVICE_ID = "deviceId"; 162 public static final String DEVICE_ID = "deviceId";
@@ -239,7 +241,7 @@ public abstract class BaseController { @@ -239,7 +241,7 @@ public abstract class BaseController {
239 protected static final String EVENT_END_TIME_DESCRIPTION = "Timestamp. Events with creation time after it won't be queried."; 241 protected static final String EVENT_END_TIME_DESCRIPTION = "Timestamp. Events with creation time after it won't be queried.";
240 242
241 protected static final String EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Unassignment works in async way - first, 'unassign' notification event pushed to edge queue on platform. "; 243 protected static final String EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Unassignment works in async way - first, 'unassign' notification event pushed to edge queue on platform. ";
242 - protected static final String EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)" ; 244 + protected static final String EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
243 protected static final String EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Assignment works in async way - first, notification event pushed to edge service queue on platform. "; 245 protected static final String EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION = "Assignment works in async way - first, notification event pushed to edge service queue on platform. ";
244 protected static final String EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)"; 246 protected static final String EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION = "(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
245 247
@@ -257,41 +259,112 @@ public abstract class BaseController { @@ -257,41 +259,112 @@ public abstract class BaseController {
257 protected static final String EVENT_DEBUG_RULE_NODE_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_NODE\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END; 259 protected static final String EVENT_DEBUG_RULE_NODE_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_NODE\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
258 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_CHAIN\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END; 260 protected static final String EVENT_DEBUG_RULE_CHAIN_FILTER_OBJ = MARKDOWN_CODE_BLOCK_START + "{ \"eventType\": \"DEBUG_RULE_CHAIN\"," + DEBUG_FILTER_OBJ + MARKDOWN_CODE_BLOCK_END;
259 261
260 - protected static final String DEVICE_PROFILE_ALARM_CREATE_RULES_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{ \"createRules\": { \"MAJOR\": { \"schedule\": null, \"condition\": { \"spec\": { \"type\": \"SIMPLE\" }, " +  
261 - "\"condition\": [{ \"key\": { \"key\": \"temp\", \"type\": \"TIME_SERIES\" }, \"value\": null, \"predicate\": { \"type\": \"NUMERIC\", \"value\": { \"userValue\": null, \"defaultValue\": 30.0, \"dynamicValue\": null }, " +  
262 - "\"operation\": \"GREATER\" }, \"valueType\": \"NUMERIC\" }] }, \"dashboardId\": null, \"alarmDetails\": null }, \"CRITICAL\": { \"schedule\": null, \"condition\": { \"spec\": { \"type\": \"SIMPLE\" }, \"condition\": " +  
263 - "[{ \"key\": { \"key\": \"temp\", \"type\": \"TIME_SERIES\" }, \"value\": null, \"predicate\": { \"type\": \"NUMERIC\", \"value\": { \"userValue\": null, \"defaultValue\": 50.0, \"dynamicValue\": null }, \"operation\": \"GREATER\" }, " +  
264 - "\"valueType\": \"NUMERIC\" }] }, \"dashboardId\": null, \"alarmDetails\": null } } }" + MARKDOWN_CODE_BLOCK_END; 262 + protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
  263 + "Provides a hint about the data type of the entity field that is defined in the filter key. " +
  264 + "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." +
  265 + "The following filter value types and corresponding predicate operations are supported: " + NEW_LINE +
  266 + " * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +
  267 + " * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +
  268 + " * 'BOOLEAN' - used for boolean values. Operations: EQUAL, NOT_EQUAL;\n" +
  269 + " * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";
265 270
266 protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE = MARKDOWN_CODE_BLOCK_START + 271 protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
267 - "{ \"schedule\": { \"type\": \"SPECIFIC_TIME\", \"endsOn\": 64800000, \"startsOn\": 43200000, \"timezone\": \"Europe/Kiev\", \"daysOfWeek\": [1, 3, 7] } }" + 272 + "{\n" +
  273 + " \"schedule\":{\n" +
  274 + " \"type\":\"SPECIFIC_TIME\",\n" +
  275 + " \"endsOn\":64800000,\n" +
  276 + " \"startsOn\":43200000,\n" +
  277 + " \"timezone\":\"Europe/Kiev\",\n" +
  278 + " \"daysOfWeek\":[\n" +
  279 + " 1,\n" +
  280 + " 3,\n" +
  281 + " 5\n" +
  282 + " ]\n" +
  283 + " }\n" +
  284 + "}" +
268 MARKDOWN_CODE_BLOCK_END; 285 MARKDOWN_CODE_BLOCK_END;
269 protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE = MARKDOWN_CODE_BLOCK_START + 286 protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
270 - "{ \"schedule\": { \"type\": \"CUSTOM\", \"items\": [{ \"endsOn\": 64800000, \"enabled\": true, \"startsOn\": 43200000, \"dayOfWeek\": 1 }, " +  
271 - "{ \"endsOn\": 0, \"enabled\": false, \"startsOn\": 0, \"dayOfWeek\": 2 }, { \"endsOn\": 57600000, \"enabled\": true, \"startsOn\": 36000000, \"dayOfWeek\": 3 }, " +  
272 - "{ \"endsOn\": 0, \"enabled\": false, \"startsOn\": 0, \"dayOfWeek\": 4 }, { \"endsOn\": 68400000, \"enabled\": true, \"startsOn\": 32400000, \"dayOfWeek\": 5 }, " +  
273 - "{ \"endsOn\": 0, \"enabled\": false, \"startsOn\": 0, \"dayOfWeek\": 6 }, { \"endsOn\": 0, \"enabled\": false, \"startsOn\": 0, \"dayOfWeek\": 7 }], \"timezone\": \"Europe/Kiev\" } }" + 287 + "{\n" +
  288 + " \"schedule\":{\n" +
  289 + " \"type\":\"CUSTOM\",\n" +
  290 + " \"items\":[\n" +
  291 + " {\n" +
  292 + " \"endsOn\":0,\n" +
  293 + " \"enabled\":false,\n" +
  294 + " \"startsOn\":0,\n" +
  295 + " \"dayOfWeek\":1\n" +
  296 + " },\n" +
  297 + " {\n" +
  298 + " \"endsOn\":64800000,\n" +
  299 + " \"enabled\":true,\n" +
  300 + " \"startsOn\":43200000,\n" +
  301 + " \"dayOfWeek\":2\n" +
  302 + " },\n" +
  303 + " {\n" +
  304 + " \"endsOn\":0,\n" +
  305 + " \"enabled\":false,\n" +
  306 + " \"startsOn\":0,\n" +
  307 + " \"dayOfWeek\":3\n" +
  308 + " },\n" +
  309 + " {\n" +
  310 + " \"endsOn\":57600000,\n" +
  311 + " \"enabled\":true,\n" +
  312 + " \"startsOn\":36000000,\n" +
  313 + " \"dayOfWeek\":4\n" +
  314 + " },\n" +
  315 + " {\n" +
  316 + " \"endsOn\":0,\n" +
  317 + " \"enabled\":false,\n" +
  318 + " \"startsOn\":0,\n" +
  319 + " \"dayOfWeek\":5\n" +
  320 + " },\n" +
  321 + " {\n" +
  322 + " \"endsOn\":0,\n" +
  323 + " \"enabled\":false,\n" +
  324 + " \"startsOn\":0,\n" +
  325 + " \"dayOfWeek\":6\n" +
  326 + " },\n" +
  327 + " {\n" +
  328 + " \"endsOn\":0,\n" +
  329 + " \"enabled\":false,\n" +
  330 + " \"startsOn\":0,\n" +
  331 + " \"dayOfWeek\":7\n" +
  332 + " }\n" +
  333 + " ],\n" +
  334 + " \"timezone\":\"Europe/Kiev\"\n" +
  335 + " }\n" +
  336 + "}" +
274 MARKDOWN_CODE_BLOCK_END; 337 MARKDOWN_CODE_BLOCK_END;
275 - protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\"schedule\": null}" + MARKDOWN_CODE_BLOCK_END; 338 + protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "\"schedule\": null" + MARKDOWN_CODE_BLOCK_END;
276 339
277 protected static final String DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE = MARKDOWN_CODE_BLOCK_START + 340 protected static final String DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
278 - "{ \"spec\": { \"type\": \"DURATION\", \"unit\": \"MINUTES\", \"predicate\": { \"userValue\": null, \"defaultValue\": 30, \"dynamicValue\": null } } }" + 341 + "{\n" +
  342 + " \"spec\":{\n" +
  343 + " \"type\":\"REPEATING\",\n" +
  344 + " \"predicate\":{\n" +
  345 + " \"userValue\":null,\n" +
  346 + " \"defaultValue\":5,\n" +
  347 + " \"dynamicValue\":{\n" +
  348 + " \"inherit\":true,\n" +
  349 + " \"sourceType\":\"CURRENT_DEVICE\",\n" +
  350 + " \"sourceAttribute\":\"tempAttr\"\n" +
  351 + " }\n" +
  352 + " }\n" +
  353 + " }\n" +
  354 + "}" +
279 MARKDOWN_CODE_BLOCK_END; 355 MARKDOWN_CODE_BLOCK_END;
280 protected static final String DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START + 356 protected static final String DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
281 - "{ \"spec\": { \"type\": \"REPEATING\", \"predicate\": { \"userValue\": null, \"defaultValue\": 3, \"dynamicValue\": " +  
282 - "{ \"inherit\": false, \"sourceType\": \"CURRENT_DEVICE\", \"sourceAttribute\": \"repeatingLimit\" } } } }" +  
283 - MARKDOWN_CODE_BLOCK_END;  
284 -  
285 - protected static final String DEVICE_PROFILE_CONDITIONS_TIME_SERIES_NUMERIC_EXAMPLE = MARKDOWN_CODE_BLOCK_START +  
286 - "{ \"condition\": [{ \"key\": { \"key\": \"temp\", \"type\": \"TIME_SERIES\" }, " +  
287 - "\"value\": null, \"predicate\": { \"type\": \"NUMERIC\", \"value\": { \"userValue\": null, \"defaultValue\": 30.0, \"dynamicValue\": null }, \"operation\": \"GREATER\" }, " +  
288 - "\"valueType\": \"NUMERIC\" }] }" +  
289 - MARKDOWN_CODE_BLOCK_END;  
290 -  
291 - protected static final String DEVICE_PROFILE_CONDITIONS_CONSTANT_EXAMPLE = MARKDOWN_CODE_BLOCK_START +  
292 - "{ \"condition\": [{ \"key\": { \"key\": \"constantKey\", \"type\": \"CONSTANT\" }, \"value\": true, \"predicate\": { \"type\": \"BOOLEAN\", \"value\": " +  
293 - "{ \"userValue\": null, \"defaultValue\": false, \"dynamicValue\": { \"inherit\": false, \"sourceType\": \"CURRENT_TENANT\", \"sourceAttribute\": \"alarmEnabled\" } }, " +  
294 - "\"operation\": \"EQUAL\" }, \"valueType\": \"BOOLEAN\" }] }" + 357 + "{\n" +
  358 + " \"spec\":{\n" +
  359 + " \"type\":\"DURATION\",\n" +
  360 + " \"unit\":\"MINUTES\",\n" +
  361 + " \"predicate\":{\n" +
  362 + " \"userValue\":null,\n" +
  363 + " \"defaultValue\":30,\n" +
  364 + " \"dynamicValue\":null\n" +
  365 + " }\n" +
  366 + " }\n" +
  367 + "}" +
295 MARKDOWN_CODE_BLOCK_END; 368 MARKDOWN_CODE_BLOCK_END;
296 369
297 protected static final String RELATION_TYPE_PARAM_DESCRIPTION = "A string value representing relation type between entities. For example, 'Contains', 'Manages'. It can be any string value."; 370 protected static final String RELATION_TYPE_PARAM_DESCRIPTION = "A string value representing relation type between entities. For example, 'Contains', 'Manages'. It can be any string value.";
@@ -299,8 +372,6 @@ public abstract class BaseController { @@ -299,8 +372,6 @@ public abstract class BaseController {
299 372
300 protected static final String ADMINISTRATOR_AUTHORITY_ONLY = "Available for users with 'Tenant Administrator' authority only."; 373 protected static final String ADMINISTRATOR_AUTHORITY_ONLY = "Available for users with 'Tenant Administrator' authority only.";
301 374
302 - protected static final String NEW_LINE = "\n\n";  
303 -  
304 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; 375 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
305 protected static final String DEFAULT_DASHBOARD = "defaultDashboardId"; 376 protected static final String DEFAULT_DASHBOARD = "defaultDashboardId";
306 protected static final String HOME_DASHBOARD = "homeDashboardId"; 377 protected static final String HOME_DASHBOARD = "homeDashboardId";
@@ -55,6 +55,453 @@ import java.util.UUID; @@ -55,6 +55,453 @@ import java.util.UUID;
55 @Slf4j 55 @Slf4j
56 public class DeviceProfileController extends BaseController { 56 public class DeviceProfileController extends BaseController {
57 57
  58 + private static final String COAP_TRANSPORT_CONFIGURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
  59 + "{\n" +
  60 + " \"type\":\"COAP\",\n" +
  61 + " \"clientSettings\":{\n" +
  62 + " \"edrxCycle\":null,\n" +
  63 + " \"powerMode\":\"DRX\",\n" +
  64 + " \"psmActivityTimer\":null,\n" +
  65 + " \"pagingTransmissionWindow\":null\n" +
  66 + " },\n" +
  67 + " \"coapDeviceTypeConfiguration\":{\n" +
  68 + " \"coapDeviceType\":\"DEFAULT\",\n" +
  69 + " \"transportPayloadTypeConfiguration\":{\n" +
  70 + " \"transportPayloadType\":\"JSON\"\n" +
  71 + " }\n" +
  72 + " }\n" +
  73 + "}"
  74 + + MARKDOWN_CODE_BLOCK_END;
  75 +
  76 + private static final String TRANSPORT_CONFIGURATION = "# Transport Configuration" + NEW_LINE +
  77 + "5 transport configuration types are available:\n" +
  78 + " * 'DEFAULT';\n" +
  79 + " * 'MQTT';\n" +
  80 + " * 'LWM2M';\n" +
  81 + " * 'COAP';\n" +
  82 + " * 'SNMP'." + NEW_LINE + "Default type supports basic MQTT, HTTP, CoAP and LwM2M transports. " +
  83 + "Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-profiles/#transport-configuration) for more details about other types.\n" +
  84 + "\nSee another example of COAP transport configuration below:" + NEW_LINE + COAP_TRANSPORT_CONFIGURATION_EXAMPLE;
  85 +
  86 + private static final String ALARM_FILTER_KEY = "## Alarm Filter Key" + NEW_LINE +
  87 + "Filter Key defines either entity field, attribute, telemetry or constant. It is a JSON object that consists the key name and type. The following filter key types are supported:\n" +
  88 + " * 'ATTRIBUTE' - used for attributes values;\n" +
  89 + " * 'TIME_SERIES' - used for time-series values;\n" +
  90 + " * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type;\n" +
  91 + " * 'CONSTANT' - constant value specified." + NEW_LINE + "Let's review the example:" + NEW_LINE +
  92 + MARKDOWN_CODE_BLOCK_START +
  93 + "{\n" +
  94 + " \"type\": \"TIME_SERIES\",\n" +
  95 + " \"key\": \"temperature\"\n" +
  96 + "}" +
  97 + MARKDOWN_CODE_BLOCK_END;
  98 +
  99 + private static final String FILTER_PREDICATE = NEW_LINE + "## Filter Predicate" + NEW_LINE +
  100 + "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
  101 + "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." + NEW_LINE +
  102 + "Simple predicate example to check 'value < 100': " + NEW_LINE +
  103 + MARKDOWN_CODE_BLOCK_START +
  104 + "{\n" +
  105 + " \"operation\": \"LESS\",\n" +
  106 + " \"value\": {\n" +
  107 + " \"userValue\": null,\n" +
  108 + " \"defaultValue\": 100,\n" +
  109 + " \"dynamicValue\": null\n" +
  110 + " },\n" +
  111 + " \"type\": \"NUMERIC\"\n" +
  112 + "}" +
  113 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  114 + "Complex predicate example, to check 'value < 10 or value > 20': " + NEW_LINE +
  115 + MARKDOWN_CODE_BLOCK_START +
  116 + "{\n" +
  117 + " \"type\": \"COMPLEX\",\n" +
  118 + " \"operation\": \"OR\",\n" +
  119 + " \"predicates\": [\n" +
  120 + " {\n" +
  121 + " \"operation\": \"LESS\",\n" +
  122 + " \"value\": {\n" +
  123 + " \"userValue\": null,\n" +
  124 + " \"defaultValue\": 10,\n" +
  125 + " \"dynamicValue\": null\n" +
  126 + " },\n" +
  127 + " \"type\": \"NUMERIC\"\n" +
  128 + " },\n" +
  129 + " {\n" +
  130 + " \"operation\": \"GREATER\",\n" +
  131 + " \"value\": {\n" +
  132 + " \"userValue\": null,\n" +
  133 + " \"defaultValue\": 20,\n" +
  134 + " \"dynamicValue\": null\n" +
  135 + " },\n" +
  136 + " \"type\": \"NUMERIC\"\n" +
  137 + " }\n" +
  138 + " ]\n" +
  139 + "}" +
  140 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  141 + "More complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': " + NEW_LINE +
  142 + MARKDOWN_CODE_BLOCK_START +
  143 + "{\n" +
  144 + " \"type\": \"COMPLEX\",\n" +
  145 + " \"operation\": \"OR\",\n" +
  146 + " \"predicates\": [\n" +
  147 + " {\n" +
  148 + " \"operation\": \"LESS\",\n" +
  149 + " \"value\": {\n" +
  150 + " \"userValue\": null,\n" +
  151 + " \"defaultValue\": 10,\n" +
  152 + " \"dynamicValue\": null\n" +
  153 + " },\n" +
  154 + " \"type\": \"NUMERIC\"\n" +
  155 + " },\n" +
  156 + " {\n" +
  157 + " \"type\": \"COMPLEX\",\n" +
  158 + " \"operation\": \"AND\",\n" +
  159 + " \"predicates\": [\n" +
  160 + " {\n" +
  161 + " \"operation\": \"GREATER\",\n" +
  162 + " \"value\": {\n" +
  163 + " \"userValue\": null,\n" +
  164 + " \"defaultValue\": 50,\n" +
  165 + " \"dynamicValue\": null\n" +
  166 + " },\n" +
  167 + " \"type\": \"NUMERIC\"\n" +
  168 + " },\n" +
  169 + " {\n" +
  170 + " \"operation\": \"LESS\",\n" +
  171 + " \"value\": {\n" +
  172 + " \"userValue\": null,\n" +
  173 + " \"defaultValue\": 60,\n" +
  174 + " \"dynamicValue\": null\n" +
  175 + " },\n" +
  176 + " \"type\": \"NUMERIC\"\n" +
  177 + " }\n" +
  178 + " ]\n" +
  179 + " }\n" +
  180 + " ]\n" +
  181 + "}" +
  182 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  183 + "You may also want to replace hardcoded values (for example, temperature > 20) with the more dynamic " +
  184 + "expression (for example, temperature > value of the tenant attribute with key 'temperatureThreshold'). " +
  185 + "It is possible to use 'dynamicValue' to define attribute of the tenant, customer or device. " +
  186 + "See example below:" + NEW_LINE +
  187 + MARKDOWN_CODE_BLOCK_START +
  188 + "{\n" +
  189 + " \"operation\": \"GREATER\",\n" +
  190 + " \"value\": {\n" +
  191 + " \"userValue\": null,\n" +
  192 + " \"defaultValue\": 0,\n" +
  193 + " \"dynamicValue\": {\n" +
  194 + " \"inherit\": false,\n" +
  195 + " \"sourceType\": \"CURRENT_TENANT\",\n" +
  196 + " \"sourceAttribute\": \"temperatureThreshold\"\n" +
  197 + " }\n" +
  198 + " },\n" +
  199 + " \"type\": \"NUMERIC\"\n" +
  200 + "}" +
  201 + MARKDOWN_CODE_BLOCK_END + NEW_LINE +
  202 + "Note that you may use 'CURRENT_DEVICE', 'CURRENT_CUSTOMER' and 'CURRENT_TENANT' as a 'sourceType'. The 'defaultValue' is used when the attribute with such a name is not defined for the chosen source. " +
  203 + "The 'sourceAttribute' can be inherited from the owner of the specified 'sourceType' if 'inherit' is set to true.";
  204 +
  205 + private static final String KEY_FILTERS_DESCRIPTION = "# Key Filters" + NEW_LINE +
  206 + "Key filter objects are created under the **'condition'** array. They allow you to define complex logical expressions over entity field, " +
  207 + "attribute, latest time-series value or constant. The filter is defined using 'key', 'valueType', " +
  208 + "'value' (refers to the value of the 'CONSTANT' alarm filter key type) and 'predicate' objects. Let's review each object:" + NEW_LINE +
  209 + ALARM_FILTER_KEY + FILTER_VALUE_TYPE + NEW_LINE + FILTER_PREDICATE + NEW_LINE;
  210 +
  211 + private static final String DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
  212 + " \"alarms\":[\n" +
  213 + " ],\n" +
  214 + " \"configuration\":{\n" +
  215 + " \"type\":\"DEFAULT\"\n" +
  216 + " },\n" +
  217 + " \"provisionConfiguration\":{\n" +
  218 + " \"type\":\"DISABLED\",\n" +
  219 + " \"provisionDeviceSecret\":null\n" +
  220 + " },\n" +
  221 + " \"transportConfiguration\":{\n" +
  222 + " \"type\":\"DEFAULT\"\n" +
  223 + " }\n" +
  224 + "}" + MARKDOWN_CODE_BLOCK_END;
  225 +
  226 + private static final String CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
  227 + " \"alarms\":[\n" +
  228 + " {\n" +
  229 + " \"id\":\"2492b935-1226-59e9-8615-17d8978a4f93\",\n" +
  230 + " \"alarmType\":\"Temperature Alarm\",\n" +
  231 + " \"clearRule\":{\n" +
  232 + " \"schedule\":null,\n" +
  233 + " \"condition\":{\n" +
  234 + " \"spec\":{\n" +
  235 + " \"type\":\"SIMPLE\"\n" +
  236 + " },\n" +
  237 + " \"condition\":[\n" +
  238 + " {\n" +
  239 + " \"key\":{\n" +
  240 + " \"key\":\"temperature\",\n" +
  241 + " \"type\":\"TIME_SERIES\"\n" +
  242 + " },\n" +
  243 + " \"value\":null,\n" +
  244 + " \"predicate\":{\n" +
  245 + " \"type\":\"NUMERIC\",\n" +
  246 + " \"value\":{\n" +
  247 + " \"userValue\":null,\n" +
  248 + " \"defaultValue\":30.0,\n" +
  249 + " \"dynamicValue\":null\n" +
  250 + " },\n" +
  251 + " \"operation\":\"LESS\"\n" +
  252 + " },\n" +
  253 + " \"valueType\":\"NUMERIC\"\n" +
  254 + " }\n" +
  255 + " ]\n" +
  256 + " },\n" +
  257 + " \"dashboardId\":null,\n" +
  258 + " \"alarmDetails\":null\n" +
  259 + " },\n" +
  260 + " \"propagate\":false,\n" +
  261 + " \"createRules\":{\n" +
  262 + " \"MAJOR\":{\n" +
  263 + " \"schedule\":{\n" +
  264 + " \"type\":\"SPECIFIC_TIME\",\n" +
  265 + " \"endsOn\":64800000,\n" +
  266 + " \"startsOn\":43200000,\n" +
  267 + " \"timezone\":\"Europe/Kiev\",\n" +
  268 + " \"daysOfWeek\":[\n" +
  269 + " 1,\n" +
  270 + " 3,\n" +
  271 + " 5\n" +
  272 + " ]\n" +
  273 + " },\n" +
  274 + " \"condition\":{\n" +
  275 + " \"spec\":{\n" +
  276 + " \"type\":\"DURATION\",\n" +
  277 + " \"unit\":\"MINUTES\",\n" +
  278 + " \"predicate\":{\n" +
  279 + " \"userValue\":null,\n" +
  280 + " \"defaultValue\":30,\n" +
  281 + " \"dynamicValue\":null\n" +
  282 + " }\n" +
  283 + " },\n" +
  284 + " \"condition\":[\n" +
  285 + " {\n" +
  286 + " \"key\":{\n" +
  287 + " \"key\":\"temperature\",\n" +
  288 + " \"type\":\"TIME_SERIES\"\n" +
  289 + " },\n" +
  290 + " \"value\":null,\n" +
  291 + " \"predicate\":{\n" +
  292 + " \"type\":\"COMPLEX\",\n" +
  293 + " \"operation\":\"OR\",\n" +
  294 + " \"predicates\":[\n" +
  295 + " {\n" +
  296 + " \"type\":\"NUMERIC\",\n" +
  297 + " \"value\":{\n" +
  298 + " \"userValue\":null,\n" +
  299 + " \"defaultValue\":50.0,\n" +
  300 + " \"dynamicValue\":null\n" +
  301 + " },\n" +
  302 + " \"operation\":\"LESS_OR_EQUAL\"\n" +
  303 + " },\n" +
  304 + " {\n" +
  305 + " \"type\":\"NUMERIC\",\n" +
  306 + " \"value\":{\n" +
  307 + " \"userValue\":null,\n" +
  308 + " \"defaultValue\":30.0,\n" +
  309 + " \"dynamicValue\":null\n" +
  310 + " },\n" +
  311 + " \"operation\":\"GREATER\"\n" +
  312 + " }\n" +
  313 + " ]\n" +
  314 + " },\n" +
  315 + " \"valueType\":\"NUMERIC\"\n" +
  316 + " }\n" +
  317 + " ]\n" +
  318 + " },\n" +
  319 + " \"dashboardId\":null,\n" +
  320 + " \"alarmDetails\":null\n" +
  321 + " },\n" +
  322 + " \"WARNING\":{\n" +
  323 + " \"schedule\":{\n" +
  324 + " \"type\":\"CUSTOM\",\n" +
  325 + " \"items\":[\n" +
  326 + " {\n" +
  327 + " \"endsOn\":0,\n" +
  328 + " \"enabled\":false,\n" +
  329 + " \"startsOn\":0,\n" +
  330 + " \"dayOfWeek\":1\n" +
  331 + " },\n" +
  332 + " {\n" +
  333 + " \"endsOn\":64800000,\n" +
  334 + " \"enabled\":true,\n" +
  335 + " \"startsOn\":43200000,\n" +
  336 + " \"dayOfWeek\":2\n" +
  337 + " },\n" +
  338 + " {\n" +
  339 + " \"endsOn\":0,\n" +
  340 + " \"enabled\":false,\n" +
  341 + " \"startsOn\":0,\n" +
  342 + " \"dayOfWeek\":3\n" +
  343 + " },\n" +
  344 + " {\n" +
  345 + " \"endsOn\":57600000,\n" +
  346 + " \"enabled\":true,\n" +
  347 + " \"startsOn\":36000000,\n" +
  348 + " \"dayOfWeek\":4\n" +
  349 + " },\n" +
  350 + " {\n" +
  351 + " \"endsOn\":0,\n" +
  352 + " \"enabled\":false,\n" +
  353 + " \"startsOn\":0,\n" +
  354 + " \"dayOfWeek\":5\n" +
  355 + " },\n" +
  356 + " {\n" +
  357 + " \"endsOn\":0,\n" +
  358 + " \"enabled\":false,\n" +
  359 + " \"startsOn\":0,\n" +
  360 + " \"dayOfWeek\":6\n" +
  361 + " },\n" +
  362 + " {\n" +
  363 + " \"endsOn\":0,\n" +
  364 + " \"enabled\":false,\n" +
  365 + " \"startsOn\":0,\n" +
  366 + " \"dayOfWeek\":7\n" +
  367 + " }\n" +
  368 + " ],\n" +
  369 + " \"timezone\":\"Europe/Kiev\"\n" +
  370 + " },\n" +
  371 + " \"condition\":{\n" +
  372 + " \"spec\":{\n" +
  373 + " \"type\":\"REPEATING\",\n" +
  374 + " \"predicate\":{\n" +
  375 + " \"userValue\":null,\n" +
  376 + " \"defaultValue\":5,\n" +
  377 + " \"dynamicValue\":null\n" +
  378 + " }\n" +
  379 + " },\n" +
  380 + " \"condition\":[\n" +
  381 + " {\n" +
  382 + " \"key\":{\n" +
  383 + " \"key\":\"tempConstant\",\n" +
  384 + " \"type\":\"CONSTANT\"\n" +
  385 + " },\n" +
  386 + " \"value\":30,\n" +
  387 + " \"predicate\":{\n" +
  388 + " \"type\":\"NUMERIC\",\n" +
  389 + " \"value\":{\n" +
  390 + " \"userValue\":null,\n" +
  391 + " \"defaultValue\":0.0,\n" +
  392 + " \"dynamicValue\":{\n" +
  393 + " \"inherit\":false,\n" +
  394 + " \"sourceType\":\"CURRENT_DEVICE\",\n" +
  395 + " \"sourceAttribute\":\"tempThreshold\"\n" +
  396 + " }\n" +
  397 + " },\n" +
  398 + " \"operation\":\"EQUAL\"\n" +
  399 + " },\n" +
  400 + " \"valueType\":\"NUMERIC\"\n" +
  401 + " }\n" +
  402 + " ]\n" +
  403 + " },\n" +
  404 + " \"dashboardId\":null,\n" +
  405 + " \"alarmDetails\":null\n" +
  406 + " },\n" +
  407 + " \"CRITICAL\":{\n" +
  408 + " \"schedule\":null,\n" +
  409 + " \"condition\":{\n" +
  410 + " \"spec\":{\n" +
  411 + " \"type\":\"SIMPLE\"\n" +
  412 + " },\n" +
  413 + " \"condition\":[\n" +
  414 + " {\n" +
  415 + " \"key\":{\n" +
  416 + " \"key\":\"temperature\",\n" +
  417 + " \"type\":\"TIME_SERIES\"\n" +
  418 + " },\n" +
  419 + " \"value\":null,\n" +
  420 + " \"predicate\":{\n" +
  421 + " \"type\":\"NUMERIC\",\n" +
  422 + " \"value\":{\n" +
  423 + " \"userValue\":null,\n" +
  424 + " \"defaultValue\":50.0,\n" +
  425 + " \"dynamicValue\":null\n" +
  426 + " },\n" +
  427 + " \"operation\":\"GREATER\"\n" +
  428 + " },\n" +
  429 + " \"valueType\":\"NUMERIC\"\n" +
  430 + " }\n" +
  431 + " ]\n" +
  432 + " },\n" +
  433 + " \"dashboardId\":null,\n" +
  434 + " \"alarmDetails\":null\n" +
  435 + " }\n" +
  436 + " },\n" +
  437 + " \"propagateRelationTypes\":null\n" +
  438 + " }\n" +
  439 + " ],\n" +
  440 + " \"configuration\":{\n" +
  441 + " \"type\":\"DEFAULT\"\n" +
  442 + " },\n" +
  443 + " \"provisionConfiguration\":{\n" +
  444 + " \"type\":\"ALLOW_CREATE_NEW_DEVICES\",\n" +
  445 + " \"provisionDeviceSecret\":\"vaxb9hzqdbz3oqukvomg\"\n" +
  446 + " },\n" +
  447 + " \"transportConfiguration\":{\n" +
  448 + " \"type\":\"MQTT\",\n" +
  449 + " \"deviceTelemetryTopic\":\"v1/devices/me/telemetry\",\n" +
  450 + " \"deviceAttributesTopic\":\"v1/devices/me/attributes\",\n" +
  451 + " \"transportPayloadTypeConfiguration\":{\n" +
  452 + " \"transportPayloadType\":\"PROTOBUF\",\n" +
  453 + " \"deviceTelemetryProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage telemetry;\\n\\nmessage SensorDataReading {\\n\\n optional double temperature = 1;\\n optional double humidity = 2;\\n InnerObject innerObject = 3;\\n\\n message InnerObject {\\n optional string key1 = 1;\\n optional bool key2 = 2;\\n optional double key3 = 3;\\n optional int32 key4 = 4;\\n optional string key5 = 5;\\n }\\n}\",\n" +
  454 + " \"deviceAttributesProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage attributes;\\n\\nmessage SensorConfiguration {\\n optional string firmwareVersion = 1;\\n optional string serialNumber = 2;\\n}\",\n" +
  455 + " \"deviceRpcRequestProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage rpc;\\n\\nmessage RpcRequestMsg {\\n optional string method = 1;\\n optional int32 requestId = 2;\\n optional string params = 3;\\n}\",\n" +
  456 + " \"deviceRpcResponseProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage rpc;\\n\\nmessage RpcResponseMsg {\\n optional string payload = 1;\\n}\"\n" +
  457 + " }\n" +
  458 + " }\n" +
  459 + "}" + MARKDOWN_CODE_BLOCK_END;
  460 + private static final String DEVICE_PROFILE_DATA_DEFINITION = NEW_LINE + "# Device profile data definition" + NEW_LINE +
  461 + "Device profile data object contains alarm rules configuration, device provision strategy and transport type configuration for device connectivity. Let's review some examples. " +
  462 + "First one is the default device profile data configuration and second one - the custom one. " +
  463 + NEW_LINE + DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE + NEW_LINE + CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE +
  464 + NEW_LINE + "Let's review some specific objects examples related to the device profile configuration:";
  465 +
  466 + private static final String ALARM_SCHEDULE = NEW_LINE + "# Alarm Schedule" + NEW_LINE +
  467 + "Alarm Schedule JSON object represents the time interval during which the alarm rule is active. Note, " +
  468 + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE + NEW_LINE + "means alarm rule is active all the time. " +
  469 + "**'daysOfWeek'** field represents Monday as 1, Tuesday as 2 and so on. **'startsOn'** and **'endsOn'** fields represent hours in millis (e.g. 64800000 = 18:00 or 6pm). " +
  470 + "**'enabled'** flag specifies if item in a custom rule is active for specific day of the week:" + NEW_LINE +
  471 + "## Specific Time Schedule" + NEW_LINE +
  472 + DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE + NEW_LINE +
  473 + "## Custom Schedule" +
  474 + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE + NEW_LINE;
  475 +
  476 + private static final String ALARM_CONDITION_TYPE = "# Alarm condition type (**'spec'**)" + NEW_LINE +
  477 + "Alarm condition type can be either simple, duration, or repeating. For example, 5 times in a row or during 5 minutes." + NEW_LINE +
  478 + "Note, **'userValue'** field is not used and reserved for future usage, **'dynamicValue'** is used for condition appliance by using the value of the **'sourceAttribute'** " +
  479 + "or else **'defaultValue'** is used (if **'sourceAttribute'** is absent).\n" +
  480 + "\n**'sourceType'** of the **'sourceAttribute'** can be: \n" +
  481 + " * 'CURRENT_DEVICE';\n" +
  482 + " * 'CURRENT_CUSTOMER';\n" +
  483 + " * 'CURRENT_TENANT'." + NEW_LINE +
  484 + "**'sourceAttribute'** can be inherited from the owner if **'inherit'** is set to true (for CURRENT_DEVICE and CURRENT_CUSTOMER)." + NEW_LINE +
  485 + "## Repeating alarm condition" + NEW_LINE +
  486 + DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE + NEW_LINE +
  487 + "## Duration alarm condition" + NEW_LINE +
  488 + DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE + NEW_LINE +
  489 + "**'unit'** can be: \n" +
  490 + " * 'SECONDS';\n" +
  491 + " * 'MINUTES';\n" +
  492 + " * 'HOURS';\n" +
  493 + " * 'DAYS'." + NEW_LINE;
  494 +
  495 + private static final String PROVISION_CONFIGURATION = "# Provision Configuration" + NEW_LINE +
  496 + "There are 3 types of device provision configuration for the device profile: \n" +
  497 + " * 'DISABLED';\n" +
  498 + " * 'ALLOW_CREATE_NEW_DEVICES';\n" +
  499 + " * 'CHECK_PRE_PROVISIONED_DEVICES'." + NEW_LINE +
  500 + "Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-provisioning/) for more details." + NEW_LINE;
  501 +
  502 + private static final String DEVICE_PROFILE_DATA = DEVICE_PROFILE_DATA_DEFINITION + ALARM_SCHEDULE + ALARM_CONDITION_TYPE +
  503 + KEY_FILTERS_DESCRIPTION + PROVISION_CONFIGURATION + TRANSPORT_CONFIGURATION;
  504 +
58 private static final String DEVICE_PROFILE_ID = "deviceProfileId"; 505 private static final String DEVICE_PROFILE_ID = "deviceProfileId";
59 506
60 @Autowired 507 @Autowired
@@ -173,20 +620,9 @@ public class DeviceProfileController extends BaseController { @@ -173,20 +620,9 @@ public class DeviceProfileController extends BaseController {
173 notes = "Create or update the Device Profile. When creating device profile, platform generates device profile id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " + 620 notes = "Create or update the Device Profile. When creating device profile, platform generates device profile id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
174 "The newly created device profile id will be present in the response. " + 621 "The newly created device profile id will be present in the response. " +
175 "Specify existing device profile id to update the device profile. " + 622 "Specify existing device profile id to update the device profile. " +
176 - "Referencing non-existing device profile Id will cause 'Not Found' error. " +  
177 - "\n\nDevice profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + TENANT_AUTHORITY_PARAGRAPH +  
178 - NEW_LINE + "See the object example below for createRules field:" + NEW_LINE + DEVICE_PROFILE_ALARM_CREATE_RULES_EXAMPLE +  
179 - NEW_LINE + "See alarm schedule objects examples below. Note," + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE + NEW_LINE + " means alarm rule is active all the time. " +  
180 - "'daysOfWeek' field represents Monday as 1, Tuesday as 2 and so on. 'startsOn' and 'endsOn' represent hours in millis. " +  
181 - "'enabled' flag represents if custom rule is active for specific day of the week:" + NEW_LINE +  
182 - DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE + NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE + NEW_LINE +  
183 - "Alarm condition type ('spec') can be either simple, duration, or repeating. For example, 5 times in a row or during 5 minutes. See examples below. " + NEW_LINE +  
184 - DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE + NEW_LINE + DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE + NEW_LINE +  
185 - "Note, 'userValue' field is not used, 'dynamicValue' is used for condition appliance from the 'sourceAttribute' or else 'defaultValue' is used. " +  
186 - "'sourceType' of the 'sourceAttribute' can be CURRENT_DEVICE/CURRENT_CUSTOMER/CURRENT_TENANT or inherited from the owner if set to true (for device and customer)." +  
187 - NEW_LINE + "Condition array examples for alarm rule activation:" + NEW_LINE + DEVICE_PROFILE_CONDITIONS_TIME_SERIES_NUMERIC_EXAMPLE + NEW_LINE +  
188 - DEVICE_PROFILE_CONDITIONS_CONSTANT_EXAMPLE + NEW_LINE +  
189 - "Note, see description of predicate fields above for 'spec' object. Navigate to Docs or Alarm Rules on ThingsBoard UI for more details and examples of fields possible values. ", 623 + "Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE +
  624 + "Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA +
  625 + TENANT_AUTHORITY_PARAGRAPH,
190 produces = "application/json", 626 produces = "application/json",
191 consumes = "application/json") 627 consumes = "application/json")
192 @PreAuthorize("hasAuthority('TENANT_ADMIN')") 628 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@@ -45,7 +45,7 @@ import org.thingsboard.server.service.query.EntityQueryService; @@ -45,7 +45,7 @@ import org.thingsboard.server.service.query.EntityQueryService;
45 public class EntityQueryController extends BaseController { 45 public class EntityQueryController extends BaseController {
46 46
47 private static final String SINGLE_ENTITY = "\n\n## Single Entity\n\n" + 47 private static final String SINGLE_ENTITY = "\n\n## Single Entity\n\n" +
48 - "Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n"+ 48 + "Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n" +
49 MARKDOWN_CODE_BLOCK_START + 49 MARKDOWN_CODE_BLOCK_START +
50 "{\n" + 50 "{\n" +
51 " \"type\": \"singleEntity\",\n" + 51 " \"type\": \"singleEntity\",\n" +
@@ -53,12 +53,12 @@ public class EntityQueryController extends BaseController { @@ -53,12 +53,12 @@ public class EntityQueryController extends BaseController {
53 " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" + 53 " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
54 " \"entityType\": \"DEVICE\"\n" + 54 " \"entityType\": \"DEVICE\"\n" +
55 " }\n" + 55 " }\n" +
56 - "}"+ 56 + "}" +
57 MARKDOWN_CODE_BLOCK_END + 57 MARKDOWN_CODE_BLOCK_END +
58 ""; 58 "";
59 59
60 private static final String ENTITY_LIST = "\n\n## Entity List Filter\n\n" + 60 private static final String ENTITY_LIST = "\n\n## Entity List Filter\n\n" +
61 - "Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n"+ 61 + "Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n" +
62 MARKDOWN_CODE_BLOCK_START + 62 MARKDOWN_CODE_BLOCK_START +
63 "{\n" + 63 "{\n" +
64 " \"type\": \"entityList\",\n" + 64 " \"type\": \"entityList\",\n" +
@@ -67,84 +67,84 @@ public class EntityQueryController extends BaseController { @@ -67,84 +67,84 @@ public class EntityQueryController extends BaseController {
67 " \"e6501f30-2a7a-11ec-94eb-213c95f54092\",\n" + 67 " \"e6501f30-2a7a-11ec-94eb-213c95f54092\",\n" +
68 " \"e6657bf0-2a7a-11ec-94eb-213c95f54092\"\n" + 68 " \"e6657bf0-2a7a-11ec-94eb-213c95f54092\"\n" +
69 " ]\n" + 69 " ]\n" +
70 - "}"+ 70 + "}" +
71 MARKDOWN_CODE_BLOCK_END + 71 MARKDOWN_CODE_BLOCK_END +
72 ""; 72 "";
73 73
74 private static final String ENTITY_NAME = "\n\n## Entity Name Filter\n\n" + 74 private static final String ENTITY_NAME = "\n\n## Entity Name Filter\n\n" +
75 "Allows to filter entities of the same type using the **'starts with'** expression over entity name. " + 75 "Allows to filter entities of the same type using the **'starts with'** expression over entity name. " +
76 - "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+ 76 + "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
77 MARKDOWN_CODE_BLOCK_START + 77 MARKDOWN_CODE_BLOCK_START +
78 "{\n" + 78 "{\n" +
79 " \"type\": \"entityName\",\n" + 79 " \"type\": \"entityName\",\n" +
80 " \"entityType\": \"DEVICE\",\n" + 80 " \"entityType\": \"DEVICE\",\n" +
81 " \"entityNameFilter\": \"Air Quality\"\n" + 81 " \"entityNameFilter\": \"Air Quality\"\n" +
82 - "}"+ 82 + "}" +
83 MARKDOWN_CODE_BLOCK_END + 83 MARKDOWN_CODE_BLOCK_END +
84 ""; 84 "";
85 85
86 private static final String ENTITY_TYPE = "\n\n## Entity Type Filter\n\n" + 86 private static final String ENTITY_TYPE = "\n\n## Entity Type Filter\n\n" +
87 "Allows to filter entities based on their type (CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, etc)" + 87 "Allows to filter entities based on their type (CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, etc)" +
88 - "For example, this entity filter selects all tenant customers:\n\n"+ 88 + "For example, this entity filter selects all tenant customers:\n\n" +
89 MARKDOWN_CODE_BLOCK_START + 89 MARKDOWN_CODE_BLOCK_START +
90 "{\n" + 90 "{\n" +
91 " \"type\": \"entityType\",\n" + 91 " \"type\": \"entityType\",\n" +
92 " \"entityType\": \"CUSTOMER\"\n" + 92 " \"entityType\": \"CUSTOMER\"\n" +
93 - "}"+ 93 + "}" +
94 MARKDOWN_CODE_BLOCK_END + 94 MARKDOWN_CODE_BLOCK_END +
95 ""; 95 "";
96 96
97 private static final String ASSET_TYPE = "\n\n## Asset Type Filter\n\n" + 97 private static final String ASSET_TYPE = "\n\n## Asset Type Filter\n\n" +
98 "Allows to filter assets based on their type and the **'starts with'** expression over their name. " + 98 "Allows to filter assets based on their type and the **'starts with'** expression over their name. " +
99 - "For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n"+ 99 + "For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n" +
100 MARKDOWN_CODE_BLOCK_START + 100 MARKDOWN_CODE_BLOCK_START +
101 "{\n" + 101 "{\n" +
102 " \"type\": \"assetType\",\n" + 102 " \"type\": \"assetType\",\n" +
103 " \"assetType\": \"charging station\",\n" + 103 " \"assetType\": \"charging station\",\n" +
104 " \"assetNameFilter\": \"Tesla\"\n" + 104 " \"assetNameFilter\": \"Tesla\"\n" +
105 - "}"+ 105 + "}" +
106 MARKDOWN_CODE_BLOCK_END + 106 MARKDOWN_CODE_BLOCK_END +
107 ""; 107 "";
108 108
109 private static final String DEVICE_TYPE = "\n\n## Device Type Filter\n\n" + 109 private static final String DEVICE_TYPE = "\n\n## Device Type Filter\n\n" +
110 "Allows to filter devices based on their type and the **'starts with'** expression over their name. " + 110 "Allows to filter devices based on their type and the **'starts with'** expression over their name. " +
111 - "For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n"+ 111 + "For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n" +
112 MARKDOWN_CODE_BLOCK_START + 112 MARKDOWN_CODE_BLOCK_START +
113 "{\n" + 113 "{\n" +
114 " \"type\": \"deviceType\",\n" + 114 " \"type\": \"deviceType\",\n" +
115 " \"deviceType\": \"Temperature Sensor\",\n" + 115 " \"deviceType\": \"Temperature Sensor\",\n" +
116 " \"deviceNameFilter\": \"ABC\"\n" + 116 " \"deviceNameFilter\": \"ABC\"\n" +
117 - "}"+ 117 + "}" +
118 MARKDOWN_CODE_BLOCK_END + 118 MARKDOWN_CODE_BLOCK_END +
119 ""; 119 "";
120 120
121 private static final String EDGE_TYPE = "\n\n## Edge Type Filter\n\n" + 121 private static final String EDGE_TYPE = "\n\n## Edge Type Filter\n\n" +
122 "Allows to filter edge instances based on their type and the **'starts with'** expression over their name. " + 122 "Allows to filter edge instances based on their type and the **'starts with'** expression over their name. " +
123 - "For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n"+ 123 + "For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n" +
124 MARKDOWN_CODE_BLOCK_START + 124 MARKDOWN_CODE_BLOCK_START +
125 "{\n" + 125 "{\n" +
126 " \"type\": \"edgeType\",\n" + 126 " \"type\": \"edgeType\",\n" +
127 " \"edgeType\": \"Factory\",\n" + 127 " \"edgeType\": \"Factory\",\n" +
128 " \"edgeNameFilter\": \"Nevada\"\n" + 128 " \"edgeNameFilter\": \"Nevada\"\n" +
129 - "}"+ 129 + "}" +
130 MARKDOWN_CODE_BLOCK_END + 130 MARKDOWN_CODE_BLOCK_END +
131 ""; 131 "";
132 132
133 private static final String ENTITY_VIEW_TYPE = "\n\n## Entity View Filter\n\n" + 133 private static final String ENTITY_VIEW_TYPE = "\n\n## Entity View Filter\n\n" +
134 "Allows to filter entity views based on their type and the **'starts with'** expression over their name. " + 134 "Allows to filter entity views based on their type and the **'starts with'** expression over their name. " +
135 - "For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n"+ 135 + "For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n" +
136 MARKDOWN_CODE_BLOCK_START + 136 MARKDOWN_CODE_BLOCK_START +
137 "{\n" + 137 "{\n" +
138 " \"type\": \"entityViewType\",\n" + 138 " \"type\": \"entityViewType\",\n" +
139 " \"entityViewType\": \"Concrete Mixer\",\n" + 139 " \"entityViewType\": \"Concrete Mixer\",\n" +
140 " \"entityViewNameFilter\": \"CAT\"\n" + 140 " \"entityViewNameFilter\": \"CAT\"\n" +
141 - "}"+ 141 + "}" +
142 MARKDOWN_CODE_BLOCK_END + 142 MARKDOWN_CODE_BLOCK_END +
143 ""; 143 "";
144 144
145 private static final String API_USAGE = "\n\n## Api Usage Filter\n\n" + 145 private static final String API_USAGE = "\n\n## Api Usage Filter\n\n" +
146 "Allows to query for Api Usage based on optional customer id. If the customer id is not set, returns current tenant API usage." + 146 "Allows to query for Api Usage based on optional customer id. If the customer id is not set, returns current tenant API usage." +
147 - "For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n"+ 147 + "For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n" +
148 MARKDOWN_CODE_BLOCK_START + 148 MARKDOWN_CODE_BLOCK_START +
149 "{\n" + 149 "{\n" +
150 " \"type\": \"apiUsageState\",\n" + 150 " \"type\": \"apiUsageState\",\n" +
@@ -152,7 +152,7 @@ public class EntityQueryController extends BaseController { @@ -152,7 +152,7 @@ public class EntityQueryController extends BaseController {
152 " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" + 152 " \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
153 " \"entityType\": \"CUSTOMER\"\n" + 153 " \"entityType\": \"CUSTOMER\"\n" +
154 " }\n" + 154 " }\n" +
155 - "}"+ 155 + "}" +
156 MARKDOWN_CODE_BLOCK_END + 156 MARKDOWN_CODE_BLOCK_END +
157 ""; 157 "";
158 158
@@ -165,7 +165,7 @@ public class EntityQueryController extends BaseController { @@ -165,7 +165,7 @@ public class EntityQueryController extends BaseController {
165 FETCH_LAST_LEVEL_ONLY_DESCRIPTION + 165 FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
166 "The 'filter' object allows you to define the relation type and set of acceptable entity types to search for. " + 166 "The 'filter' object allows you to define the relation type and set of acceptable entity types to search for. " +
167 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only those who match the 'filters'.\n\n" + 167 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only those who match the 'filters'.\n\n" +
168 - "For example, this entity filter selects all devices and assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092':\n\n"+ 168 + "For example, this entity filter selects all devices and assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092':\n\n" +
169 MARKDOWN_CODE_BLOCK_START + 169 MARKDOWN_CODE_BLOCK_START +
170 "{\n" + 170 "{\n" +
171 " \"type\": \"relationsQuery\",\n" + 171 " \"type\": \"relationsQuery\",\n" +
@@ -185,7 +185,7 @@ public class EntityQueryController extends BaseController { @@ -185,7 +185,7 @@ public class EntityQueryController extends BaseController {
185 " ]\n" + 185 " ]\n" +
186 " }\n" + 186 " }\n" +
187 " ]\n" + 187 " ]\n" +
188 - "}"+ 188 + "}" +
189 MARKDOWN_CODE_BLOCK_END + 189 MARKDOWN_CODE_BLOCK_END +
190 ""; 190 "";
191 191
@@ -197,7 +197,7 @@ public class EntityQueryController extends BaseController { @@ -197,7 +197,7 @@ public class EntityQueryController extends BaseController {
197 "The 'relationType' defines the type of the relation to search for. " + 197 "The 'relationType' defines the type of the relation to search for. " +
198 "The 'assetTypes' defines the type of the asset to search for. " + 198 "The 'assetTypes' defines the type of the asset to search for. " +
199 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only assets that match 'relationType' and 'assetTypes' conditions.\n\n" + 199 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only assets that match 'relationType' and 'assetTypes' conditions.\n\n" +
200 - "For example, this entity filter selects 'charging station' assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+ 200 + "For example, this entity filter selects 'charging station' assets which are related to the asset with id 'e51de0c0-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
201 MARKDOWN_CODE_BLOCK_START + 201 MARKDOWN_CODE_BLOCK_START +
202 "{\n" + 202 "{\n" +
203 " \"type\": \"assetSearchQuery\",\n" + 203 " \"type\": \"assetSearchQuery\",\n" +
@@ -212,7 +212,7 @@ public class EntityQueryController extends BaseController { @@ -212,7 +212,7 @@ public class EntityQueryController extends BaseController {
212 " \"assetTypes\": [\n" + 212 " \"assetTypes\": [\n" +
213 " \"charging station\"\n" + 213 " \"charging station\"\n" +
214 " ]\n" + 214 " ]\n" +
215 - "}"+ 215 + "}" +
216 MARKDOWN_CODE_BLOCK_END + 216 MARKDOWN_CODE_BLOCK_END +
217 ""; 217 "";
218 218
@@ -223,7 +223,7 @@ public class EntityQueryController extends BaseController { @@ -223,7 +223,7 @@ public class EntityQueryController extends BaseController {
223 "The 'relationType' defines the type of the relation to search for. " + 223 "The 'relationType' defines the type of the relation to search for. " +
224 "The 'deviceTypes' defines the type of the device to search for. " + 224 "The 'deviceTypes' defines the type of the device to search for. " +
225 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" + 225 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
226 - "For example, this entity filter selects 'Charging port' and 'Air Quality Sensor' devices which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+ 226 + "For example, this entity filter selects 'Charging port' and 'Air Quality Sensor' devices which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
227 MARKDOWN_CODE_BLOCK_START + 227 MARKDOWN_CODE_BLOCK_START +
228 "{\n" + 228 "{\n" +
229 " \"type\": \"deviceSearchQuery\",\n" + 229 " \"type\": \"deviceSearchQuery\",\n" +
@@ -239,7 +239,7 @@ public class EntityQueryController extends BaseController { @@ -239,7 +239,7 @@ public class EntityQueryController extends BaseController {
239 " \"Air Quality Sensor\",\n" + 239 " \"Air Quality Sensor\",\n" +
240 " \"Charging port\"\n" + 240 " \"Charging port\"\n" +
241 " ]\n" + 241 " ]\n" +
242 - "}"+ 242 + "}" +
243 MARKDOWN_CODE_BLOCK_END + 243 MARKDOWN_CODE_BLOCK_END +
244 ""; 244 "";
245 245
@@ -250,7 +250,7 @@ public class EntityQueryController extends BaseController { @@ -250,7 +250,7 @@ public class EntityQueryController extends BaseController {
250 "The 'relationType' defines the type of the relation to search for. " + 250 "The 'relationType' defines the type of the relation to search for. " +
251 "The 'entityViewTypes' defines the type of the entity view to search for. " + 251 "The 'entityViewTypes' defines the type of the entity view to search for. " +
252 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" + 252 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
253 - "For example, this entity filter selects 'Concrete mixer' entity views which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+ 253 + "For example, this entity filter selects 'Concrete mixer' entity views which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
254 MARKDOWN_CODE_BLOCK_START + 254 MARKDOWN_CODE_BLOCK_START +
255 "{\n" + 255 "{\n" +
256 " \"type\": \"entityViewSearchQuery\",\n" + 256 " \"type\": \"entityViewSearchQuery\",\n" +
@@ -265,7 +265,7 @@ public class EntityQueryController extends BaseController { @@ -265,7 +265,7 @@ public class EntityQueryController extends BaseController {
265 " \"entityViewTypes\": [\n" + 265 " \"entityViewTypes\": [\n" +
266 " \"Concrete mixer\"\n" + 266 " \"Concrete mixer\"\n" +
267 " ]\n" + 267 " ]\n" +
268 - "}"+ 268 + "}" +
269 MARKDOWN_CODE_BLOCK_END + 269 MARKDOWN_CODE_BLOCK_END +
270 ""; 270 "";
271 271
@@ -276,7 +276,7 @@ public class EntityQueryController extends BaseController { @@ -276,7 +276,7 @@ public class EntityQueryController extends BaseController {
276 "The 'relationType' defines the type of the relation to search for. " + 276 "The 'relationType' defines the type of the relation to search for. " +
277 "The 'deviceTypes' defines the type of the device to search for. " + 277 "The 'deviceTypes' defines the type of the device to search for. " +
278 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" + 278 "The relation query calculates all related entities, even if they are filtered using different relation types, and then extracts only devices that match 'relationType' and 'deviceTypes' conditions.\n\n" +
279 - "For example, this entity filter selects 'Factory' edge instances which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n"+ 279 + "For example, this entity filter selects 'Factory' edge instances which are related to the asset with id 'e52b0020-2a7a-11ec-94eb-213c95f54092' using 'Contains' relation:\n\n" +
280 MARKDOWN_CODE_BLOCK_START + 280 MARKDOWN_CODE_BLOCK_START +
281 "{\n" + 281 "{\n" +
282 " \"type\": \"deviceSearchQuery\",\n" + 282 " \"type\": \"deviceSearchQuery\",\n" +
@@ -291,27 +291,27 @@ public class EntityQueryController extends BaseController { @@ -291,27 +291,27 @@ public class EntityQueryController extends BaseController {
291 " \"edgeTypes\": [\n" + 291 " \"edgeTypes\": [\n" +
292 " \"Factory\"\n" + 292 " \"Factory\"\n" +
293 " ]\n" + 293 " ]\n" +
294 - "}"+ 294 + "}" +
295 MARKDOWN_CODE_BLOCK_END + 295 MARKDOWN_CODE_BLOCK_END +
296 ""; 296 "";
297 297
298 private static final String EMPTY = "\n\n## Entity Type Filter\n\n" + 298 private static final String EMPTY = "\n\n## Entity Type Filter\n\n" +
299 "Allows to filter multiple entities of the same type using the **'starts with'** expression over entity name. " + 299 "Allows to filter multiple entities of the same type using the **'starts with'** expression over entity name. " +
300 - "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+ 300 + "For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
301 MARKDOWN_CODE_BLOCK_START + 301 MARKDOWN_CODE_BLOCK_START +
302 - ""+ 302 + "" +
303 MARKDOWN_CODE_BLOCK_END + 303 MARKDOWN_CODE_BLOCK_END +
304 ""; 304 "";
305 305
306 private static final String ENTITY_FILTERS = 306 private static final String ENTITY_FILTERS =
307 "\n\n # Entity Filters" + 307 "\n\n # Entity Filters" +
308 - "\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +  
309 - SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER  
310 - + ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER; 308 + "\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +
  309 + SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER
  310 + + ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER;
311 311
312 private static final String FILTER_KEY = "\n\n## Filter Key\n\n" + 312 private static final String FILTER_KEY = "\n\n## Filter Key\n\n" +
313 "Filter Key defines either entity field, attribute or telemetry. It is a JSON object that consists the key name and type. " + 313 "Filter Key defines either entity field, attribute or telemetry. It is a JSON object that consists the key name and type. " +
314 - "The following filter key types are supported: \n\n"+ 314 + "The following filter key types are supported: \n\n" +
315 " * 'CLIENT_ATTRIBUTE' - used for client attributes; \n" + 315 " * 'CLIENT_ATTRIBUTE' - used for client attributes; \n" +
316 " * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" + 316 " * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" +
317 " * 'SERVER_ATTRIBUTE' - used for server attributes; \n" + 317 " * 'SERVER_ATTRIBUTE' - used for server attributes; \n" +
@@ -328,19 +328,10 @@ public class EntityQueryController extends BaseController { @@ -328,19 +328,10 @@ public class EntityQueryController extends BaseController {
328 MARKDOWN_CODE_BLOCK_END + 328 MARKDOWN_CODE_BLOCK_END +
329 ""; 329 "";
330 330
331 - private static final String FILTER_VALUE_TYPE = "\n\n## Value Type and Operations\n\n" +  
332 - "Provides a hint about the data type of the entity field that is defined in the filter key. " +  
333 - "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." +  
334 - "The following filter value types and corresponding predicate operations are supported: \n\n"+  
335 - " * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +  
336 - " * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +  
337 - " * 'BOOLEAN' - used for boolean values; Operations: EQUAL, NOT_EQUAL \n" +  
338 - " * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";  
339 -  
340 private static final String FILTER_PREDICATE = "\n\n## Filter Predicate\n\n" + 331 private static final String FILTER_PREDICATE = "\n\n## Filter Predicate\n\n" +
341 "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " + 332 "Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
342 "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." + 333 "Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." +
343 - "\n\nSimple predicate example to check 'value < 100': \n\n"+ 334 + "\n\nSimple predicate example to check 'value < 100': \n\n" +
344 MARKDOWN_CODE_BLOCK_START + 335 MARKDOWN_CODE_BLOCK_START +
345 "{\n" + 336 "{\n" +
346 " \"operation\": \"LESS\",\n" + 337 " \"operation\": \"LESS\",\n" +
@@ -351,7 +342,7 @@ public class EntityQueryController extends BaseController { @@ -351,7 +342,7 @@ public class EntityQueryController extends BaseController {
351 " \"type\": \"NUMERIC\"\n" + 342 " \"type\": \"NUMERIC\"\n" +
352 "}" + 343 "}" +
353 MARKDOWN_CODE_BLOCK_END + 344 MARKDOWN_CODE_BLOCK_END +
354 - "\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n"+ 345 + "\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n" +
355 MARKDOWN_CODE_BLOCK_START + 346 MARKDOWN_CODE_BLOCK_START +
356 "{\n" + 347 "{\n" +
357 " \"type\": \"COMPLEX\",\n" + 348 " \"type\": \"COMPLEX\",\n" +
@@ -376,7 +367,7 @@ public class EntityQueryController extends BaseController { @@ -376,7 +367,7 @@ public class EntityQueryController extends BaseController {
376 " ]\n" + 367 " ]\n" +
377 "}" + 368 "}" +
378 MARKDOWN_CODE_BLOCK_END + 369 MARKDOWN_CODE_BLOCK_END +
379 - "\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n"+ 370 + "\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n" +
380 MARKDOWN_CODE_BLOCK_START + 371 MARKDOWN_CODE_BLOCK_START +
381 "{\n" + 372 "{\n" +
382 " \"type\": \"COMPLEX\",\n" + 373 " \"type\": \"COMPLEX\",\n" +
@@ -461,16 +452,16 @@ public class EntityQueryController extends BaseController { @@ -461,16 +452,16 @@ public class EntityQueryController extends BaseController {
461 452
462 private static final String ENTITY_COUNT_QUERY_DESCRIPTION = 453 private static final String ENTITY_COUNT_QUERY_DESCRIPTION =
463 "Allows to run complex queries to search the count of platform entities (devices, assets, customers, etc) " + 454 "Allows to run complex queries to search the count of platform entities (devices, assets, customers, etc) " +
464 - "based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +  
465 - "# Query Definition\n\n" +  
466 - "\n\nMain **entity filter** is mandatory and defines generic search criteria. " + 455 + "based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +
  456 + "# Query Definition\n\n" +
  457 + "\n\nMain **entity filter** is mandatory and defines generic search criteria. " +
467 "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" + 458 "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
468 - "\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +  
469 - "main entity fields (name, label, type, etc), attributes and telemetry. " +  
470 - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+  
471 - "\n\nLet's review the example:" +  
472 - "\n\n" + MARKDOWN_CODE_BLOCK_START +  
473 - "{\n" + 459 + "\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +
  460 + "main entity fields (name, label, type, etc), attributes and telemetry. " +
  461 + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
  462 + "\n\nLet's review the example:" +
  463 + "\n\n" + MARKDOWN_CODE_BLOCK_START +
  464 + "{\n" +
474 " \"entityFilter\": {\n" + 465 " \"entityFilter\": {\n" +
475 " \"type\": \"entityType\",\n" + 466 " \"type\": \"entityType\",\n" +
476 " \"entityType\": \"DEVICE\"\n" + 467 " \"entityType\": \"DEVICE\"\n" +
@@ -492,12 +483,12 @@ public class EntityQueryController extends BaseController { @@ -492,12 +483,12 @@ public class EntityQueryController extends BaseController {
492 " }\n" + 483 " }\n" +
493 " }\n" + 484 " }\n" +
494 " ]\n" + 485 " ]\n" +
495 - "}"+  
496 - MARKDOWN_CODE_BLOCK_END +  
497 - "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +  
498 - ENTITY_FILTERS +  
499 - KEY_FILTERS +  
500 - TENANT_AND_USER_AUTHORITY_PARAGRAPH;; 486 + "}" +
  487 + MARKDOWN_CODE_BLOCK_END +
  488 + "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
  489 + ENTITY_FILTERS +
  490 + KEY_FILTERS +
  491 + TENANT_AND_USER_AUTHORITY_PARAGRAPH;
501 492
502 private static final String ENTITY_DATA_QUERY_DESCRIPTION = 493 private static final String ENTITY_DATA_QUERY_DESCRIPTION =
503 "Allows to run complex queries over platform entities (devices, assets, customers, etc) " + 494 "Allows to run complex queries over platform entities (devices, assets, customers, etc) " +
@@ -508,7 +499,7 @@ public class EntityQueryController extends BaseController { @@ -508,7 +499,7 @@ public class EntityQueryController extends BaseController {
508 "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" + 499 "For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
509 "\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " + 500 "\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " +
510 "main entity fields (name, label, type, etc), attributes and telemetry. " + 501 "main entity fields (name, label, type, etc), attributes and telemetry. " +
511 - "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+ 502 + "For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
512 "\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." + 503 "\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." +
513 "\n\nThe **page link** contains information about the page to fetch and the sort ordering." + 504 "\n\nThe **page link** contains information about the page to fetch and the sort ordering." +
514 "\n\nLet's review the example:" + 505 "\n\nLet's review the example:" +
@@ -575,7 +566,7 @@ public class EntityQueryController extends BaseController { @@ -575,7 +566,7 @@ public class EntityQueryController extends BaseController {
575 " \"direction\": \"ASC\"\n" + 566 " \"direction\": \"ASC\"\n" +
576 " }\n" + 567 " }\n" +
577 " }\n" + 568 " }\n" +
578 - "}"+ 569 + "}" +
579 MARKDOWN_CODE_BLOCK_END + 570 MARKDOWN_CODE_BLOCK_END +
580 "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" + 571 "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
581 ENTITY_FILTERS + 572 ENTITY_FILTERS +
@@ -672,7 +663,7 @@ public class EntityQueryController extends BaseController { @@ -672,7 +663,7 @@ public class EntityQueryController extends BaseController {
672 " \"key\": \"temperature\"\n" + 663 " \"key\": \"temperature\"\n" +
673 " }\n" + 664 " }\n" +
674 " ]\n" + 665 " ]\n" +
675 - "}"+ 666 + "}" +
676 MARKDOWN_CODE_BLOCK_END + 667 MARKDOWN_CODE_BLOCK_END +
677 ""; 668 "";
678 669