Browse Source

Merge branch 'feature/swagger-device-profile-data' of https://github.com/dmytro-landiak/thingsboard into feature/swagger

pull/5425/head
Andrii Shvaika 5 years ago
parent
commit
45424dedeb
  1. 112
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 454
      application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java
  3. 119
      application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java
  4. 2
      application/src/main/java/org/thingsboard/server/controller/EventController.java
  5. 4
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java
  6. 3
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java
  7. 5
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java
  8. 7
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java
  9. 5
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java
  10. 7
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java
  11. 14
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java
  12. 2
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileConfiguration.java
  13. 9
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java
  14. 1
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileProvisionConfiguration.java

112
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -155,6 +155,8 @@ public abstract class BaseController {
/*Swagger UI description*/
protected static final String NEW_LINE = "\n\n";
public static final String CUSTOMER_ID = "customerId";
public static final String TENANT_ID = "tenantId";
public static final String DEVICE_ID = "deviceId";
@ -263,7 +265,7 @@ public abstract class BaseController {
protected static final String EVENT_END_TIME_DESCRIPTION = "Timestamp. Events with creation time after it won't be queried.";
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. ";
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)" ;
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)";
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. ";
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)";
@ -281,6 +283,114 @@ public abstract class BaseController {
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;
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;
protected static final String FILTER_VALUE_TYPE = NEW_LINE + "## Value Type and Operations" + NEW_LINE +
"Provides a hint about the data type of the entity field that is defined in the filter key. " +
"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." +
"The following filter value types and corresponding predicate operations are supported: " + NEW_LINE +
" * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +
" * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +
" * 'BOOLEAN' - used for boolean values. Operations: EQUAL, NOT_EQUAL;\n" +
" * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";
protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"schedule\":{\n" +
" \"type\":\"SPECIFIC_TIME\",\n" +
" \"endsOn\":64800000,\n" +
" \"startsOn\":43200000,\n" +
" \"timezone\":\"Europe/Kiev\",\n" +
" \"daysOfWeek\":[\n" +
" 1,\n" +
" 3,\n" +
" 5\n" +
" ]\n" +
" }\n" +
"}" +
MARKDOWN_CODE_BLOCK_END;
protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"schedule\":{\n" +
" \"type\":\"CUSTOM\",\n" +
" \"items\":[\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":1\n" +
" },\n" +
" {\n" +
" \"endsOn\":64800000,\n" +
" \"enabled\":true,\n" +
" \"startsOn\":43200000,\n" +
" \"dayOfWeek\":2\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":3\n" +
" },\n" +
" {\n" +
" \"endsOn\":57600000,\n" +
" \"enabled\":true,\n" +
" \"startsOn\":36000000,\n" +
" \"dayOfWeek\":4\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":5\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":6\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":7\n" +
" }\n" +
" ],\n" +
" \"timezone\":\"Europe/Kiev\"\n" +
" }\n" +
"}" +
MARKDOWN_CODE_BLOCK_END;
protected static final String DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "\"schedule\": null" + MARKDOWN_CODE_BLOCK_END;
protected static final String DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"spec\":{\n" +
" \"type\":\"REPEATING\",\n" +
" \"predicate\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":5,\n" +
" \"dynamicValue\":{\n" +
" \"inherit\":true,\n" +
" \"sourceType\":\"CURRENT_DEVICE\",\n" +
" \"sourceAttribute\":\"tempAttr\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}" +
MARKDOWN_CODE_BLOCK_END;
protected static final String DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"spec\":{\n" +
" \"type\":\"DURATION\",\n" +
" \"unit\":\"MINUTES\",\n" +
" \"predicate\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":30,\n" +
" \"dynamicValue\":null\n" +
" }\n" +
" }\n" +
"}" +
MARKDOWN_CODE_BLOCK_END;
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.";
protected static final String RELATION_TYPE_GROUP_PARAM_DESCRIPTION = "A string value representing relation type group. For example, 'COMMON'";

454
application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java

@ -55,6 +55,453 @@ import java.util.UUID;
@Slf4j
public class DeviceProfileController extends BaseController {
private static final String COAP_TRANSPORT_CONFIGURATION_EXAMPLE = MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\":\"COAP\",\n" +
" \"clientSettings\":{\n" +
" \"edrxCycle\":null,\n" +
" \"powerMode\":\"DRX\",\n" +
" \"psmActivityTimer\":null,\n" +
" \"pagingTransmissionWindow\":null\n" +
" },\n" +
" \"coapDeviceTypeConfiguration\":{\n" +
" \"coapDeviceType\":\"DEFAULT\",\n" +
" \"transportPayloadTypeConfiguration\":{\n" +
" \"transportPayloadType\":\"JSON\"\n" +
" }\n" +
" }\n" +
"}"
+ MARKDOWN_CODE_BLOCK_END;
private static final String TRANSPORT_CONFIGURATION = "# Transport Configuration" + NEW_LINE +
"5 transport configuration types are available:\n" +
" * 'DEFAULT';\n" +
" * 'MQTT';\n" +
" * 'LWM2M';\n" +
" * 'COAP';\n" +
" * 'SNMP'." + NEW_LINE + "Default type supports basic MQTT, HTTP, CoAP and LwM2M transports. " +
"Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-profiles/#transport-configuration) for more details about other types.\n" +
"\nSee another example of COAP transport configuration below:" + NEW_LINE + COAP_TRANSPORT_CONFIGURATION_EXAMPLE;
private static final String ALARM_FILTER_KEY = "## Alarm Filter Key" + NEW_LINE +
"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" +
" * 'ATTRIBUTE' - used for attributes values;\n" +
" * 'TIME_SERIES' - used for time-series values;\n" +
" * 'ENTITY_FIELD' - used for accessing entity fields like 'name', 'label', etc. The list of available fields depends on the entity type;\n" +
" * 'CONSTANT' - constant value specified." + NEW_LINE + "Let's review the example:" + NEW_LINE +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"TIME_SERIES\",\n" +
" \"key\": \"temperature\"\n" +
"}" +
MARKDOWN_CODE_BLOCK_END;
private static final String FILTER_PREDICATE = NEW_LINE + "## Filter Predicate" + NEW_LINE +
"Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
"Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." + NEW_LINE +
"Simple predicate example to check 'value < 100': " + NEW_LINE +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"operation\": \"LESS\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 100,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
"}" +
MARKDOWN_CODE_BLOCK_END + NEW_LINE +
"Complex predicate example, to check 'value < 10 or value > 20': " + NEW_LINE +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"COMPLEX\",\n" +
" \"operation\": \"OR\",\n" +
" \"predicates\": [\n" +
" {\n" +
" \"operation\": \"LESS\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 10,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
" },\n" +
" {\n" +
" \"operation\": \"GREATER\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 20,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
" }\n" +
" ]\n" +
"}" +
MARKDOWN_CODE_BLOCK_END + NEW_LINE +
"More complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': " + NEW_LINE +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"COMPLEX\",\n" +
" \"operation\": \"OR\",\n" +
" \"predicates\": [\n" +
" {\n" +
" \"operation\": \"LESS\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 10,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
" },\n" +
" {\n" +
" \"type\": \"COMPLEX\",\n" +
" \"operation\": \"AND\",\n" +
" \"predicates\": [\n" +
" {\n" +
" \"operation\": \"GREATER\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 50,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
" },\n" +
" {\n" +
" \"operation\": \"LESS\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 60,\n" +
" \"dynamicValue\": null\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}" +
MARKDOWN_CODE_BLOCK_END + NEW_LINE +
"You may also want to replace hardcoded values (for example, temperature > 20) with the more dynamic " +
"expression (for example, temperature > value of the tenant attribute with key 'temperatureThreshold'). " +
"It is possible to use 'dynamicValue' to define attribute of the tenant, customer or device. " +
"See example below:" + NEW_LINE +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"operation\": \"GREATER\",\n" +
" \"value\": {\n" +
" \"userValue\": null,\n" +
" \"defaultValue\": 0,\n" +
" \"dynamicValue\": {\n" +
" \"inherit\": false,\n" +
" \"sourceType\": \"CURRENT_TENANT\",\n" +
" \"sourceAttribute\": \"temperatureThreshold\"\n" +
" }\n" +
" },\n" +
" \"type\": \"NUMERIC\"\n" +
"}" +
MARKDOWN_CODE_BLOCK_END + NEW_LINE +
"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. " +
"The 'sourceAttribute' can be inherited from the owner of the specified 'sourceType' if 'inherit' is set to true.";
private static final String KEY_FILTERS_DESCRIPTION = "# Key Filters" + NEW_LINE +
"Key filter objects are created under the **'condition'** array. They allow you to define complex logical expressions over entity field, " +
"attribute, latest time-series value or constant. The filter is defined using 'key', 'valueType', " +
"'value' (refers to the value of the 'CONSTANT' alarm filter key type) and 'predicate' objects. Let's review each object:" + NEW_LINE +
ALARM_FILTER_KEY + FILTER_VALUE_TYPE + NEW_LINE + FILTER_PREDICATE + NEW_LINE;
private static final String DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
" \"alarms\":[\n" +
" ],\n" +
" \"configuration\":{\n" +
" \"type\":\"DEFAULT\"\n" +
" },\n" +
" \"provisionConfiguration\":{\n" +
" \"type\":\"DISABLED\",\n" +
" \"provisionDeviceSecret\":null\n" +
" },\n" +
" \"transportConfiguration\":{\n" +
" \"type\":\"DEFAULT\"\n" +
" }\n" +
"}" + MARKDOWN_CODE_BLOCK_END;
private static final String CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE = MARKDOWN_CODE_BLOCK_START + "{\n" +
" \"alarms\":[\n" +
" {\n" +
" \"id\":\"2492b935-1226-59e9-8615-17d8978a4f93\",\n" +
" \"alarmType\":\"Temperature Alarm\",\n" +
" \"clearRule\":{\n" +
" \"schedule\":null,\n" +
" \"condition\":{\n" +
" \"spec\":{\n" +
" \"type\":\"SIMPLE\"\n" +
" },\n" +
" \"condition\":[\n" +
" {\n" +
" \"key\":{\n" +
" \"key\":\"temperature\",\n" +
" \"type\":\"TIME_SERIES\"\n" +
" },\n" +
" \"value\":null,\n" +
" \"predicate\":{\n" +
" \"type\":\"NUMERIC\",\n" +
" \"value\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":30.0,\n" +
" \"dynamicValue\":null\n" +
" },\n" +
" \"operation\":\"LESS\"\n" +
" },\n" +
" \"valueType\":\"NUMERIC\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"dashboardId\":null,\n" +
" \"alarmDetails\":null\n" +
" },\n" +
" \"propagate\":false,\n" +
" \"createRules\":{\n" +
" \"MAJOR\":{\n" +
" \"schedule\":{\n" +
" \"type\":\"SPECIFIC_TIME\",\n" +
" \"endsOn\":64800000,\n" +
" \"startsOn\":43200000,\n" +
" \"timezone\":\"Europe/Kiev\",\n" +
" \"daysOfWeek\":[\n" +
" 1,\n" +
" 3,\n" +
" 5\n" +
" ]\n" +
" },\n" +
" \"condition\":{\n" +
" \"spec\":{\n" +
" \"type\":\"DURATION\",\n" +
" \"unit\":\"MINUTES\",\n" +
" \"predicate\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":30,\n" +
" \"dynamicValue\":null\n" +
" }\n" +
" },\n" +
" \"condition\":[\n" +
" {\n" +
" \"key\":{\n" +
" \"key\":\"temperature\",\n" +
" \"type\":\"TIME_SERIES\"\n" +
" },\n" +
" \"value\":null,\n" +
" \"predicate\":{\n" +
" \"type\":\"COMPLEX\",\n" +
" \"operation\":\"OR\",\n" +
" \"predicates\":[\n" +
" {\n" +
" \"type\":\"NUMERIC\",\n" +
" \"value\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":50.0,\n" +
" \"dynamicValue\":null\n" +
" },\n" +
" \"operation\":\"LESS_OR_EQUAL\"\n" +
" },\n" +
" {\n" +
" \"type\":\"NUMERIC\",\n" +
" \"value\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":30.0,\n" +
" \"dynamicValue\":null\n" +
" },\n" +
" \"operation\":\"GREATER\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"valueType\":\"NUMERIC\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"dashboardId\":null,\n" +
" \"alarmDetails\":null\n" +
" },\n" +
" \"WARNING\":{\n" +
" \"schedule\":{\n" +
" \"type\":\"CUSTOM\",\n" +
" \"items\":[\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":1\n" +
" },\n" +
" {\n" +
" \"endsOn\":64800000,\n" +
" \"enabled\":true,\n" +
" \"startsOn\":43200000,\n" +
" \"dayOfWeek\":2\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":3\n" +
" },\n" +
" {\n" +
" \"endsOn\":57600000,\n" +
" \"enabled\":true,\n" +
" \"startsOn\":36000000,\n" +
" \"dayOfWeek\":4\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":5\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":6\n" +
" },\n" +
" {\n" +
" \"endsOn\":0,\n" +
" \"enabled\":false,\n" +
" \"startsOn\":0,\n" +
" \"dayOfWeek\":7\n" +
" }\n" +
" ],\n" +
" \"timezone\":\"Europe/Kiev\"\n" +
" },\n" +
" \"condition\":{\n" +
" \"spec\":{\n" +
" \"type\":\"REPEATING\",\n" +
" \"predicate\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":5,\n" +
" \"dynamicValue\":null\n" +
" }\n" +
" },\n" +
" \"condition\":[\n" +
" {\n" +
" \"key\":{\n" +
" \"key\":\"tempConstant\",\n" +
" \"type\":\"CONSTANT\"\n" +
" },\n" +
" \"value\":30,\n" +
" \"predicate\":{\n" +
" \"type\":\"NUMERIC\",\n" +
" \"value\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":0.0,\n" +
" \"dynamicValue\":{\n" +
" \"inherit\":false,\n" +
" \"sourceType\":\"CURRENT_DEVICE\",\n" +
" \"sourceAttribute\":\"tempThreshold\"\n" +
" }\n" +
" },\n" +
" \"operation\":\"EQUAL\"\n" +
" },\n" +
" \"valueType\":\"NUMERIC\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"dashboardId\":null,\n" +
" \"alarmDetails\":null\n" +
" },\n" +
" \"CRITICAL\":{\n" +
" \"schedule\":null,\n" +
" \"condition\":{\n" +
" \"spec\":{\n" +
" \"type\":\"SIMPLE\"\n" +
" },\n" +
" \"condition\":[\n" +
" {\n" +
" \"key\":{\n" +
" \"key\":\"temperature\",\n" +
" \"type\":\"TIME_SERIES\"\n" +
" },\n" +
" \"value\":null,\n" +
" \"predicate\":{\n" +
" \"type\":\"NUMERIC\",\n" +
" \"value\":{\n" +
" \"userValue\":null,\n" +
" \"defaultValue\":50.0,\n" +
" \"dynamicValue\":null\n" +
" },\n" +
" \"operation\":\"GREATER\"\n" +
" },\n" +
" \"valueType\":\"NUMERIC\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"dashboardId\":null,\n" +
" \"alarmDetails\":null\n" +
" }\n" +
" },\n" +
" \"propagateRelationTypes\":null\n" +
" }\n" +
" ],\n" +
" \"configuration\":{\n" +
" \"type\":\"DEFAULT\"\n" +
" },\n" +
" \"provisionConfiguration\":{\n" +
" \"type\":\"ALLOW_CREATE_NEW_DEVICES\",\n" +
" \"provisionDeviceSecret\":\"vaxb9hzqdbz3oqukvomg\"\n" +
" },\n" +
" \"transportConfiguration\":{\n" +
" \"type\":\"MQTT\",\n" +
" \"deviceTelemetryTopic\":\"v1/devices/me/telemetry\",\n" +
" \"deviceAttributesTopic\":\"v1/devices/me/attributes\",\n" +
" \"transportPayloadTypeConfiguration\":{\n" +
" \"transportPayloadType\":\"PROTOBUF\",\n" +
" \"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" +
" \"deviceAttributesProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage attributes;\\n\\nmessage SensorConfiguration {\\n optional string firmwareVersion = 1;\\n optional string serialNumber = 2;\\n}\",\n" +
" \"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" +
" \"deviceRpcResponseProtoSchema\":\"syntax =\\\"proto3\\\";\\npackage rpc;\\n\\nmessage RpcResponseMsg {\\n optional string payload = 1;\\n}\"\n" +
" }\n" +
" }\n" +
"}" + MARKDOWN_CODE_BLOCK_END;
private static final String DEVICE_PROFILE_DATA_DEFINITION = NEW_LINE + "# Device profile data definition" + NEW_LINE +
"Device profile data object contains alarm rules configuration, device provision strategy and transport type configuration for device connectivity. Let's review some examples. " +
"First one is the default device profile data configuration and second one - the custom one. " +
NEW_LINE + DEFAULT_DEVICE_PROFILE_DATA_EXAMPLE + NEW_LINE + CUSTOM_DEVICE_PROFILE_DATA_EXAMPLE +
NEW_LINE + "Let's review some specific objects examples related to the device profile configuration:";
private static final String ALARM_SCHEDULE = NEW_LINE + "# Alarm Schedule" + NEW_LINE +
"Alarm Schedule JSON object represents the time interval during which the alarm rule is active. Note, " +
NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_ALWAYS_EXAMPLE + NEW_LINE + "means alarm rule is active all the time. " +
"**'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). " +
"**'enabled'** flag specifies if item in a custom rule is active for specific day of the week:" + NEW_LINE +
"## Specific Time Schedule" + NEW_LINE +
DEVICE_PROFILE_ALARM_SCHEDULE_SPECIFIC_TIME_EXAMPLE + NEW_LINE +
"## Custom Schedule" +
NEW_LINE + DEVICE_PROFILE_ALARM_SCHEDULE_CUSTOM_EXAMPLE + NEW_LINE;
private static final String ALARM_CONDITION_TYPE = "# Alarm condition type (**'spec'**)" + NEW_LINE +
"Alarm condition type can be either simple, duration, or repeating. For example, 5 times in a row or during 5 minutes." + NEW_LINE +
"Note, **'userValue'** field is not used and reserved for future usage, **'dynamicValue'** is used for condition appliance by using the value of the **'sourceAttribute'** " +
"or else **'defaultValue'** is used (if **'sourceAttribute'** is absent).\n" +
"\n**'sourceType'** of the **'sourceAttribute'** can be: \n" +
" * 'CURRENT_DEVICE';\n" +
" * 'CURRENT_CUSTOMER';\n" +
" * 'CURRENT_TENANT'." + NEW_LINE +
"**'sourceAttribute'** can be inherited from the owner if **'inherit'** is set to true (for CURRENT_DEVICE and CURRENT_CUSTOMER)." + NEW_LINE +
"## Repeating alarm condition" + NEW_LINE +
DEVICE_PROFILE_ALARM_CONDITION_REPEATING_EXAMPLE + NEW_LINE +
"## Duration alarm condition" + NEW_LINE +
DEVICE_PROFILE_ALARM_CONDITION_DURATION_EXAMPLE + NEW_LINE +
"**'unit'** can be: \n" +
" * 'SECONDS';\n" +
" * 'MINUTES';\n" +
" * 'HOURS';\n" +
" * 'DAYS'." + NEW_LINE;
private static final String PROVISION_CONFIGURATION = "# Provision Configuration" + NEW_LINE +
"There are 3 types of device provision configuration for the device profile: \n" +
" * 'DISABLED';\n" +
" * 'ALLOW_CREATE_NEW_DEVICES';\n" +
" * 'CHECK_PRE_PROVISIONED_DEVICES'." + NEW_LINE +
"Please refer to the [docs](https://thingsboard.io/docs/user-guide/device-provisioning/) for more details." + NEW_LINE;
private static final String DEVICE_PROFILE_DATA = DEVICE_PROFILE_DATA_DEFINITION + ALARM_SCHEDULE + ALARM_CONDITION_TYPE +
KEY_FILTERS_DESCRIPTION + PROVISION_CONFIGURATION + TRANSPORT_CONFIGURATION;
private static final String DEVICE_PROFILE_ID = "deviceProfileId";
@Autowired
@ -169,12 +616,13 @@ public class DeviceProfileController extends BaseController {
}
}
@ApiOperation(value = "Create Or Update Device Profile (saveDevice)",
@ApiOperation(value = "Create Or Update Device Profile (saveDeviceProfile)",
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). " +
"The newly created device profile id will be present in the response. " +
"Specify existing device profile id to update the device profile. " +
"Referencing non-existing device profile Id will cause 'Not Found' error. " +
"\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,
"Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE +
"Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA +
TENANT_AUTHORITY_PARAGRAPH,
produces = "application/json",
consumes = "application/json")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")

119
application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java

@ -45,7 +45,7 @@ import org.thingsboard.server.service.query.EntityQueryService;
public class EntityQueryController extends BaseController {
private static final String SINGLE_ENTITY = "\n\n## Single Entity\n\n" +
"Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n"+
"Allows to filter only one entity based on the id. For example, this entity filter selects certain device:\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"singleEntity\",\n" +
@ -53,12 +53,12 @@ public class EntityQueryController extends BaseController {
" \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
" \"entityType\": \"DEVICE\"\n" +
" }\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ENTITY_LIST = "\n\n## Entity List Filter\n\n" +
"Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n"+
"Allows to filter entities of the same type using their ids. For example, this entity filter selects two devices:\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"entityList\",\n" +
@ -67,84 +67,84 @@ public class EntityQueryController extends BaseController {
" \"e6501f30-2a7a-11ec-94eb-213c95f54092\",\n" +
" \"e6657bf0-2a7a-11ec-94eb-213c95f54092\"\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ENTITY_NAME = "\n\n## Entity Name Filter\n\n" +
"Allows to filter entities of the same type using the **'starts with'** expression over entity name. " +
"For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+
"For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"entityName\",\n" +
" \"entityType\": \"DEVICE\",\n" +
" \"entityNameFilter\": \"Air Quality\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ENTITY_TYPE = "\n\n## Entity Type Filter\n\n" +
"Allows to filter entities based on their type (CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, etc)" +
"For example, this entity filter selects all tenant customers:\n\n"+
"For example, this entity filter selects all tenant customers:\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"entityType\",\n" +
" \"entityType\": \"CUSTOMER\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ASSET_TYPE = "\n\n## Asset Type Filter\n\n" +
"Allows to filter assets based on their type and the **'starts with'** expression over their name. " +
"For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n"+
"For example, this entity filter selects all 'charging station' assets which name starts with 'Tesla':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"assetType\",\n" +
" \"assetType\": \"charging station\",\n" +
" \"assetNameFilter\": \"Tesla\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String DEVICE_TYPE = "\n\n## Device Type Filter\n\n" +
"Allows to filter devices based on their type and the **'starts with'** expression over their name. " +
"For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n"+
"For example, this entity filter selects all 'Temperature Sensor' devices which name starts with 'ABC':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"deviceType\",\n" +
" \"deviceType\": \"Temperature Sensor\",\n" +
" \"deviceNameFilter\": \"ABC\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String EDGE_TYPE = "\n\n## Edge Type Filter\n\n" +
"Allows to filter edge instances based on their type and the **'starts with'** expression over their name. " +
"For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n"+
"For example, this entity filter selects all 'Factory' edge instances which name starts with 'Nevada':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"edgeType\",\n" +
" \"edgeType\": \"Factory\",\n" +
" \"edgeNameFilter\": \"Nevada\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ENTITY_VIEW_TYPE = "\n\n## Entity View Filter\n\n" +
"Allows to filter entity views based on their type and the **'starts with'** expression over their name. " +
"For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n"+
"For example, this entity filter selects all 'Concrete Mixer' entity views which name starts with 'CAT':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"entityViewType\",\n" +
" \"entityViewType\": \"Concrete Mixer\",\n" +
" \"entityViewNameFilter\": \"CAT\"\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String API_USAGE = "\n\n## Api Usage Filter\n\n" +
"Allows to query for Api Usage based on optional customer id. If the customer id is not set, returns current tenant API usage." +
"For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n"+
"For example, this entity filter selects the 'Api Usage' entity for customer with id 'e6501f30-2a7a-11ec-94eb-213c95f54092':\n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"apiUsageState\",\n" +
@ -152,7 +152,7 @@ public class EntityQueryController extends BaseController {
" \"id\": \"d521edb0-2a7a-11ec-94eb-213c95f54092\",\n" +
" \"entityType\": \"CUSTOMER\"\n" +
" }\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
@ -165,7 +165,7 @@ public class EntityQueryController extends BaseController {
FETCH_LAST_LEVEL_ONLY_DESCRIPTION +
"The 'filter' object allows you to define the relation type and set of acceptable entity types to search for. " +
"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" +
"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"+
"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" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"relationsQuery\",\n" +
@ -185,7 +185,7 @@ public class EntityQueryController extends BaseController {
" ]\n" +
" }\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
@ -197,7 +197,7 @@ public class EntityQueryController extends BaseController {
"The 'relationType' defines the type of the relation to search for. " +
"The 'assetTypes' defines the type of the asset to search for. " +
"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" +
"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"+
"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" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"assetSearchQuery\",\n" +
@ -212,7 +212,7 @@ public class EntityQueryController extends BaseController {
" \"assetTypes\": [\n" +
" \"charging station\"\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
@ -223,7 +223,7 @@ public class EntityQueryController extends BaseController {
"The 'relationType' defines the type of the relation to search for. " +
"The 'deviceTypes' defines the type of the device to search for. " +
"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" +
"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"+
"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" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"deviceSearchQuery\",\n" +
@ -239,7 +239,7 @@ public class EntityQueryController extends BaseController {
" \"Air Quality Sensor\",\n" +
" \"Charging port\"\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
@ -250,7 +250,7 @@ public class EntityQueryController extends BaseController {
"The 'relationType' defines the type of the relation to search for. " +
"The 'entityViewTypes' defines the type of the entity view to search for. " +
"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" +
"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"+
"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" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"entityViewSearchQuery\",\n" +
@ -265,7 +265,7 @@ public class EntityQueryController extends BaseController {
" \"entityViewTypes\": [\n" +
" \"Concrete mixer\"\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
@ -276,7 +276,7 @@ public class EntityQueryController extends BaseController {
"The 'relationType' defines the type of the relation to search for. " +
"The 'deviceTypes' defines the type of the device to search for. " +
"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" +
"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"+
"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" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"deviceSearchQuery\",\n" +
@ -291,27 +291,27 @@ public class EntityQueryController extends BaseController {
" \"edgeTypes\": [\n" +
" \"Factory\"\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String EMPTY = "\n\n## Entity Type Filter\n\n" +
"Allows to filter multiple entities of the same type using the **'starts with'** expression over entity name. " +
"For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n"+
"For example, this entity filter selects all devices which name starts with 'Air Quality':\n\n" +
MARKDOWN_CODE_BLOCK_START +
""+
"" +
MARKDOWN_CODE_BLOCK_END +
"";
private static final String ENTITY_FILTERS =
"\n\n # Entity Filters" +
"\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +
SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER
+ ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER;
"\nEntity Filter body depends on the 'type' parameter. Let's review available entity filter types. In fact, they do correspond to available dashboard aliases." +
SINGLE_ENTITY + ENTITY_LIST + ENTITY_NAME + ENTITY_TYPE + ASSET_TYPE + DEVICE_TYPE + EDGE_TYPE + ENTITY_VIEW_TYPE + API_USAGE + RELATIONS_QUERY_FILTER
+ ASSET_QUERY_FILTER + DEVICE_QUERY_FILTER + EV_QUERY_FILTER + EDGE_QUERY_FILTER;
private static final String FILTER_KEY = "\n\n## Filter Key\n\n" +
"Filter Key defines either entity field, attribute or telemetry. It is a JSON object that consists the key name and type. " +
"The following filter key types are supported: \n\n"+
"The following filter key types are supported: \n\n" +
" * 'CLIENT_ATTRIBUTE' - used for client attributes; \n" +
" * 'SHARED_ATTRIBUTE' - used for shared attributes; \n" +
" * 'SERVER_ATTRIBUTE' - used for server attributes; \n" +
@ -328,19 +328,10 @@ public class EntityQueryController extends BaseController {
MARKDOWN_CODE_BLOCK_END +
"";
private static final String FILTER_VALUE_TYPE = "\n\n## Value Type and Operations\n\n" +
"Provides a hint about the data type of the entity field that is defined in the filter key. " +
"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." +
"The following filter value types and corresponding predicate operations are supported: \n\n"+
" * 'STRING' - used to filter any 'String' or 'JSON' values. Operations: EQUAL, NOT_EQUAL, STARTS_WITH, ENDS_WITH, CONTAINS, NOT_CONTAINS; \n" +
" * 'NUMERIC' - used for 'Long' and 'Double' values. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n" +
" * 'BOOLEAN' - used for boolean values; Operations: EQUAL, NOT_EQUAL \n" +
" * 'DATE_TIME' - similar to numeric, transforms value to milliseconds since epoch. Operations: EQUAL, NOT_EQUAL, GREATER, LESS, GREATER_OR_EQUAL, LESS_OR_EQUAL; \n";
private static final String FILTER_PREDICATE = "\n\n## Filter Predicate\n\n" +
"Filter Predicate defines the logical expression to evaluate. The list of available operations depends on the filter value type, see above. " +
"Platform supports 4 predicate types: 'STRING', 'NUMERIC', 'BOOLEAN' and 'COMPLEX'. The last one allows to combine multiple operations over one filter key." +
"\n\nSimple predicate example to check 'value < 100': \n\n"+
"\n\nSimple predicate example to check 'value < 100': \n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"operation\": \"LESS\",\n" +
@ -351,7 +342,7 @@ public class EntityQueryController extends BaseController {
" \"type\": \"NUMERIC\"\n" +
"}" +
MARKDOWN_CODE_BLOCK_END +
"\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n"+
"\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"COMPLEX\",\n" +
@ -376,7 +367,7 @@ public class EntityQueryController extends BaseController {
" ]\n" +
"}" +
MARKDOWN_CODE_BLOCK_END +
"\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n"+
"\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n" +
MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"type\": \"COMPLEX\",\n" +
@ -461,16 +452,16 @@ public class EntityQueryController extends BaseController {
private static final String ENTITY_COUNT_QUERY_DESCRIPTION =
"Allows to run complex queries to search the count of platform entities (devices, assets, customers, etc) " +
"based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +
"# Query Definition\n\n" +
"\n\nMain **entity filter** is mandatory and defines generic search criteria. " +
"based on the combination of main entity filter and multiple key filters. Returns the number of entities that match the query definition.\n\n" +
"# Query Definition\n\n" +
"\n\nMain **entity filter** is mandatory and defines generic search criteria. " +
"For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
"\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +
"main entity fields (name, label, type, etc), attributes and telemetry. " +
"For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+
"\n\nLet's review the example:" +
"\n\n" + MARKDOWN_CODE_BLOCK_START +
"{\n" +
"\n\nOptional **key filters** allow to filter results of the entity filter by complex criteria against " +
"main entity fields (name, label, type, etc), attributes and telemetry. " +
"For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
"\n\nLet's review the example:" +
"\n\n" + MARKDOWN_CODE_BLOCK_START +
"{\n" +
" \"entityFilter\": {\n" +
" \"type\": \"entityType\",\n" +
" \"entityType\": \"DEVICE\"\n" +
@ -492,12 +483,12 @@ public class EntityQueryController extends BaseController {
" }\n" +
" }\n" +
" ]\n" +
"}"+
MARKDOWN_CODE_BLOCK_END +
"\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:" +
ENTITY_FILTERS +
KEY_FILTERS +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;;
"}" +
MARKDOWN_CODE_BLOCK_END +
"\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:" +
ENTITY_FILTERS +
KEY_FILTERS +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
private static final String ENTITY_DATA_QUERY_DESCRIPTION =
"Allows to run complex queries over platform entities (devices, assets, customers, etc) " +
@ -508,7 +499,7 @@ public class EntityQueryController extends BaseController {
"For example, \"find all devices with profile 'Moisture Sensor'\" or \"Find all devices related to asset 'Building A'\"" +
"\n\nOptional **key filters** allow to filter results of the **entity filter** by complex criteria against " +
"main entity fields (name, label, type, etc), attributes and telemetry. " +
"For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"."+
"For example, \"temperature > 20 or temperature< 10\" or \"name starts with 'T', and attribute 'model' is 'T1000', and timeseries field 'batteryLevel' > 40\"." +
"\n\nThe **entity fields** and **latest values** contains list of entity fields and latest attribute/telemetry fields to fetch for each entity." +
"\n\nThe **page link** contains information about the page to fetch and the sort ordering." +
"\n\nLet's review the example:" +
@ -575,7 +566,7 @@ public class EntityQueryController extends BaseController {
" \"direction\": \"ASC\"\n" +
" }\n" +
" }\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"\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:" +
ENTITY_FILTERS +
@ -672,7 +663,7 @@ public class EntityQueryController extends BaseController {
" \"key\": \"temperature\"\n" +
" }\n" +
" ]\n" +
"}"+
"}" +
MARKDOWN_CODE_BLOCK_END +
"";

2
application/src/main/java/org/thingsboard/server/controller/EventController.java

@ -45,8 +45,6 @@ import org.thingsboard.server.service.security.permission.Operation;
@RequestMapping("/api")
public class EventController extends BaseController {
private static final String NEW_LINE = "\n\n";
@Autowired
private EventService eventService;

4
common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java

@ -69,8 +69,8 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha
@ApiModelProperty(position = 15, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true")
private boolean propagate;
@ApiModelProperty(position = 16, value = "JSON array of relation types that should be used for propagation. " +
"By default, 'propagateRelationTypes' array is empty which means that the alarm will propagate based on any relation type to parent entities. " +
"This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will ignoned.")
"By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " +
"This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.")
private List<String> propagateRelationTypes;
public Alarm() {

3
common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java

@ -16,13 +16,16 @@
package org.thingsboard.server.common.data.device.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class DeviceData {
@ApiModelProperty(position = 1, value = "Device configuration for device profile type. DEFAULT is only supported value for now")
private DeviceConfiguration configuration;
@ApiModelProperty(position = 2, value = "Device transport configuration used to connect the device")
private DeviceTransportConfiguration transportConfiguration;
}

5
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java

@ -16,18 +16,23 @@
package org.thingsboard.server.common.data.device.profile;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import javax.validation.Valid;
import java.util.List;
@ApiModel
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmCondition implements Serializable {
@Valid
@ApiModelProperty(position = 1, value = "JSON array of alarm condition filters")
private List<AlarmConditionFilter> condition;
@ApiModelProperty(position = 2, value = "JSON object representing alarm condition type")
private AlarmConditionSpec spec;
}

7
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.common.data.device.profile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.query.EntityKeyValueType;
import org.thingsboard.server.common.data.query.KeyFilterPredicate;
@ -24,15 +26,20 @@ import javax.validation.Valid;
import java.io.Serializable;
@ApiModel
@Data
public class AlarmConditionFilter implements Serializable {
@Valid
@ApiModelProperty(position = 1, value = "JSON object for specifying alarm condition by specific key")
private AlarmConditionFilterKey key;
@ApiModelProperty(position = 2, value = "String representation of the type of the value", example = "NUMERIC")
private EntityKeyValueType valueType;
@NoXss
@ApiModelProperty(position = 3, value = "Value used in Constant comparison. For other types, such as TIME_SERIES or ATTRIBUTE, the predicate condition is used")
private Object value;
@Valid
@ApiModelProperty(position = 4, value = "JSON object representing filter condition")
private KeyFilterPredicate predicate;
}

5
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java

@ -15,16 +15,21 @@
*/
package org.thingsboard.server.common.data.device.profile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.validation.NoXss;
import java.io.Serializable;
@ApiModel
@Data
public class AlarmConditionFilterKey implements Serializable {
@ApiModelProperty(position = 1, value = "The key type", example = "TIME_SERIES")
private final AlarmConditionKeyType type;
@NoXss
@ApiModelProperty(position = 2, value = "String value representing the key", example = "temp")
private final String key;
}

7
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.common.data.device.profile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.validation.NoXss;
@ -23,15 +25,20 @@ import javax.validation.Valid;
import java.io.Serializable;
@ApiModel
@Data
public class AlarmRule implements Serializable {
@Valid
@ApiModelProperty(position = 1, value = "JSON object representing the alarm rule condition")
private AlarmCondition condition;
@ApiModelProperty(position = 2, value = "JSON object representing time interval during which the rule is active")
private AlarmSchedule schedule;
// Advanced
@NoXss
@ApiModelProperty(position = 3, value = "String value representing the additional details for an alarm rule")
private String alarmDetails;
@ApiModelProperty(position = 4, value = "JSON object with the dashboard Id representing the reference to alarm details dashboard used by mobile application")
private DashboardId dashboardId;
}

14
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java

@ -15,28 +15,40 @@
*/
package org.thingsboard.server.common.data.device.profile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.validation.NoXss;
import java.io.Serializable;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.List;
import java.util.TreeMap;
@ApiModel
@Data
public class DeviceProfileAlarm implements Serializable {
@ApiModelProperty(position = 1, value = "String value representing the alarm rule id", example = "highTemperatureAlarmID")
private String id;
@NoXss
@ApiModelProperty(position = 2, value = "String value representing type of the alarm", example = "High Temperature Alarm")
private String alarmType;
@Valid
@ApiModelProperty(position = 3, value = "Complex JSON object representing create alarm rules. The unique create alarm rule can be created for each alarm severity type. " +
"There can be 5 create alarm rules configured per a single alarm type. See method implementation notes and AlarmRule model for more details")
private TreeMap<AlarmSeverity, AlarmRule> createRules;
@Valid
@ApiModelProperty(position = 4, value = "JSON object representing clear alarm rule")
private AlarmRule clearRule;
// Hidden in advanced settings
@ApiModelProperty(position = 5, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true")
private boolean propagate;
@ApiModelProperty(position = 6, value = "JSON array of relation types that should be used for propagation. " +
"By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " +
"This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.")
private List<String> propagateRelationTypes;
}

2
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileConfiguration.java

@ -29,7 +29,7 @@ import java.io.Serializable;
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultDeviceProfileConfiguration.class, name = "DEFAULT")})
@JsonSubTypes.Type(value = DefaultDeviceProfileConfiguration.class, name = "DEFAULT")})
public interface DeviceProfileConfiguration extends Serializable {
@JsonIgnore

9
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java

@ -15,20 +15,27 @@
*/
package org.thingsboard.server.common.data.device.profile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.List;
@ApiModel
@Data
public class DeviceProfileData implements Serializable {
@ApiModelProperty(position = 1, value = "JSON object of device profile configuration")
private DeviceProfileConfiguration configuration;
@Valid
@ApiModelProperty(position = 2, value = "JSON object of device profile transport configuration")
private DeviceProfileTransportConfiguration transportConfiguration;
@ApiModelProperty(position = 3, value = "JSON object of provisioning strategy type per device profile")
private DeviceProfileProvisionConfiguration provisionConfiguration;
@Valid
@ApiModelProperty(position = 4, value = "JSON array of alarm rules configuration per device profile")
private List<DeviceProfileAlarm> alarms;
}

1
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileProvisionConfiguration.java

@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import java.io.Serializable;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,

Loading…
Cancel
Save