Showing
10 changed files
with
185 additions
and
17 deletions
... | ... | @@ -187,11 +187,13 @@ public abstract class BaseController { |
187 | 187 | protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; |
188 | 188 | protected static final String ASSET_TYPE_DESCRIPTION = "Asset type"; |
189 | 189 | protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'"; |
190 | + protected static final String RULE_CHAIN_TYPE_DESCRIPTION = "Rule chain type (CORE or EDGE)"; | |
190 | 191 | |
191 | 192 | protected static final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name."; |
192 | 193 | protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title."; |
193 | 194 | protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty."; |
194 | 195 | protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name."; |
196 | + protected static final String RULE_CHAIN_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the rule chain name."; | |
195 | 197 | protected static final String DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device profile name."; |
196 | 198 | protected static final String CUSTOMER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the customer title."; |
197 | 199 | protected static final String EDGE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the edge name."; |
... | ... | @@ -207,10 +209,12 @@ public abstract class BaseController { |
207 | 209 | protected static final String ALARM_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, startTs, endTs, type, ackTs, clearTs, severity, status"; |
208 | 210 | protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, id"; |
209 | 211 | protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; |
212 | + protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root"; | |
210 | 213 | protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus"; |
211 | 214 | protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)"; |
212 | 215 | protected static final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC"; |
213 | 216 | protected static final String RPC_STATUS_ALLOWABLE_VALUES = "QUEUED, SENT, DELIVERED, SUCCESSFUL, TIMEOUT, EXPIRED, FAILED"; |
217 | + protected static final String RULE_CHAIN_TYPES_ALLOWABLE_VALUES = "CORE, EDGE"; | |
214 | 218 | protected static final String TRANSPORT_TYPE_ALLOWABLE_VALUES = "DEFAULT, MQTT, COAP, LWM2M, SNMP"; |
215 | 219 | protected static final String DEVICE_INFO_DESCRIPTION = "Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. "; |
216 | 220 | protected static final String ASSET_INFO_DESCRIPTION = "Asset Info is an extension of the default Asset object that contains information about the assigned customer name. "; | ... | ... |
... | ... | @@ -91,9 +91,9 @@ public class RpcV2Controller extends AbstractRpcController { |
91 | 91 | "In case of persistent RPC, the result of this call is 'rpcId' UUID. In case of lightweight RPC, " + |
92 | 92 | "the result of this call is the response from device, or 504 Gateway Timeout if device is offline."; |
93 | 93 | |
94 | - private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT; | |
94 | + private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT + TENANT_AND_USER_AUTHORITY_PARAGRAPH; | |
95 | 95 | |
96 | - private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT; | |
96 | + private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT + TENANT_AND_USER_AUTHORITY_PARAGRAPH; | |
97 | 97 | |
98 | 98 | @ApiOperation(value = "Send one-way RPC request", notes = ONE_WAY_RPC_REQUEST_DESCRIPTION) |
99 | 99 | @ApiResponses(value = { |
... | ... | @@ -131,7 +131,7 @@ public class RpcV2Controller extends AbstractRpcController { |
131 | 131 | return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); |
132 | 132 | } |
133 | 133 | |
134 | - @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call.") | |
134 | + @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call." + TENANT_AND_USER_AUTHORITY_PARAGRAPH) | |
135 | 135 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
136 | 136 | @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET) |
137 | 137 | @ResponseBody |
... | ... | @@ -147,7 +147,7 @@ public class RpcV2Controller extends AbstractRpcController { |
147 | 147 | } |
148 | 148 | } |
149 | 149 | |
150 | - @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination.") | |
150 | + @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_AND_USER_AUTHORITY_PARAGRAPH) | |
151 | 151 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
152 | 152 | @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET) |
153 | 153 | @ResponseBody |
... | ... | @@ -177,7 +177,7 @@ public class RpcV2Controller extends AbstractRpcController { |
177 | 177 | } |
178 | 178 | } |
179 | 179 | |
180 | - @ApiOperation(value = "Delete persistent RPC", notes = "Deletes the persistent RPC request.") | |
180 | + @ApiOperation(value = "Delete persistent RPC", notes = "Deletes the persistent RPC request." + TENANT_AUTHORITY_PARAGRAPH) | |
181 | 181 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
182 | 182 | @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE) |
183 | 183 | @ResponseBody | ... | ... |
... | ... | @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
21 | 21 | import com.fasterxml.jackson.databind.node.ArrayNode; |
22 | 22 | import com.fasterxml.jackson.databind.node.ObjectNode; |
23 | 23 | import io.swagger.annotations.ApiOperation; |
24 | +import io.swagger.annotations.ApiParam; | |
24 | 25 | import lombok.extern.slf4j.Slf4j; |
25 | 26 | import org.springframework.beans.factory.annotation.Autowired; |
26 | 27 | import org.springframework.beans.factory.annotation.Value; |
... | ... | @@ -95,6 +96,25 @@ public class RuleChainController extends BaseController { |
95 | 96 | private static final ObjectMapper objectMapper = new ObjectMapper(); |
96 | 97 | public static final int TIMEOUT = 20; |
97 | 98 | |
99 | + private static final String RULE_CHAIN_DESCRIPTION = "The rule chain object is lightweight and contains general information about the rule chain. " + | |
100 | + "List of rule nodes and their connection is stored in a separate 'metadata' object."; | |
101 | + private static final String RULE_CHAIN_METADATA_DESCRIPTION = "The metadata object contains information about the rule nodes and their connections."; | |
102 | + private static final String TEST_JS_FUNCTION = "Execute the JavaScript function and return the result. The format of request: \n\n" | |
103 | + + MARKDOWN_CODE_BLOCK_START | |
104 | + + "{\n" + | |
105 | + " \"script\": \"Your JS Function as String\",\n" + | |
106 | + " \"scriptType\": \"One of: update, generate, filter, switch, json, string\",\n" + | |
107 | + " \"argNames\": [\"msg\", \"metadata\", \"type\"],\n" + | |
108 | + " \"msg\": \"{\\\"temperature\\\": 42}\", \n" + | |
109 | + " \"metadata\": {\n" + | |
110 | + " \"deviceName\": \"Device A\",\n" + | |
111 | + " \"deviceType\": \"Thermometer\"\n" + | |
112 | + " },\n" + | |
113 | + " \"msgType\": \"POST_TELEMETRY_REQUEST\"\n" + | |
114 | + "}" | |
115 | + + MARKDOWN_CODE_BLOCK_END | |
116 | + + "\n\n Expected result JSON contains \"output\" and \"error\"."; | |
117 | + | |
98 | 118 | @Autowired |
99 | 119 | private InstallScripts installScripts; |
100 | 120 | |
... | ... | @@ -110,10 +130,14 @@ public class RuleChainController extends BaseController { |
110 | 130 | @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}") |
111 | 131 | private boolean debugPerTenantEnabled; |
112 | 132 | |
133 | + @ApiOperation(value = "Get Rule Chain (getRuleChainById)", | |
134 | + notes = "Fetch the Rule Chain object based on the provided Rule Chain Id. " + RULE_CHAIN_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) | |
113 | 135 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
114 | 136 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) |
115 | 137 | @ResponseBody |
116 | - public RuleChain getRuleChainById(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
138 | + public RuleChain getRuleChainById( | |
139 | + @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) | |
140 | + @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
117 | 141 | checkParameter(RULE_CHAIN_ID, strRuleChainId); |
118 | 142 | try { |
119 | 143 | RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); |
... | ... | @@ -123,10 +147,14 @@ public class RuleChainController extends BaseController { |
123 | 147 | } |
124 | 148 | } |
125 | 149 | |
150 | + @ApiOperation(value = "Get Rule Chain (getRuleChainById)", | |
151 | + notes = "Fetch the Rule Chain Metadata object based on the provided Rule Chain Id. " + RULE_CHAIN_METADATA_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) | |
126 | 152 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
127 | 153 | @RequestMapping(value = "/ruleChain/{ruleChainId}/metadata", method = RequestMethod.GET) |
128 | 154 | @ResponseBody |
129 | - public RuleChainMetaData getRuleChainMetaData(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
155 | + public RuleChainMetaData getRuleChainMetaData( | |
156 | + @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) | |
157 | + @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
130 | 158 | checkParameter(RULE_CHAIN_ID, strRuleChainId); |
131 | 159 | try { |
132 | 160 | RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); |
... | ... | @@ -137,11 +165,18 @@ public class RuleChainController extends BaseController { |
137 | 165 | } |
138 | 166 | } |
139 | 167 | |
140 | - | |
168 | + @ApiOperation(value = "Create Or Update Rule Chain (saveRuleChain)", | |
169 | + 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). " + | |
170 | + "The newly created Rule Chain Id will be present in the response. " + | |
171 | + "Specify existing Rule Chain id to update the rule chain. " + | |
172 | + "Referencing non-existing rule chain Id will cause 'Not Found' error." + | |
173 | + "\n\n" + RULE_CHAIN_DESCRIPTION) | |
141 | 174 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
142 | 175 | @RequestMapping(value = "/ruleChain", method = RequestMethod.POST) |
143 | 176 | @ResponseBody |
144 | - public RuleChain saveRuleChain(@RequestBody RuleChain ruleChain) throws ThingsboardException { | |
177 | + public RuleChain saveRuleChain( | |
178 | + @ApiParam(value = "A JSON value representing the rule chain.") | |
179 | + @RequestBody RuleChain ruleChain) throws ThingsboardException { | |
145 | 180 | try { |
146 | 181 | boolean created = ruleChain.getId() == null; |
147 | 182 | ruleChain.setTenantId(getCurrentUser().getTenantId()); |
... | ... | @@ -175,10 +210,15 @@ public class RuleChainController extends BaseController { |
175 | 210 | } |
176 | 211 | } |
177 | 212 | |
213 | + @ApiOperation(value = "Create Default Rule Chain", | |
214 | + notes = "Create rule chain from template, based on the specified name in the request. " + | |
215 | + "Creates the rule chain based on the template that is used to create root rule chain. " + TENANT_AUTHORITY_PARAGRAPH) | |
178 | 216 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
179 | 217 | @RequestMapping(value = "/ruleChain/device/default", method = RequestMethod.POST) |
180 | 218 | @ResponseBody |
181 | - public RuleChain saveRuleChain(@RequestBody DefaultRuleChainCreateRequest request) throws ThingsboardException { | |
219 | + public RuleChain saveRuleChain( | |
220 | + @ApiParam(value = "A JSON value representing the request.") | |
221 | + @RequestBody DefaultRuleChainCreateRequest request) throws ThingsboardException { | |
182 | 222 | try { |
183 | 223 | checkNotNull(request); |
184 | 224 | checkParameter(request.getName(), "name"); |
... | ... | @@ -198,10 +238,14 @@ public class RuleChainController extends BaseController { |
198 | 238 | } |
199 | 239 | } |
200 | 240 | |
241 | + @ApiOperation(value = "Set Root Rule Chain (setRootRuleChain)", | |
242 | + notes = "Makes the rule chain to be root rule chain. Updates previous root rule chain as well. " + TENANT_AUTHORITY_PARAGRAPH) | |
201 | 243 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
202 | 244 | @RequestMapping(value = "/ruleChain/{ruleChainId}/root", method = RequestMethod.POST) |
203 | 245 | @ResponseBody |
204 | - public RuleChain setRootRuleChain(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
246 | + public RuleChain setRootRuleChain( | |
247 | + @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) | |
248 | + @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
205 | 249 | checkParameter(RULE_CHAIN_ID, strRuleChainId); |
206 | 250 | try { |
207 | 251 | RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); |
... | ... | @@ -237,10 +281,14 @@ public class RuleChainController extends BaseController { |
237 | 281 | } |
238 | 282 | } |
239 | 283 | |
284 | + @ApiOperation(value = "Update Rule Chain Metadata", | |
285 | + notes = "Updates the rule chain metadata. " + RULE_CHAIN_METADATA_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) | |
240 | 286 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
241 | 287 | @RequestMapping(value = "/ruleChain/metadata", method = RequestMethod.POST) |
242 | 288 | @ResponseBody |
243 | - public RuleChainMetaData saveRuleChainMetaData(@RequestBody RuleChainMetaData ruleChainMetaData) throws ThingsboardException { | |
289 | + public RuleChainMetaData saveRuleChainMetaData( | |
290 | + @ApiParam(value = "A JSON value representing the rule chain metadata.") | |
291 | + @RequestBody RuleChainMetaData ruleChainMetaData) throws ThingsboardException { | |
244 | 292 | try { |
245 | 293 | TenantId tenantId = getTenantId(); |
246 | 294 | if (debugPerTenantEnabled) { |
... | ... | @@ -278,15 +326,24 @@ public class RuleChainController extends BaseController { |
278 | 326 | } |
279 | 327 | } |
280 | 328 | |
329 | + | |
330 | + @ApiOperation(value = "Get Rule Chains (getRuleChains)", | |
331 | + notes = "Returns a page of Rule Chains owned by tenant. " + RULE_CHAIN_DESCRIPTION + PAGE_DATA_PARAMETERS) | |
281 | 332 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
282 | 333 | @RequestMapping(value = "/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET) |
283 | 334 | @ResponseBody |
284 | 335 | public PageData<RuleChain> getRuleChains( |
336 | + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) | |
285 | 337 | @RequestParam int pageSize, |
338 | + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) | |
286 | 339 | @RequestParam int page, |
340 | + @ApiParam(value = RULE_CHAIN_TYPE_DESCRIPTION, allowableValues = RULE_CHAIN_TYPES_ALLOWABLE_VALUES) | |
287 | 341 | @RequestParam(value = "type", required = false) String typeStr, |
342 | + @ApiParam(value = RULE_CHAIN_TEXT_SEARCH_DESCRIPTION) | |
288 | 343 | @RequestParam(required = false) String textSearch, |
344 | + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES) | |
289 | 345 | @RequestParam(required = false) String sortProperty, |
346 | + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) | |
290 | 347 | @RequestParam(required = false) String sortOrder) throws ThingsboardException { |
291 | 348 | try { |
292 | 349 | TenantId tenantId = getCurrentUser().getTenantId(); |
... | ... | @@ -301,10 +358,14 @@ public class RuleChainController extends BaseController { |
301 | 358 | } |
302 | 359 | } |
303 | 360 | |
361 | + @ApiOperation(value = "Delete rule chain (deleteRuleChain)", | |
362 | + 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.") | |
304 | 363 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
305 | 364 | @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) |
306 | 365 | @ResponseStatus(value = HttpStatus.OK) |
307 | - public void deleteRuleChain(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
366 | + public void deleteRuleChain( | |
367 | + @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) | |
368 | + @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { | |
308 | 369 | checkParameter(RULE_CHAIN_ID, strRuleChainId); |
309 | 370 | try { |
310 | 371 | RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); |
... | ... | @@ -347,10 +408,15 @@ public class RuleChainController extends BaseController { |
347 | 408 | } |
348 | 409 | } |
349 | 410 | |
411 | + @ApiOperation(value = "Get latest input message (getLatestRuleNodeDebugInput)", | |
412 | + notes = "Gets the input message from the debug events for specified Rule Chain Id. " + | |
413 | + "Referencing non-existing rule chain Id will cause an error. ") | |
350 | 414 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
351 | 415 | @RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET) |
352 | 416 | @ResponseBody |
353 | - public JsonNode getLatestRuleNodeDebugInput(@PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException { | |
417 | + public JsonNode getLatestRuleNodeDebugInput( | |
418 | + @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) | |
419 | + @PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException { | |
354 | 420 | checkParameter(RULE_NODE_ID, strRuleNodeId); |
355 | 421 | try { |
356 | 422 | RuleNodeId ruleNodeId = new RuleNodeId(toUUID(strRuleNodeId)); |
... | ... | @@ -373,10 +439,15 @@ public class RuleChainController extends BaseController { |
373 | 439 | } |
374 | 440 | } |
375 | 441 | |
442 | + | |
443 | + @ApiOperation(value = "Test JavaScript function", | |
444 | + notes = TEST_JS_FUNCTION + TENANT_AUTHORITY_PARAGRAPH) | |
376 | 445 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
377 | 446 | @RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST) |
378 | 447 | @ResponseBody |
379 | - public JsonNode testScript(@RequestBody JsonNode inputParams) throws ThingsboardException { | |
448 | + public JsonNode testScript( | |
449 | + @ApiParam(value = "Test JS request. See API call description above.") | |
450 | + @RequestBody JsonNode inputParams) throws ThingsboardException { | |
380 | 451 | try { |
381 | 452 | String script = inputParams.get("script").asText(); |
382 | 453 | String scriptType = inputParams.get("scriptType").asText(); |
... | ... | @@ -436,10 +507,13 @@ public class RuleChainController extends BaseController { |
436 | 507 | } |
437 | 508 | } |
438 | 509 | |
510 | + @ApiOperation(value = "Export Rule Chains", notes = "Exports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH) | |
439 | 511 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
440 | 512 | @RequestMapping(value = "/ruleChains/export", params = {"limit"}, method = RequestMethod.GET) |
441 | 513 | @ResponseBody |
442 | - public RuleChainData exportRuleChains(@RequestParam("limit") int limit) throws ThingsboardException { | |
514 | + public RuleChainData exportRuleChains( | |
515 | + @ApiParam(value = "A limit of rule chains to export.", required = true) | |
516 | + @RequestParam("limit") int limit) throws ThingsboardException { | |
443 | 517 | try { |
444 | 518 | TenantId tenantId = getCurrentUser().getTenantId(); |
445 | 519 | PageLink pageLink = new PageLink(limit); |
... | ... | @@ -449,10 +523,15 @@ public class RuleChainController extends BaseController { |
449 | 523 | } |
450 | 524 | } |
451 | 525 | |
526 | + @ApiOperation(value = "Import Rule Chains", notes = "Imports all tenant rule chains as one JSON." + TENANT_AUTHORITY_PARAGRAPH) | |
452 | 527 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
453 | 528 | @RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST) |
454 | 529 | @ResponseBody |
455 | - public void importRuleChains(@RequestBody RuleChainData ruleChainData, @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException { | |
530 | + public void importRuleChains( | |
531 | + @ApiParam(value = "A JSON value representing the rule chains.") | |
532 | + @RequestBody RuleChainData ruleChainData, | |
533 | + @ApiParam(value = "Enables overwrite for existing rule chains with the same name.") | |
534 | + @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException { | |
456 | 535 | try { |
457 | 536 | TenantId tenantId = getCurrentUser().getTenantId(); |
458 | 537 | List<RuleChainImportResult> importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, RuleChainType.CORE, overwrite); | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/rule/DefaultRuleChainCreateRequest.java
... | ... | @@ -15,17 +15,21 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | +import io.swagger.annotations.ApiModel; | |
19 | +import io.swagger.annotations.ApiModelProperty; | |
18 | 20 | import lombok.Data; |
19 | 21 | import lombok.extern.slf4j.Slf4j; |
20 | 22 | |
21 | 23 | import java.io.Serializable; |
22 | 24 | |
25 | +@ApiModel | |
23 | 26 | @Data |
24 | 27 | @Slf4j |
25 | 28 | public class DefaultRuleChainCreateRequest implements Serializable { |
26 | 29 | |
27 | 30 | private static final long serialVersionUID = 5600333716030561537L; |
28 | 31 | |
32 | + @ApiModelProperty(position = 1, required = true, value = "Name of the new rule chain", example = "Root Rule Chain") | |
29 | 33 | private String name; |
30 | 34 | |
31 | 35 | } | ... | ... |
... | ... | @@ -15,14 +15,20 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | +import io.swagger.annotations.ApiModel; | |
19 | +import io.swagger.annotations.ApiModelProperty; | |
18 | 20 | import lombok.Data; |
19 | 21 | |
20 | 22 | /** |
21 | 23 | * Created by ashvayka on 21.03.18. |
22 | 24 | */ |
25 | +@ApiModel | |
23 | 26 | @Data |
24 | 27 | public class NodeConnectionInfo { |
28 | + @ApiModelProperty(position = 1, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") | |
25 | 29 | private int fromIndex; |
30 | + @ApiModelProperty(position = 2, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'to' part of the connection.") | |
26 | 31 | private int toIndex; |
32 | + @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'") | |
27 | 33 | private String type; |
28 | 34 | } | ... | ... |
... | ... | @@ -17,6 +17,8 @@ package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.annotation.JsonIgnore; |
19 | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | +import io.swagger.annotations.ApiModel; | |
21 | +import io.swagger.annotations.ApiModelProperty; | |
20 | 22 | import lombok.Data; |
21 | 23 | import lombok.EqualsAndHashCode; |
22 | 24 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -28,6 +30,7 @@ import org.thingsboard.server.common.data.id.RuleNodeId; |
28 | 30 | import org.thingsboard.server.common.data.id.TenantId; |
29 | 31 | import org.thingsboard.server.common.data.validation.NoXss; |
30 | 32 | |
33 | +@ApiModel | |
31 | 34 | @Data |
32 | 35 | @EqualsAndHashCode(callSuper = true) |
33 | 36 | @Slf4j |
... | ... | @@ -35,13 +38,20 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im |
35 | 38 | |
36 | 39 | private static final long serialVersionUID = -5656679015121935465L; |
37 | 40 | |
41 | + @ApiModelProperty(position = 3, required = true, value = "JSON object with Tenant Id.", readOnly = true) | |
38 | 42 | private TenantId tenantId; |
39 | 43 | @NoXss |
44 | + @ApiModelProperty(position = 4, required = true, value = "Rule Chain name", example = "Humidity data processing") | |
40 | 45 | private String name; |
46 | + @ApiModelProperty(position = 5, value = "Rule Chain type. 'EDGE' rule chains are processing messages on the edge devices only.", example = "A4B72CCDFF33") | |
41 | 47 | private RuleChainType type; |
48 | + @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.") | |
42 | 49 | private RuleNodeId firstRuleNodeId; |
50 | + @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.") | |
43 | 51 | private boolean root; |
52 | + @ApiModelProperty(position = 8, value = "Reserved for future usage.") | |
44 | 53 | private boolean debugMode; |
54 | + @ApiModelProperty(position = 9, value = "Reserved for future usage. The actual list of rule nodes and their relations is stored in the database separately.") | |
45 | 55 | private transient JsonNode configuration; |
46 | 56 | |
47 | 57 | @JsonIgnore |
... | ... | @@ -75,6 +85,21 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im |
75 | 85 | return name; |
76 | 86 | } |
77 | 87 | |
88 | + @ApiModelProperty(position = 1, value = "JSON object with the Rule Chain Id. " + | |
89 | + "Specify this field to update the Rule Chain. " + | |
90 | + "Referencing non-existing Rule Chain Id will cause error. " + | |
91 | + "Omit this field to create new rule chain." ) | |
92 | + @Override | |
93 | + public RuleChainId getId() { | |
94 | + return super.getId(); | |
95 | + } | |
96 | + | |
97 | + @ApiModelProperty(position = 2, value = "Timestamp of the rule chain creation, in milliseconds", example = "1609459200000", readOnly = true) | |
98 | + @Override | |
99 | + public long getCreatedTime() { | |
100 | + return super.getCreatedTime(); | |
101 | + } | |
102 | + | |
78 | 103 | public JsonNode getConfiguration() { |
79 | 104 | return SearchTextBasedWithAdditionalInfo.getJson(() -> configuration, () -> configurationBytes); |
80 | 105 | } |
... | ... | @@ -82,4 +107,5 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im |
82 | 107 | public void setConfiguration(JsonNode data) { |
83 | 108 | setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes); |
84 | 109 | } |
110 | + | |
85 | 111 | } | ... | ... |
... | ... | @@ -16,16 +16,23 @@ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import io.swagger.annotations.ApiModel; | |
20 | +import io.swagger.annotations.ApiModelProperty; | |
19 | 21 | import lombok.Data; |
20 | 22 | import org.thingsboard.server.common.data.id.RuleChainId; |
21 | 23 | |
22 | 24 | /** |
23 | 25 | * Created by ashvayka on 21.03.18. |
24 | 26 | */ |
27 | +@ApiModel | |
25 | 28 | @Data |
26 | 29 | public class RuleChainConnectionInfo { |
30 | + @ApiModelProperty(position = 1, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") | |
27 | 31 | private int fromIndex; |
32 | + @ApiModelProperty(position = 2, required = true, value = "JSON object with the Rule Chain Id.") | |
28 | 33 | private RuleChainId targetRuleChainId; |
34 | + @ApiModelProperty(position = 3, required = true, value = "JSON object with the additional information about the connection.") | |
29 | 35 | private JsonNode additionalInfo; |
36 | + @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'") | |
30 | 37 | private String type; |
31 | 38 | } | ... | ... |
... | ... | @@ -15,13 +15,18 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | +import io.swagger.annotations.ApiModel; | |
19 | +import io.swagger.annotations.ApiModelProperty; | |
18 | 20 | import lombok.Data; |
19 | 21 | |
20 | 22 | import java.util.List; |
21 | 23 | |
24 | +@ApiModel | |
22 | 25 | @Data |
23 | 26 | public class RuleChainData { |
24 | 27 | |
28 | + @ApiModelProperty(position = 1, required = true, value = "List of the Rule Chain objects.", readOnly = true) | |
25 | 29 | List<RuleChain> ruleChains; |
30 | + @ApiModelProperty(position = 2, required = true, value = "List of the Rule Chain metadata objects.", readOnly = true) | |
26 | 31 | List<RuleChainMetaData> metadata; |
27 | 32 | } | ... | ... |
... | ... | @@ -16,6 +16,8 @@ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import io.swagger.annotations.ApiModel; | |
20 | +import io.swagger.annotations.ApiModelProperty; | |
19 | 21 | import lombok.Data; |
20 | 22 | import org.thingsboard.server.common.data.id.RuleChainId; |
21 | 23 | |
... | ... | @@ -25,17 +27,23 @@ import java.util.List; |
25 | 27 | /** |
26 | 28 | * Created by igor on 3/13/18. |
27 | 29 | */ |
30 | +@ApiModel | |
28 | 31 | @Data |
29 | 32 | public class RuleChainMetaData { |
30 | 33 | |
34 | + @ApiModelProperty(position = 1, required = true, value = "JSON object with Rule Chain Id.", readOnly = true) | |
31 | 35 | private RuleChainId ruleChainId; |
32 | 36 | |
37 | + @ApiModelProperty(position = 2, required = true, value = "Index of the first rule node in the 'nodes' list") | |
33 | 38 | private Integer firstNodeIndex; |
34 | 39 | |
40 | + @ApiModelProperty(position = 3, required = true, value = "List of rule node JSON objects") | |
35 | 41 | private List<RuleNode> nodes; |
36 | 42 | |
43 | + @ApiModelProperty(position = 4, required = true, value = "List of JSON objects that represent connections between rule nodes") | |
37 | 44 | private List<NodeConnectionInfo> connections; |
38 | 45 | |
46 | + @ApiModelProperty(position = 5, required = true, value = "List of JSON objects that represent connections between rule nodes and other rule chains.") | |
39 | 47 | private List<RuleChainConnectionInfo> ruleChainConnections; |
40 | 48 | |
41 | 49 | public void addConnectionInfo(int fromIndex, int toIndex, String type) { | ... | ... |
... | ... | @@ -17,6 +17,8 @@ package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.annotation.JsonIgnore; |
19 | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | +import io.swagger.annotations.ApiModel; | |
21 | +import io.swagger.annotations.ApiModelProperty; | |
20 | 22 | import lombok.Data; |
21 | 23 | import lombok.EqualsAndHashCode; |
22 | 24 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -25,6 +27,7 @@ import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; |
25 | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
26 | 28 | import org.thingsboard.server.common.data.id.RuleNodeId; |
27 | 29 | |
30 | +@ApiModel | |
28 | 31 | @Data |
29 | 32 | @EqualsAndHashCode(callSuper = true) |
30 | 33 | @Slf4j |
... | ... | @@ -32,10 +35,15 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl |
32 | 35 | |
33 | 36 | private static final long serialVersionUID = -5656679015121235465L; |
34 | 37 | |
38 | + @ApiModelProperty(position = 3, value = "JSON object with the Rule Chain Id. ", readOnly = true) | |
35 | 39 | private RuleChainId ruleChainId; |
40 | + @ApiModelProperty(position = 4, value = "Full Java Class Name of the rule node implementation. ", example = "com.mycompany.iot.rule.engine.ProcessingNode") | |
36 | 41 | private String type; |
42 | + @ApiModelProperty(position = 5, value = "User defined name of the rule node. Used on UI and for logging. ", example = "Process sensor reading") | |
37 | 43 | private String name; |
44 | + @ApiModelProperty(position = 6, value = "Enable/disable debug. ", example = "false") | |
38 | 45 | private boolean debugMode; |
46 | + @ApiModelProperty(position = 7, value = "JSON with the rule node configuration. Structure depends on the rule node implementation.", dataType = "com.fasterxml.jackson.databind.JsonNode") | |
39 | 47 | private transient JsonNode configuration; |
40 | 48 | @JsonIgnore |
41 | 49 | private byte[] configurationBytes; |
... | ... | @@ -75,4 +83,25 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl |
75 | 83 | setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes); |
76 | 84 | } |
77 | 85 | |
86 | + @ApiModelProperty(position = 1, value = "JSON object with the Rule Node Id. " + | |
87 | + "Specify this field to update the Rule Node. " + | |
88 | + "Referencing non-existing Rule Node Id will cause error. " + | |
89 | + "Omit this field to create new rule node." ) | |
90 | + @Override | |
91 | + public RuleNodeId getId() { | |
92 | + return super.getId(); | |
93 | + } | |
94 | + | |
95 | + @ApiModelProperty(position = 2, value = "Timestamp of the rule node creation, in milliseconds", example = "1609459200000", readOnly = true) | |
96 | + @Override | |
97 | + public long getCreatedTime() { | |
98 | + return super.getCreatedTime(); | |
99 | + } | |
100 | + | |
101 | + @ApiModelProperty(position = 8, value = "Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.", dataType = "com.fasterxml.jackson.databind.JsonNode") | |
102 | + @Override | |
103 | + public JsonNode getAdditionalInfo() { | |
104 | + return super.getAdditionalInfo(); | |
105 | + } | |
106 | + | |
78 | 107 | } | ... | ... |