privatestaticfinalStringALARM_SECURITY_CHECK="If the user has the authority of 'Tenant Administrator', the server checks that the originator of alarm is owned by the same tenant. "+
"If the user has the authority of 'Customer User', the server checks that the originator of alarm belongs to the customer. ";
privatestaticfinalStringALARM_QUERY_SEARCH_STATUS_DESCRIPTION="A string value representing one of the AlarmSearchStatus enumeration value";
privatestaticfinalStringALARM_QUERY_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on of next alarm fields: type, severity or status";
privatestaticfinalStringALARM_QUERY_START_TIME_DESCRIPTION="The start timestamp in milliseconds of the search time range over the Alarm class field: 'createdTime'.";
privatestaticfinalStringALARM_QUERY_END_TIME_DESCRIPTION="The end timestamp in milliseconds of the search time range over the Alarm class field: 'createdTime'.";
privatestaticfinalStringALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION="A boolean value to specify if the alarm originator name will be "+
"filled in the AlarmInfo object field: 'originatorName' or will returns as null.";
@ApiOperation(value="Create or update Alarm (saveAlarm)",
notes="Creates or Updates the Alarm. "+
"When creating alarm, platform generates Alarm Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"The newly created Alarm id will be present in the response. Specify existing Alarm id to update the alarm. "+
"Referencing non-existing Alarm Id will cause 'Not Found' error. "+
"\n\nPlatform also deduplicate the alarms based on the entity id of originator and alarm 'type'. "+
"For example, if the user or system component create the alarm with the type 'HighTemperature' for device 'Device A' the new active alarm is created. "+
"If the user tries to create 'HighTemperature' alarm for the same device again, the previous alarm will be updated (the 'end_ts' will be set to current timestamp). "+
"If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. "
@ -169,21 +210,36 @@ public class AlarmController extends BaseController {
}
}
@ApiOperation(value="Get Alarms (getAlarms)",
notes="Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. "+
notes="Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). "+
"Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error."
@ -518,8 +518,11 @@ public class AssetController extends BaseController {
@ApiOperation(value="Assign asset to edge (assignAssetToEdge)",
notes="Creates assignment of an existing asset to an instance of The Edge. "+
"The Edge is a software product for edge computing. "+
"It allows bringing data analysis and management to the edge, while seamlessly synchronizing with the platform server (cloud). ",produces=MediaType.APPLICATION_JSON_VALUE)
EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION+
"Second, remote edge service will receive a copy of assignment asset "+
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION+". "+
"Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.",
privatestaticfinalStringAUDIT_LOG_QUERY_START_TIME_DESCRIPTION="The start timestamp in milliseconds of the search time range over the AuditLog class field: 'createdTime'.";
privatestaticfinalStringAUDIT_LOG_QUERY_END_TIME_DESCRIPTION="The end timestamp in milliseconds of the search time range over the AuditLog class field: 'createdTime'.";
privatestaticfinalStringAUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION="A String value representing comma-separated list of action types. "+
"This parameter is optional, but it can be used to filter results to fetch only audit logs of specific action types. "+
"For example, 'LOGIN', 'LOGOUT'. See the 'Model' tab of the Response Class for more details.";
privatestaticfinalStringAUDIT_LOG_SORT_PROPERTY_DESCRIPTION="Property of audit log to sort by. "+
"See the 'Model' tab of the Response Class for more details. "+
"Note: entityType sort property is not defined in the AuditLog class, however, it can be used to sort audit logs by types of entities that were logged.";
@ApiOperation(value="Get audit logs by customer id (getAuditLogsByCustomerId)",
notes="Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), "+
"and users actions (login, logout, etc.) that belong to this customer. "+
@ -157,41 +157,112 @@ public abstract class BaseController {
publicstaticfinalStringCUSTOMER_ID="customerId";
publicstaticfinalStringTENANT_ID="tenantId";
publicstaticfinalStringDEVICE_ID="deviceId";
publicstaticfinalStringRPC_ID="rpcId";
publicstaticfinalStringENTITY_ID="entityId";
publicstaticfinalStringENTITY_TYPE="entityType";
publicstaticfinalStringPAGE_DATA_PARAMETERS="You can specify parameters to filter the results. "+
"The result is wrapped with PageData object that allows you to iterate over result set using pagination. "+
"See the 'Model' tab of the Response Class for more details. ";
publicstaticfinalStringDASHBOARD_ID_PARAM_DESCRIPTION="A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringRPC_ID_PARAM_DESCRIPTION="A string value representing the rpc id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringDEVICE_ID_PARAM_DESCRIPTION="A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringDEVICE_PROFILE_ID_DESCRIPTION="A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringDEVICE_PROFILE_ID_PARAM_DESCRIPTION="A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringTENANT_PROFILE_ID_PARAM_DESCRIPTION="A string value representing the tenant profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringTENANT_ID_PARAM_DESCRIPTION="A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringEDGE_ID_PARAM_DESCRIPTION="A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringCUSTOMER_ID_PARAM_DESCRIPTION="A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringUSER_ID_PARAM_DESCRIPTION="A string value representing the user id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringASSET_ID_PARAM_DESCRIPTION="A string value representing the asset id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
protectedfinalStringPAGE_SIZE_DESCRIPTION="Maximum amount of entities in a one page";
protectedfinalStringPAGE_NUMBER_DESCRIPTION="Sequence number of page starting from 0";
protectedfinalStringDEVICE_TYPE_DESCRIPTION="Device type as the name of the device profile";
protectedfinalStringDEVICE_INFO_DESCRIPTION="Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. ";
protectedfinalStringASSET_INFO_DESCRIPTION="Asset Info is an extension of the default Asset object that contains information about the assigned customer name. ";
protectedfinalStringDEVICE_NAME_DESCRIPTION="A string value representing the Device name.";
protectedfinalStringASSET_NAME_DESCRIPTION="A string value representing the Asset name.";
publicstaticfinalStringALARM_ID_PARAM_DESCRIPTION="A string value representing the alarm id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringENTITY_ID_PARAM_DESCRIPTION="A string value representing the entity id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
publicstaticfinalStringENTITY_TYPE_PARAM_DESCRIPTION="A string value representing the entity type. For example, 'DEVICE'";
publicstaticfinalStringRULE_CHAIN_ID_PARAM_DESCRIPTION="A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
protectedstaticfinalStringSYSTEM_AUTHORITY_PARAGRAPH="\n\nAvailable for users with 'SYS_ADMIN' authority.";
protectedstaticfinalStringSYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH="\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";
protectedstaticfinalStringTENANT_AUTHORITY_PARAGRAPH="\n\nAvailable for users with 'TENANT_ADMIN' authority.";
protectedstaticfinalStringTENANT_OR_USER_AUTHORITY_PARAGRAPH="\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";
protectedstaticfinalStringPAGE_SIZE_DESCRIPTION="Maximum amount of entities in a one page";
protectedstaticfinalStringPAGE_NUMBER_DESCRIPTION="Sequence number of page starting from 0";
protectedstaticfinalStringDEVICE_TYPE_DESCRIPTION="Device type as the name of the device profile";
protectedstaticfinalStringDEVICE_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the device name.";
protectedstaticfinalStringUSER_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the user email.";
protectedstaticfinalStringTENANT_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the tenant name.";
protectedstaticfinalStringTENANT_PROFILE_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the tenant profile name.";
protectedstaticfinalStringRULE_CHAIN_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the rule chain name.";
protectedstaticfinalStringDEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the device profile name.";
protectedstaticfinalStringCUSTOMER_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the customer title.";
protectedstaticfinalStringEDGE_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on the edge name.";
protectedstaticfinalStringEVENT_TEXT_SEARCH_DESCRIPTION="The value is not used in searching.";
protectedstaticfinalStringAUDIT_LOG_TEXT_SEARCH_DESCRIPTION="The case insensitive 'startsWith' filter based on one of the next properties: entityType, entityName, userName, actionType, actionStatus.";
protectedstaticfinalStringSORT_PROPERTY_DESCRIPTION="Property of entity to sort by";
protectedstaticfinalStringDEVICE_INFO_DESCRIPTION="Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. ";
protectedstaticfinalStringASSET_INFO_DESCRIPTION="Asset Info is an extension of the default Asset object that contains information about the assigned customer name. ";
protectedstaticfinalStringALARM_INFO_DESCRIPTION="Alarm Info is an extension of the default Alarm object that also contains name of the alarm originator.";
protectedstaticfinalStringRELATION_INFO_DESCRIPTION="Relation Info is an extension of the default Relation object that contains information about the 'from' and 'to' entity names. ";
protectedstaticfinalStringEDGE_INFO_DESCRIPTION="Edge Info is an extension of the default Edge object that contains information about the assigned customer name. ";
protectedstaticfinalStringDEVICE_PROFILE_INFO_DESCRIPTION="Device Profile Info is a lightweight object that includes main information about Device Profile excluding the heavyweight configuration object. ";
protectedstaticfinalStringDEVICE_NAME_DESCRIPTION="A string value representing the Device name.";
protectedstaticfinalStringASSET_NAME_DESCRIPTION="A string value representing the Asset name.";
protectedstaticfinalStringEVENT_START_TIME_DESCRIPTION="Timestamp. Events with creation time before it won't be queried.";
protectedstaticfinalStringEVENT_END_TIME_DESCRIPTION="Timestamp. Events with creation time after it won't be queried.";
protectedstaticfinalStringEDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION="Unassignment works in async way - first, 'unassign' notification event pushed to edge queue on platform. ";
protectedstaticfinalStringEDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION="(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
protectedstaticfinalStringEDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION="Assignment works in async way - first, notification event pushed to edge service queue on platform. ";
protectedstaticfinalStringEDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION="(Edge will receive this instantly, if it's currently connected, or once it's going to be connected to platform)";
protectedstaticfinalStringRELATION_TYPE_PARAM_DESCRIPTION="A string value representing relation type between entities. For example, 'Contains', 'Manages'. It can be any string value.";
protectedstaticfinalStringRELATION_TYPE_GROUP_PARAM_DESCRIPTION="A string value representing relation type group. For example, 'COMMON'";
protectedstaticfinalStringADMINISTRATOR_AUTHORITY_ONLY="Available for users with 'Tenant Administrator' authority only.";
@ -141,7 +142,8 @@ public class DeviceController extends BaseController {
"Device credentials are also generated if not provided in the 'accessToken' request parameter. "+
"The newly created device id will be present in the response. "+
"Specify existing Device id to update the device. "+
"Referencing non-existing device Id will cause 'Not Found' error.")
"Referencing non-existing device Id will cause 'Not Found' error."+
"\n\nDevice name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the device names and non-unique 'label' field for user-friendly visualization purposes.")
notes="Get a set of unique time-series keys used by devices that belong to specified profile. "+
"If profile is not set returns a list of unique keys among all profiles. "+
"The call is used for auto-complete in the UI forms. "+
"The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. "+
notes="Get a set of unique attribute keys used by devices that belong to specified profile. "+
"If profile is not set returns a list of unique keys among all profiles. "+
"The call is used for auto-complete in the UI forms. "+
"The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. "+
@ -135,10 +169,20 @@ public class DeviceProfileController extends BaseController {
}
}
@ApiOperation(value="Create Or Update Device Profile (saveDevice)",
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,
publicstaticfinalStringEDGE_SECURITY_CHECK="If the user has the authority of 'Tenant Administrator', the server checks that the edge is owned by the same tenant. "+
"If the user has the authority of 'Customer User', the server checks that the edge is assigned to the same customer.";
@ApiOperation(value="Is edges support enabled (isEdgesSupportEnabled)",
notes="Returns 'true' if edges support enabled on server, 'false' - otherwise.")
@ -117,10 +132,18 @@ public class EdgeController extends BaseController {
}
}
@ApiOperation(value="Create Or Update Edge (saveEdge)",
notes="Create or update the Edge. When creating edge, platform generates Edge Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"The newly created edge id will be present in the response. "+
"Specify existing Edge id to update the edge. "+
"Referencing non-existing Edge Id will cause 'Not Found' error."+
"\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes.",
notes="Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request.",
notes="Returns list of rule chains ids that are not assigned to particular edge, but these rule chains are present in the already assigned rule chains to edge.")
privatestaticfinalStringMAX_LEVEL_DESCRIPTION="Possible direction values are 'TO' and 'FROM'. The 'maxLevel' defines how many relation levels should the query search 'recursively'. ";
privatestaticfinalStringFETCH_LAST_LEVEL_ONLY_DESCRIPTION="Assuming the 'maxLevel' is > 1, the 'fetchLastLevelOnly' defines either to return all related entities or only entities that are on the last level of relations. ";
"Allows to filter entities that are related to the provided root entity. "+
MAX_LEVEL_DESCRIPTION+
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"+
"Allows to filter assets that are related to the provided root entity. Filters related assets based on the relation type and set of asset types. "+
MAX_LEVEL_DESCRIPTION+
FETCH_LAST_LEVEL_ONLY_DESCRIPTION+
"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"+
"Allows to filter devices that are related to the provided root entity. Filters related devices based on the relation type and set of device types. "+
MAX_LEVEL_DESCRIPTION+
FETCH_LAST_LEVEL_ONLY_DESCRIPTION+
"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"+
"Allows to filter entity views that are related to the provided root entity. Filters related entity views based on the relation type and set of entity view types. "+
MAX_LEVEL_DESCRIPTION+
FETCH_LAST_LEVEL_ONLY_DESCRIPTION+
"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"+
"Allows to filter edge instances that are related to the provided root entity. Filters related edge instances based on the relation type and set of edge types. "+
MAX_LEVEL_DESCRIPTION+
FETCH_LAST_LEVEL_ONLY_DESCRIPTION+
"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"+
privatestaticfinalStringEMPTY="\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"+
MARKDOWN_CODE_BLOCK_START+
""+
MARKDOWN_CODE_BLOCK_END+
"";
privatestaticfinalStringENTITY_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."+
"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"+
" * 'CLIENT_ATTRIBUTE' - used for client attributes; \n"+
" * 'SHARED_ATTRIBUTE' - used for shared attributes; \n"+
" * 'SERVER_ATTRIBUTE' - used for server attributes; \n"+
" * 'ATTRIBUTE' - used for any of the above; \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"+
" * 'ALARM_FIELD' - similar to entity field, but is used in alarm queries only; \n"+
"\n\n Let's review the example:\n\n"+
MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"type\": \"TIME_SERIES\",\n"+
" \"key\": \"temperature\"\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"";
privatestaticfinalStringFILTER_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";
"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"+
MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"operation\": \"LESS\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 100,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"\n\nComplex predicate example, to check 'value < 10 or value > 20': \n\n"+
MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"type\": \"COMPLEX\",\n"+
" \"operation\": \"OR\",\n"+
" \"predicates\": [\n"+
" {\n"+
" \"operation\": \"LESS\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 10,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" },\n"+
" {\n"+
" \"operation\": \"GREATER\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 20,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" }\n"+
" ]\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"\n\nMore complex predicate example, to check 'value < 10 or (value > 50 && value < 60)': \n\n"+
MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"type\": \"COMPLEX\",\n"+
" \"operation\": \"OR\",\n"+
" \"predicates\": [\n"+
" {\n"+
" \"operation\": \"LESS\",\n"+
" \"value\": {\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"+
" \"defaultValue\": 50,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" },\n"+
" {\n"+
" \"operation\": \"LESS\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 60,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" }\n"+
" ]\n"+
" }\n"+
" ]\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"\n\n 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 user that is performing the API call. "+
"\n\n Note that you may use 'CURRENT_USER', '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.";
privatestaticfinalStringKEY_FILTERS=
"\n\n # Key Filters"+
"\nKey Filter allows you to define complex logical expressions over entity field, attribute or latest time-series value. The filter is defined using 'key', 'valueType' and 'predicate' objects. "+
"Single Entity Query may have zero, one or multiple predicates. If multiple filters are defined, they are evaluated using logical 'AND'. "+
"The example below checks that temperature of the entity is above 20 degrees:"+
"\n\n"+MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"key\": {\n"+
" \"type\": \"TIME_SERIES\",\n"+
" \"key\": \"temperature\"\n"+
" },\n"+
" \"valueType\": \"NUMERIC\",\n"+
" \"predicate\": {\n"+
" \"operation\": \"GREATER\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 20,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" }\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"\n\n Now let's review 'key', 'valueType' and 'predicate' objects in detail."
"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"+
" },\n"+
" \"keyFilters\": [\n"+
" {\n"+
" \"key\": {\n"+
" \"type\": \"ATTRIBUTE\",\n"+
" \"key\": \"active\"\n"+
" },\n"+
" \"valueType\": \"BOOLEAN\",\n"+
" \"predicate\": {\n"+
" \"operation\": \"EQUAL\",\n"+
" \"value\": {\n"+
" \"defaultValue\": true,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"BOOLEAN\"\n"+
" }\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:"+
"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\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_USER_AUTHORITY_PARAGRAPH;
privatestaticfinalStringALARM_DATA_QUERY_DESCRIPTION="This method description defines how Alarm Data Query extends the Entity Data Query. "+
"See method 'Find Entity Data by Query' first to get the info about 'Entity Data Query'."+
"\n\n The platform will first search the entities that match the entity and key filters. Then, the platform will use 'Alarm Page Link' to filter the alarms related to those entities. "+
"Finally, platform fetch the properties of alarm that are defined in the **'alarmFields'** and combine them with the other entity, attribute and latest time-series fields to return the result. "+
"\n\n See example of the alarm query below. The query will search first 100 active alarms with type 'Temperature Alarm' or 'Fire Alarm' for any device with current temperature > 0. "+
"The query will return combination of the entity fields: name of the device, device model and latest temperature reading and alarms fields: createdTime, type, severity and status: "+
"\n\n"+MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"entityFilter\": {\n"+
" \"type\": \"entityType\",\n"+
" \"resolveMultiple\": true,\n"+
" \"entityType\": \"DEVICE\"\n"+
" },\n"+
" \"pageLink\": {\n"+
" \"page\": 0,\n"+
" \"pageSize\": 100,\n"+
" \"textSearch\": null,\n"+
" \"searchPropagatedAlarms\": false,\n"+
" \"statusList\": [\n"+
" \"ACTIVE\"\n"+
" ],\n"+
" \"severityList\": [\n"+
" \"CRITICAL\",\n"+
" \"MAJOR\"\n"+
" ],\n"+
" \"typeList\": [\n"+
" \"Temperature Alarm\",\n"+
" \"Fire Alarm\"\n"+
" ],\n"+
" \"sortOrder\": {\n"+
" \"key\": {\n"+
" \"key\": \"createdTime\",\n"+
" \"type\": \"ALARM_FIELD\"\n"+
" },\n"+
" \"direction\": \"DESC\"\n"+
" },\n"+
" \"timeWindow\": 86400000\n"+
" },\n"+
" \"keyFilters\": [\n"+
" {\n"+
" \"key\": {\n"+
" \"type\": \"TIME_SERIES\",\n"+
" \"key\": \"temperature\"\n"+
" },\n"+
" \"valueType\": \"NUMERIC\",\n"+
" \"predicate\": {\n"+
" \"operation\": \"GREATER\",\n"+
" \"value\": {\n"+
" \"defaultValue\": 0,\n"+
" \"dynamicValue\": null\n"+
" },\n"+
" \"type\": \"NUMERIC\"\n"+
" }\n"+
" }\n"+
" ],\n"+
" \"alarmFields\": [\n"+
" {\n"+
" \"type\": \"ALARM_FIELD\",\n"+
" \"key\": \"createdTime\"\n"+
" },\n"+
" {\n"+
" \"type\": \"ALARM_FIELD\",\n"+
" \"key\": \"type\"\n"+
" },\n"+
" {\n"+
" \"type\": \"ALARM_FIELD\",\n"+
" \"key\": \"severity\"\n"+
" },\n"+
" {\n"+
" \"type\": \"ALARM_FIELD\",\n"+
" \"key\": \"status\"\n"+
" }\n"+
" ],\n"+
" \"entityFields\": [\n"+
" {\n"+
" \"type\": \"ENTITY_FIELD\",\n"+
" \"key\": \"name\"\n"+
" }\n"+
" ],\n"+
" \"latestValues\": [\n"+
" {\n"+
" \"type\": \"ATTRIBUTE\",\n"+
" \"key\": \"model\"\n"+
" },\n"+
" {\n"+
" \"type\": \"TIME_SERIES\",\n"+
" \"key\": \"temperature\"\n"+
" }\n"+
" ]\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"";
@Autowired
privateEntityQueryServiceentityQueryService;
privatestaticfinalintMAX_PAGE_SIZE=100;
@ApiOperation(value="Count Entities by Query",notes=ENTITY_COUNT_QUERY_DESCRIPTION)
@ -83,12 +726,18 @@ public class EntityQueryController extends BaseController {
}
}
@ApiOperation(value="Find Entity Keys by Query",
notes="Uses entity data query (see 'Find Entity Data by Query') to find first 100 entities. Then fetch and return all unique time-series and/or attribute keys. Used mostly for UI hints.")
privatestaticfinalStringSECURITY_CHECKS_ENTITIES_DESCRIPTION="\n\nIf the user has the authority of 'System Administrator', the server checks that 'from' and 'to' entities are owned by the sysadmin. "+
"If the user has the authority of 'Tenant Administrator', the server checks that 'from' and 'to' entities are owned by the same tenant. "+
"If the user has the authority of 'Customer User', the server checks that the 'from' and 'to' entities are assigned to the same customer.";
privatestaticfinalStringSECURITY_CHECKS_ENTITY_DESCRIPTION="\n\nIf the user has the authority of 'System Administrator', the server checks that the entity is owned by the sysadmin. "+
"If the user has the authority of 'Tenant Administrator', the server checks that the entity is owned by the same tenant. "+
"If the user has the authority of 'Customer User', the server checks that the entity is assigned to the same customer.";
privatestaticfinalStringOAUTH2_CLIENT_REGISTRATION_TEMPLATE_DEFINITION="Client registration template is OAuth2 provider configuration template with default settings for registering new OAuth2 clients";
@ApiOperation(value="Create or update OAuth2 client registration template (saveClientRegistrationTemplate)",
publicvoiddeleteClientRegistrationTemplate(@ApiParam(value="String representation of client registration template id to delete",example="139b1f81-2f5d-11ec-9dbe-9b627e1a88f4")
privatestaticfinalStringRPC_REQUEST_DESCRIPTION="Sends the one-way remote-procedure call (RPC) request to device. "+
"The RPC call is A JSON that contains the method name ('method'), parameters ('params') and multiple optional fields. "+
"See example below. We will review the properties of the RPC call one-by-one below. "+
"\n\n"+MARKDOWN_CODE_BLOCK_START+
"{\n"+
" \"method\": \"setGpio\",\n"+
" \"params\": {\n"+
" \"pin\": 7,\n"+
" \"value\": 1\n"+
" },\n"+
" \"persistent\": false,\n"+
" \"timeout\": 5000\n"+
"}"+
MARKDOWN_CODE_BLOCK_END+
"\n\n### Server-side RPC structure\n"+
"\n"+
"The body of server-side RPC request consists of multiple fields:\n"+
"\n"+
"* **method** - mandatory, name of the method to distinct the RPC calls.\n"+
" For example, \"getCurrentTime\" or \"getWeatherForecast\". The value of the parameter is a string.\n"+
"* **params** - mandatory, parameters used for processing of the request. The value is a JSON. Leave empty JSON \"{}\" if no parameters needed.\n"+
"* **timeout** - optional, value of the processing timeout in milliseconds. The default value is 10000 (10 seconds). The minimum value is 5000 (5 seconds).\n"+
"* **expirationTime** - optional, value of the epoch time (in milliseconds, UTC timezone). Overrides **timeout** if present.\n"+
"* **persistent** - optional, indicates persistent RPC. The default value is \"false\".\n"+
"* **retries** - optional, defines how many times persistent RPC will be re-sent in case of failures on the network and/or device side.\n"+
"* **additionalInfo** - optional, defines metadata for the persistent RPC that will be added to the persistent RPC events.";
"In case of persistent RPC, the result of this call is 'rpcId' UUID. In case of lightweight RPC, "+
"the result of this call is the response from device, or 504 Gateway Timeout if device is offline.";
privatestaticfinalStringONE_WAY_RPC_REQUEST_DESCRIPTION="Sends the one-way remote-procedure call (RPC) request to device. "+RPC_REQUEST_DESCRIPTION+ONE_WAY_RPC_RESULT+TENANT_OR_USER_AUTHORITY_PARAGRAPH;
privatestaticfinalStringTWO_WAY_RPC_REQUEST_DESCRIPTION="Sends the two-way remote-procedure call (RPC) request to device. "+RPC_REQUEST_DESCRIPTION+TWO_WAY_RPC_RESULT+TENANT_OR_USER_AUTHORITY_PARAGRAPH;
@ -79,16 +147,25 @@ public class RpcV2Controller extends AbstractRpcController {
}
}
@ApiOperation(value="Get persistent RPC requests",notes="Allows to query RPC calls for specific device using pagination."+TENANT_OR_USER_AUTHORITY_PARAGRAPH)
@ -134,11 +164,18 @@ public class RuleChainController extends BaseController {
}
}
@ApiOperation(value="Create Or Update Rule Chain (saveRuleChain)",
notes="Create or update the Rule Chain. When creating Rule Chain, platform generates Rule Chain Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"The newly created Rule Chain Id will be present in the response. "+
"Specify existing Rule Chain id to update the rule chain. "+
"Referencing non-existing rule chain Id will cause 'Not Found' error."+
notes="Deletes the rule chain. Referencing non-existing rule chain Id will cause an error. Referencing rule chain that is used in the device profiles will cause an error.")
privatestaticfinalStringATTRIBUTES_SCOPE_DESCRIPTION="A string value representing the attributes scope. For example, 'SERVER_SCOPE'.";
privatestaticfinalStringATTRIBUTES_KEYS_DESCRIPTION="A string value representing the comma-separated list of attributes keys. For example, 'active,inactivityAlarmTime'.";
privatestaticfinalStringATTRIBUTES_JSON_REQUEST_DESCRIPTION="A string value representing the json object. For example, '{\"key\":\"value\"}'";
privatestaticfinalStringATTRIBUTE_DATA_CLASS_DESCRIPTION="AttributeData class represents information regarding a particular attribute and includes the next parameters: 'lastUpdatesTs' - a long value representing the timestamp of the last attribute modification in milliseconds. 'key' - attribute key name, and 'value' - attribute value.";
privatestaticfinalStringGET_ALL_ATTRIBUTES_BASE_DESCRIPTION="Returns a JSON structure that represents a list of AttributeData class objects for the selected entity based on the specified comma-separated list of attribute key names. "+ATTRIBUTE_DATA_CLASS_DESCRIPTION;
privatestaticfinalStringGET_ALL_ATTRIBUTES_BY_SCOPE_BASE_DESCRIPTION="Returns a JSON structure that represents a list of AttributeData class objects for the selected entity based on the attributes scope selected and a comma-separated list of attribute key names. "+ATTRIBUTE_DATA_CLASS_DESCRIPTION;
privatestaticfinalStringTS_DATA_CLASS_DESCRIPTION="TsData class is a timeseries data point for specific telemetry key that includes 'value' - object value, and 'ts' - a long value representing timestamp in milliseconds for this value. ";
privatestaticfinalStringTELEMETRY_KEYS_BASE_DESCRIPTION="A string value representing the comma-separated list of telemetry keys.";
privatestaticfinalStringTELEMETRY_KEYS_DESCRIPTION=TELEMETRY_KEYS_BASE_DESCRIPTION+" If keys are not selected, the result will return all latest timeseries. For example, 'temp,humidity'.";
privatestaticfinalStringTELEMETRY_SCOPE_DESCRIPTION="Value is not used in the API call implementation. However, you need to specify whatever value cause scope is a path variable.";
privatestaticfinalStringTELEMETRY_JSON_REQUEST_DESCRIPTION="A string value representing the json object. For example, '{\"key\":\"value\"}' or '{\"ts\":1527863043000,\"values\":{\"key1\":\"value1\",\"key2\":\"value2\"}}' or [{\"ts\":1527863043000,\"values\":{\"key1\":\"value1\",\"key2\":\"value2\"}}, {\"ts\":1527863053000,\"values\":{\"key1\":\"value3\",\"key2\":\"value4\"}}]";
privatestaticfinalStringSTRICT_DATA_TYPES_DESCRIPTION="A boolean value to specify if values of selected telemetry keys will represent string values(by default) or use strict data type.";
privatestaticfinalStringINVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION="Referencing a non-existing entity Id or invalid entity type will cause an error. ";
privatestaticfinalStringSAVE_ENTITY_ATTRIBUTES_DESCRIPTION="Creates or updates the entity attributes based on entity id, entity type, specified attributes scope "+
"and request payload that represents a JSON object with key-value format of attributes to create or update. "+
"For example, '{\"temperature\": 26}'. Key is a unique parameter and cannot be overwritten. Only value can be overwritten for the key. ";
privatestaticfinalStringSAVE_ATTIRIBUTES_STATUS_OK="Attribute from the request was created or updated. ";
privatestaticfinalStringINVALID_STRUCTURE_OF_THE_REQUEST="Invalid structure of the request";
privatestaticfinalStringSAVE_ATTIRIBUTES_STATUS_BAD_REQUEST=INVALID_STRUCTURE_OF_THE_REQUEST+" or invalid attributes scope provided.";
privatestaticfinalStringSAVE_ENTITY_ATTRIBUTES_STATUS_OK="Platform creates an audit log event about entity attributes updates with action type 'ATTRIBUTES_UPDATED', "+
"and also sends event msg to the rule engine with msg type 'ATTRIBUTES_UPDATED'.";
privatestaticfinalStringSAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED="User is not authorized to save entity attributes for selected entity. Most likely, User belongs to different Customer or Tenant.";
privatestaticfinalStringSAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR="The exception was thrown during processing the request. "+
"Platform creates an audit log event about entity attributes updates with action type 'ATTRIBUTES_UPDATED' that includes an error stacktrace.";
privatestaticfinalStringSAVE_ENTITY_TIMESERIES_DESCRIPTION="Creates or updates the entity timeseries based on entity id, entity type "+
"and request payload that represents a JSON object with key-value or ts-values format. "+
"For example, '{\"temperature\": 26}' or '{\"ts\":1634712287000,\"values\":{\"temperature\":26, \"humidity\":87}}', "+
"or JSON array with inner objects inside of ts-values format. "+
"For example, '[{\"ts\":1634712287000,\"values\":{\"temperature\":26, \"humidity\":87}}, {\"ts\":1634712588000,\"values\":{\"temperature\":25, \"humidity\":88}}]'. "+
"The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. ";
privatestaticfinalStringSAVE_ENTITY_TIMESERIES_STATUS_OK="Timeseries from the request was created or updated. "+
"Platform creates an audit log event about entity timeseries updates with action type 'TIMESERIES_UPDATED'.";
privatestaticfinalStringSAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED="User is not authorized to save entity timeseries for selected entity. Most likely, User belongs to different Customer or Tenant.";
privatestaticfinalStringSAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR="The exception was thrown during processing the request. "+
"Platform creates an audit log event about entity timeseries updates with action type 'TIMESERIES_UPDATED' that includes an error stacktrace.";
@Autowired
privateTimeseriesServicetsService;
@ -133,83 +179,132 @@ public class TelemetryController extends BaseController {
}
}
@ApiOperation(value="Get all attribute keys (getAttributeKeys)",
notes="Returns a list of all attribute key names for the selected entity. "+
"In the case of device entity specified, a response will include merged attribute key names list from each scope: "+
notes=GET_ALL_ATTRIBUTES_BASE_DESCRIPTION+" If 'keys' parameter is omitted, AttributeData class objects will be added to the response for all existing keys of the selected entity. "+
notes="Returns a JSON structure that represents a Map, where the map key is a telemetry key name "+
"and map value - is a list of TsData class objects. "+TS_DATA_CLASS_DESCRIPTION+
"This method allows us to group original data into intervals and aggregate it using one of the aggregation methods or just limit the number of TsData objects to fetch for each key specified. "+
"See the desription of the request parameters for more details. "+
"The result can also be sorted in ascending or descending order. "+INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION,
@ApiResponse(code=401,message="User is not authorized to save device attributes for selected device. Most likely, User belongs to different Customer or Tenant."),
@ApiResponse(code=500,message="The exception was thrown during processing the request. "+
"Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED' that includes an error stacktrace."),
@ApiOperation(value="Save or update telemetry with TTL (saveEntityTelemetryWithTTL)",
notes=SAVE_ENTITY_TIMESERIES_DESCRIPTION+"The ttl parameter used only in case of Cassandra DB use for timeseries data storage. "+INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION,
notes="Delete timeseries for selected entity based on entity id, entity type, keys "+
"and removal time range. To delete all data for keys parameter 'deleteAllDataForKeys' should be set to true, "+
"otherwise, will be deleted data that is in range of the selected time interval. ",
produces=MediaType.APPLICATION_JSON_VALUE)
@ApiResponses(value={
@ApiResponse(code=200,message="Timeseries for the selected keys in the request was removed. "+
"Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED'."),
@ApiResponse(code=400,message="Platform returns a bad request in case if keys list is empty or start and end timestamp values is empty when deleteAllDataForKeys is set to false."),
@ApiResponse(code=401,message="User is not authorized to delete entity timeseries for selected entity. Most likely, User belongs to different Customer or Tenant."),
@ApiResponse(code=500,message="The exception was thrown during processing the request. "+
"Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED' that includes an error stacktrace."),
@ApiParam(value="If the parameter is set to true, the latest telemetry will be rewritten in case that current latest value was removed, otherwise, in case that parameter is set to false the new latest value will not set.")
notes="Delete device attributes from the specified attributes scope based on device id and a list of keys to delete. "+
"Selected keys will be deleted only if there are exist in the specified attribute scope. Referencing a non-existing device Id will cause an error",
produces=MediaType.APPLICATION_JSON_VALUE)
@ApiResponses(value={
@ApiResponse(code=200,message="Device attributes was removed for the selected keys in the request. "+
"Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED'."),
@ApiResponse(code=400,message="Platform returns a bad request in case if keys or scope are not specified."),
@ApiResponse(code=401,message="User is not authorized to delete device attributes for selected entity. Most likely, User belongs to different Customer or Tenant."),
@ApiResponse(code=500,message="The exception was thrown during processing the request. "+
"Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED' that includes an error stacktrace."),
notes="Delete entity attributes from the specified attributes scope based on entity id, entity type and a list of keys to delete. "+
"Selected keys will be deleted only if there are exist in the specified attribute scope."+INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION,
produces=MediaType.APPLICATION_JSON_VALUE)
@ApiResponses(value={
@ApiResponse(code=200,message="Entity attributes was removed for the selected keys in the request. "+
"Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED'."),
@ApiResponse(code=400,message="Platform returns a bad request in case if keys or scope are not specified."),
@ApiResponse(code=401,message="User is not authorized to delete entity attributes for selected entity. Most likely, User belongs to different Customer or Tenant."),
@ApiResponse(code=500,message="The exception was thrown during processing the request. "+
"Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED' that includes an error stacktrace."),
@ -83,10 +95,19 @@ public class TenantController extends BaseController {
}
}
@ApiOperation(value="Create Or update Tenant (saveTenant)",
notes="Create or update the Tenant. When creating tenant, platform generates Tenant Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"Default Rule Chain and Device profile are also generated for the new tenants automatically. "+
"The newly created Tenant Id will be present in the response. "+
"Specify existing Tenant Id id to update the Tenant. "+
"Referencing non-existing Tenant Id will cause 'Not Found' error."+
notes="Deletes the tenant, it's customers, rule chains, devices and all other related entities. Referencing non-existing tenant Id will cause an error."+SYSTEM_AUTHORITY_PARAGRAPH)
@ -124,14 +149,21 @@ public class TenantController extends BaseController {
}
}
@ApiOperation(value="Get Tenants (getTenants)",notes="Returns a page of tenants registered in the platform. "+PAGE_DATA_PARAMETERS+SYSTEM_AUTHORITY_PARAGRAPH)
@ -81,10 +95,65 @@ public class TenantProfileController extends BaseController {
}
}
@ApiOperation(value="Create Or update Tenant Profile (saveTenantProfile)",
notes="Create or update the Tenant Profile. When creating tenant profile, platform generates Tenant Profile Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"The newly created Tenant Profile Id will be present in the response. "+
"Specify existing Tenant Profile Id id to update the Tenant Profile. "+
"Referencing non-existing Tenant Profile Id will cause 'Not Found' error. "+
"\n\nUpdate of the tenant profile configuration will cause immediate recalculation of API limits for all affected Tenants. "+
"\n\nThe **'profileData'** object is the part of Tenant Profile that defines API limits and Rate limits. "+
"\n\nYou have an ability to define maximum number of devices ('maxDevice'), assets ('maxAssets') and other entities. "+
"You may also define maximum number of messages to be processed per month ('maxTransportMessages', 'maxREExecutions', etc). "+
"The '*RateLimit' defines the rate limits using simple syntax. For example, '1000:1,20000:60' means up to 1000 events per second but no more than 20000 event per minute. "+
"Let's review the example of tenant profile data below: "+
notes="Deletes the tenant profile. Referencing non-existing tenant profile Id will cause an error. Referencing profile that is used by the tenants will cause an error. "+SYSTEM_AUTHORITY_PARAGRAPH)
@ -135,14 +212,21 @@ public class TenantProfileController extends BaseController {
}
}
@ApiOperation(value="Get Tenant Profiles (getTenantProfiles)",notes="Returns a page of tenant profiles registered in the platform. "+PAGE_DATA_PARAMETERS+SYSTEM_AUTHORITY_PARAGRAPH)
@ -151,14 +235,22 @@ public class TenantProfileController extends BaseController {
}
}
@ApiOperation(value="Get Tenant Profiles Info (getTenantProfileInfos)",notes="Returns a page of tenant profile info objects registered in the platform. "
@ -112,10 +123,16 @@ public class UserController extends BaseController {
returnuserTokenAccessEnabled;
}
@ApiOperation(value="Get User Token (getUserToken)",
notes="Returns the token of the User based on the provided User Id. "+
"If the user who performs the request has the authority of 'SYS_ADMIN', it is possible to get the token of any tenant administrator. "+
"If the user who performs the request has the authority of 'TENANT_ADMIN', it is possible to get the token of any customer user that belongs to the same tenant. ")
@ApiOperation(value="Save Or update User (saveUser)",
notes="Create or update the User. When creating user, platform generates User Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). "+
"The newly created User Id will be present in the response. "+
"Specify existing User Id to update the device. "+
"Referencing non-existing User Id will cause 'Not Found' error."+
"\n\nDevice email is unique for entire platform setup.")
@ -188,10 +209,13 @@ public class UserController extends BaseController {
}
}
@ApiOperation(value="Send or re-send the activation email",
notes="Force send the activation email to the user. Useful to resend the email if user has accidentally deleted it. "+SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@ -331,11 +388,16 @@ public class UserController extends BaseController {
}
}
@ApiOperation(value="Enable/Disable User credentials (setUserCredentialsEnabled)",
notes="Enables or Disables user credentials. Useful when you would like to block user account without deleting it. "+PAGE_DATA_PARAMETERS+TENANT_AUTHORITY_PARAGRAPH)
@ -76,6 +149,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId {
@Override
@JsonProperty(access=Access.READ_ONLY)
@ApiModelProperty(position=4,value="Name of the customer. Read-only, duplicated from title for backward compatibility",example="Company A",readOnly=true)
@ApiModelProperty(position=12,value="Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ")
privateStringimage;
privatebooleanisDefault;
@ApiModelProperty(position=16,value="Type of the profile. Always 'DEFAULT' for now. Reserved for future use.")
privateDeviceProfileTypetype;
@ApiModelProperty(position=14,value="Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.")
@ApiModelProperty(position=7,value="Reference to the rule chain. "+
"If present, the specified rule chain will be used to process all messages related to device, including telemetry, attribute updates, etc. "+
"Otherwise, the root rule chain will be used to process those messages.")
privateRuleChainIddefaultRuleChainId;
@ApiModelProperty(position=6,value="Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.")
privateDashboardIddefaultDashboardId;
@NoXss
@ApiModelProperty(position=8,value="Reference to the rule engine queue. "+
"If present, the specified queue will be used to store all unprocessed messages related to device, including telemetry, attribute updates, etc. "+
"Otherwise, the 'Main' queue will be used to store those messages.")
privateStringdefaultQueueName;
@Valid
privatetransientDeviceProfileDataprofileData;
@JsonIgnore
privatebyte[]profileDataBytes;
@NoXss
@ApiModelProperty(position=13,value="Unique provisioning key used by 'Device Provisioning' feature.")
privateStringprovisionDeviceKey;
@ApiModelProperty(position=9,value="Reference to the firmware OTA package. If present, the specified package will be used as default device firmware. ")
privateOtaPackageIdfirmwareId;
@ApiModelProperty(position=10,value="Reference to the software OTA package. If present, the specified package will be used as default device software. ")
privateOtaPackageIdsoftwareId;
publicDeviceProfile(){
@ -88,16 +107,32 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
this.softwareId=deviceProfile.getSoftwareId();
}
@ApiModelProperty(position=1,value="JSON object with the device profile Id. "+
"Specify this field to update the device profile. "+
"Referencing non-existing device profile Id will cause error. "+
"Omit this field to create new device profile.")
@Override
publicDeviceProfileIdgetId(){
returnsuper.getId();
}
@ApiModelProperty(position=2,value="Timestamp of the profile creation, in milliseconds",example="1609459200000",readOnly=true)
@Override
publiclonggetCreatedTime(){
returnsuper.getCreatedTime();
}
@Override
publicStringgetSearchText(){
returngetName();
}
@Override
publicStringgetName(){
returnname;
@ApiModelProperty(position=5,value="Used to mark the default profile. Default profile is used when the device profile is not specified during device creation.")
publicbooleanisDefault(){
returnisDefault;
}
@ApiModelProperty(position=16,value="Complex JSON object that includes addition device profile configuration (transport, alarm rules, etc).")
@ApiModelProperty(position=3,value="Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ")
privatefinalStringimage;
@ApiModelProperty(position=4,value="Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.")
privatefinalDashboardIddefaultDashboardId;
@ApiModelProperty(position=5,value="Type of the profile. Always 'DEFAULT' for now. Reserved for future use.")
privatefinalDeviceProfileTypetype;
@ApiModelProperty(position=6,value="Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.")
@ApiModelProperty(position=3,value="Title of the tenant",example="Company A")
privateStringtitle;
@NoXss
@ApiModelProperty(position=5,value="Geo region of the tenant",example="North America")
privateStringregion;
@ApiModelProperty(position=6,required=true,value="JSON object with Tenant Profile Id")
privateTenantProfileIdtenantProfileId;
publicTenant(){
@ -63,6 +71,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
}
@Override
@ApiModelProperty(position=4,value="Name of the tenant. Read-only, duplicated from title for backward compatibility",example="Company A",readOnly=true)
@ApiModelProperty(position=3,value="Name of the tenant profile",example="High Priority Tenants")
privateStringname;
@NoXss
@ApiModelProperty(position=4,value="Description of the tenant profile",example="Any text")
privateStringdescription;
@ApiModelProperty(position=5,value="Default Tenant profile to be used.",example="true")
privatebooleanisDefault;
@ApiModelProperty(position=6,value="If enabled, will push all messages related to this tenant and processed by core platform services into separate queue. "+
"Useful for complex microservices deployments, to isolate processing of the data for specific tenants",example="true")
privatebooleanisolatedTbCore;
@ApiModelProperty(position=7,value="If enabled, will push all messages related to this tenant and processed by the rule engine into separate queue. "+
"Useful for complex microservices deployments, to isolate processing of the data for specific tenants",example="true")
privatebooleanisolatedTbRuleEngine;
@ApiModelProperty(position=8,value="Complex JSON object that contains profile settings: max devices, max assets, rate limits, etc.")
privatetransientTenantProfileDataprofileData;
@JsonIgnore
privatebyte[]profileDataBytes;
@ -65,6 +76,21 @@ public class TenantProfile extends SearchTextBased<TenantProfileId> implements H
@ApiModelProperty(position=3,value="JSON object with Tenant Id",readOnly=true)
privateTenantIdtenantId;
@ApiModelProperty(position=4,value="JSON object with Customer Id",readOnly=true)
privateCustomerIdcustomerId;
@ApiModelProperty(position=5,value="JSON object with Entity id",readOnly=true)
privateEntityIdentityId;
@ApiModelProperty(position=6,value="Name of the logged entity",example="Thermometer",readOnly=true)
privateStringentityName;
@ApiModelProperty(position=7,value="JSON object with User id.",readOnly=true)
privateUserIduserId;
@ApiModelProperty(position=8,value="Unique user name(email) of the user that performed some action on logged entity",example="tenant@thingsboard.org",readOnly=true)
@ApiModelProperty(position=12,value="Failure action details info. An empty string in case of action status type 'SUCCESS', otherwise includes stack trace of the caused exception.",readOnly=true)
privateStringactionFailureDetails;
publicAuditLog(){
@ -57,4 +70,17 @@ public class AuditLog extends BaseData<AuditLogId> {
@ApiModelProperty(position=1,value="String value representing msg direction type (incoming to entity or outcoming from entity)",allowableValues="IN, OUT")
protectedStringmsgDirectionType;
@ApiModelProperty(position=2,value="String value representing the server name, identifier or ip address where the platform is running",example="ip-172-31-24-152")
protectedStringserver;
@ApiModelProperty(position=3,value="The case insensitive 'contains' filter based on data (key and value) for the message.",example="humidity")
protectedStringdataSearch;
@ApiModelProperty(position=4,value="The case insensitive 'contains' filter based on metadata (key and value) for the message.",example="deviceName")
protectedStringmetadataSearch;
@ApiModelProperty(position=5,value="String value representing the entity type",allowableValues="DEVICE")
protectedStringentityName;
@ApiModelProperty(position=6,value="String value representing the type of message routing",example="Success")
protectedStringrelationType;
@ApiModelProperty(position=7,value="String value representing the entity id in the event body (originator of the message)",example="de9d54a0-2b7a-11ec-a3cc-23386423d98f")
protectedStringentityId;
@ApiModelProperty(position=8,value="String value representing the message type",example="POST_TELEMETRY_REQUEST")
protectedStringmsgType;
@ApiModelProperty(position=9,value="Boolean value to filter the errors",allowableValues="false, true")
protectedbooleanisError;
@ApiModelProperty(position=10,value="The case insensitive 'contains' filter based on error message",example="not present in the DB")
protectedStringerrorStr;
@ApiModelProperty(position=11,value="String value representing the method name when the error happened",example="onClusterEventMsg")
protectedStringmethod;
@ApiModelProperty(position=12,value="The minimum number of successfully processed messages",example="25")
protectedIntegermessagesProcessed;
@ApiModelProperty(position=13,value="The minimum number of errors occurred during messages processing",example="30")
protectedIntegererrorsOccurred;
@ApiModelProperty(position=14,value="String value representing the lifecycle event type",example="STARTED")
protectedStringevent;
@ApiModelProperty(position=15,value="String value representing status of the lifecycle event",allowableValues="Success, Failure")
@ApiModelProperty(value="Email attribute key of OAuth2 principal attributes. "+
"Must be specified for BASIC mapper type and cannot be specified for GITHUB type")
privatefinalStringemailAttributeKey;
@ApiModelProperty(value="First name attribute key")
privatefinalStringfirstNameAttributeKey;
@ApiModelProperty(value="Last name attribute key")
privatefinalStringlastNameAttributeKey;
@ApiModelProperty(value="Tenant naming strategy. For DOMAIN type, domain for tenant name will be taken from the email (substring before '@')",required=true)
@ApiModelProperty(position=1,required=true,value="Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.")
privateintfromIndex;
@ApiModelProperty(position=2,required=true,value="Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'to' part of the connection.")
privateinttoIndex;
@ApiModelProperty(position=3,required=true,value="Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'")
@ApiModelProperty(position=3,required=true,value="JSON object with Tenant Id.",readOnly=true)
privateTenantIdtenantId;
@NoXss
@ApiModelProperty(position=4,required=true,value="Rule Chain name",example="Humidity data processing")
privateStringname;
@ApiModelProperty(position=5,value="Rule Chain type. 'EDGE' rule chains are processing messages on the edge devices only.",example="A4B72CCDFF33")
privateRuleChainTypetype;
@ApiModelProperty(position=6,value="JSON object with Rule Chain Id. Pointer to the first rule node that should receive all messages pushed to this rule chain.")
privateRuleNodeIdfirstRuleNodeId;
@ApiModelProperty(position=7,value="Indicates root rule chain. The root rule chain process messages from all devices and entities by default. User may configure default rule chain per device profile.")
privatebooleanroot;
@ApiModelProperty(position=8,value="Reserved for future usage.")
privatebooleandebugMode;
@ApiModelProperty(position=9,value="Reserved for future usage. The actual list of rule nodes and their relations is stored in the database separately.")
privatetransientJsonNodeconfiguration;
@JsonIgnore
@ -75,6 +85,21 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im
returnname;
}
@ApiModelProperty(position=1,value="JSON object with the Rule Chain Id. "+
"Specify this field to update the Rule Chain. "+
"Referencing non-existing Rule Chain Id will cause error. "+
"Omit this field to create new rule chain.")
@Override
publicRuleChainIdgetId(){
returnsuper.getId();
}
@ApiModelProperty(position=2,value="Timestamp of the rule chain creation, in milliseconds",example="1609459200000",readOnly=true)
@ApiModelProperty(position=1,required=true,value="Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.")
privateintfromIndex;
@ApiModelProperty(position=2,required=true,value="JSON object with the Rule Chain Id.")
privateRuleChainIdtargetRuleChainId;
@ApiModelProperty(position=3,required=true,value="JSON object with the additional information about the connection.")
privateJsonNodeadditionalInfo;
@ApiModelProperty(position=4,required=true,value="Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'")
@ApiModelProperty(position=7,value="JSON with the rule node configuration. Structure depends on the rule node implementation.",dataType="com.fasterxml.jackson.databind.JsonNode")
privatetransientJsonNodeconfiguration;
@JsonIgnore
privatebyte[]configurationBytes;
@ -75,4 +83,25 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl
@ApiModelProperty(position=1,value="JSON object with the Rule Node Id. "+
"Specify this field to update the Rule Node. "+
"Referencing non-existing Rule Node Id will cause error. "+
"Omit this field to create new rule node.")
@Override
publicRuleNodeIdgetId(){
returnsuper.getId();
}
@ApiModelProperty(position=2,value="Timestamp of the rule node creation, in milliseconds",example="1609459200000",readOnly=true)
@Override
publiclonggetCreatedTime(){
returnsuper.getCreatedTime();
}
@ApiModelProperty(position=8,value="Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.",dataType="com.fasterxml.jackson.databind.JsonNode")