Commit 9ae508be86efd0a46a43822ebae1b961a76e66c5
Merge branch '20230411' into 'master_dev'
fix: 产品模块,传输协议那里可用脚本需要返回系统自带的脚本 See merge request yunteng/thingskit!172
Showing
62 changed files
with
2987 additions
and
438 deletions
... | ... | @@ -57,8 +57,11 @@ import org.thingsboard.server.common.data.rule.RuleNode; |
57 | 57 | import org.thingsboard.server.common.data.widget.WidgetTypeDetails; |
58 | 58 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
59 | 59 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
60 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
60 | 61 | import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; |
61 | 62 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
63 | +import org.thingsboard.server.common.data.yunteng.dto.PublicCustomerDTO; | |
64 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
62 | 65 | import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; |
63 | 66 | import org.thingsboard.server.dao.asset.AssetService; |
64 | 67 | import org.thingsboard.server.dao.attributes.AttributesService; |
... | ... | @@ -243,6 +246,10 @@ public abstract class BaseController { |
243 | 246 | @Getter |
244 | 247 | protected boolean edgesEnabled; |
245 | 248 | |
249 | + //thingskit | |
250 | + @Autowired | |
251 | + private CacheUtils cacheUtils; | |
252 | + | |
246 | 253 | @ExceptionHandler(ThingsboardException.class) |
247 | 254 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { |
248 | 255 | errorResponseHandler.handle(ex, response); |
... | ... | @@ -888,7 +895,6 @@ public abstract class BaseController { |
888 | 895 | * 构建设备配置的配置数据 |
889 | 896 | * @param transportType 产品的通信协议 |
890 | 897 | * @param deviceProfileData 空的设备配置数据 |
891 | - * @return | |
892 | 898 | */ |
893 | 899 | protected DeviceProfileData buildDeviceProfileData(String transportType,DeviceProfileData deviceProfileData) { |
894 | 900 | if(null == deviceProfileData){ |
... | ... | @@ -949,4 +955,27 @@ public abstract class BaseController { |
949 | 955 | getTenantId(), savedDeviceProfile.getId(), EdgeEventActionType.UPDATED); |
950 | 956 | return savedDeviceProfile; |
951 | 957 | } |
958 | + | |
959 | + /** | |
960 | + * 获取租户的公共ID并设置缓存 | |
961 | + * @param tenantId 租户ID | |
962 | + * @return 公共ID | |
963 | + */ | |
964 | + private String findPublicCustomerId(TenantId tenantId){ | |
965 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
966 | + String cacheKey = | |
967 | + FastIotConstants.CacheConfigKey.PUBLIC_ID + tenantId.getId().toString(); | |
968 | + Optional<String> publicId = cacheUtils.get(cacheKey); | |
969 | + return publicId.orElseGet( | |
970 | + () -> Optional.ofNullable(customerService.findOrCreatePublicCustomer(tenantId)). | |
971 | + map(customer -> customer.getId().getId().toString()).orElse(null)); | |
972 | + } | |
973 | + | |
974 | + protected void setPublicCustomerIdToCache(PublicCustomerDTO dto) throws ThingsboardException { | |
975 | + String publicCustomerId = findPublicCustomerId(getTenantId()); | |
976 | + if (Objects.equals(dto.getViewType(), ViewType.PUBLIC_VIEW) | |
977 | + && !StringUtils.isEmpty(publicCustomerId)) { | |
978 | + dto.setPublicId(publicCustomerId); | |
979 | + } | |
980 | + } | |
952 | 981 | } | ... | ... |
... | ... | @@ -8,10 +8,13 @@ import org.springframework.http.ResponseEntity; |
8 | 8 | import org.springframework.security.access.prepost.PreAuthorize; |
9 | 9 | import org.springframework.validation.annotation.Validated; |
10 | 10 | import org.springframework.web.bind.annotation.*; |
11 | +import org.thingsboard.server.common.data.Customer; | |
11 | 12 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
12 | 13 | import org.thingsboard.server.common.data.yunteng.common.AddGroup; |
13 | 14 | import org.thingsboard.server.common.data.yunteng.common.DeleteGroup; |
14 | 15 | import org.thingsboard.server.common.data.yunteng.common.UpdateGroup; |
16 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
17 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
15 | 18 | import org.thingsboard.server.common.data.yunteng.dto.ConfigurationCenterDTO; |
16 | 19 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
17 | 20 | import org.thingsboard.server.common.data.yunteng.dto.request.ConfigurationContentInfoDTO; |
... | ... | @@ -31,7 +34,7 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant. |
31 | 34 | @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") |
32 | 35 | public class TkConfigurationCenterController extends BaseController { |
33 | 36 | |
34 | - private final TkConfigurationCenterService ytConfigurationCenterService; | |
37 | + private final TkConfigurationCenterService tkConfigurationCenterService; | |
35 | 38 | |
36 | 39 | @GetMapping(params = {PAGE_SIZE, PAGE}) |
37 | 40 | @ApiOperation("分页") |
... | ... | @@ -62,8 +65,15 @@ public class TkConfigurationCenterController extends BaseController { |
62 | 65 | if (null != orderType) { |
63 | 66 | queryMap.put(ORDER_TYPE, orderType.name()); |
64 | 67 | } |
65 | - queryMap.put("userId",getCurrentUser().getCurrentUserId()); | |
66 | - return ytConfigurationCenterService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
68 | + queryMap.put("userId", getCurrentUser().getCurrentUserId()); | |
69 | + TkPageData<ConfigurationCenterDTO> pageData = | |
70 | + tkConfigurationCenterService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
71 | + if (!pageData.getItems().isEmpty()) { | |
72 | + for (ConfigurationCenterDTO dto : pageData.getItems()) { | |
73 | + setPublicCustomerIdToCache(dto); | |
74 | + } | |
75 | + } | |
76 | + return pageData; | |
67 | 77 | } |
68 | 78 | |
69 | 79 | @PostMapping |
... | ... | @@ -75,7 +85,7 @@ public class TkConfigurationCenterController extends BaseController { |
75 | 85 | throws ThingsboardException { |
76 | 86 | configurationCenterDTO.setTenantId(getCurrentUser().getCurrentTenantId()); |
77 | 87 | return ResponseEntity.ok( |
78 | - ytConfigurationCenterService.saveConfiguration(configurationCenterDTO)); | |
88 | + tkConfigurationCenterService.saveConfiguration(configurationCenterDTO)); | |
79 | 89 | } |
80 | 90 | |
81 | 91 | @PutMapping |
... | ... | @@ -87,7 +97,7 @@ public class TkConfigurationCenterController extends BaseController { |
87 | 97 | throws ThingsboardException { |
88 | 98 | configurationCenterDTO.setTenantId(getCurrentUser().getCurrentTenantId()); |
89 | 99 | return ResponseEntity.ok( |
90 | - ytConfigurationCenterService.updateConfiguration(configurationCenterDTO)); | |
100 | + tkConfigurationCenterService.updateConfiguration(configurationCenterDTO)); | |
91 | 101 | } |
92 | 102 | |
93 | 103 | @DeleteMapping |
... | ... | @@ -98,17 +108,34 @@ public class TkConfigurationCenterController extends BaseController { |
98 | 108 | @Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) |
99 | 109 | throws ThingsboardException { |
100 | 110 | deleteDTO.setTenantId(getCurrentUser().getCurrentTenantId()); |
101 | - return ResponseEntity.ok(ytConfigurationCenterService.deleteConfigurationCenter(deleteDTO)); | |
111 | + return ResponseEntity.ok(tkConfigurationCenterService.deleteConfigurationCenter(deleteDTO)); | |
102 | 112 | } |
103 | 113 | |
104 | 114 | @GetMapping("/get_configuration_info/{id}") |
105 | 115 | @ApiOperation("获取组态信息") |
106 | 116 | @PreAuthorize( |
107 | - "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:configuration:center:get_configuration_info:design','api:yt:configuration:center:get_configuration_info:preview'})") | |
117 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:configuration:center:get_configuration_info:design'" | |
118 | + + ",'api:yt:configuration:center:get_configuration_info:preview'})") | |
108 | 119 | public ResponseEntity<ConfigurationContentInfoDTO> getConfigurationInfos( |
109 | 120 | @PathVariable("id") String id) throws ThingsboardException { |
110 | 121 | return ResponseEntity.ok( |
111 | - ytConfigurationCenterService.getConfigurationInfos( | |
122 | + tkConfigurationCenterService.getConfigurationInfos( | |
112 | 123 | id, getCurrentUser().getCurrentTenantId())); |
113 | 124 | } |
125 | + | |
126 | + @PostMapping("share/{id}") | |
127 | + @ApiOperation("分享") | |
128 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:configuration:center:share'})") | |
129 | + public ResponseEntity<Boolean> share( | |
130 | + @PathVariable("id") String id, | |
131 | + @RequestParam(value = "accessCredentials", required = false) String accessCredentials, | |
132 | + @RequestParam(value = "isShare") boolean isShare) | |
133 | + throws ThingsboardException { | |
134 | + if (StringUtils.isEmpty(id)) { | |
135 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
136 | + } | |
137 | + return ResponseEntity.ok( | |
138 | + tkConfigurationCenterService.shareOrMonopolyConfigurationCenter( | |
139 | + isShare, id, accessCredentials, getCurrentUser().getCurrentTenantId())); | |
140 | + } | |
114 | 141 | } | ... | ... |
... | ... | @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiOperation; |
5 | 5 | import lombok.RequiredArgsConstructor; |
6 | 6 | import org.apache.commons.lang3.StringUtils; |
7 | 7 | import org.quartz.SchedulerException; |
8 | +import org.springframework.http.ResponseEntity; | |
8 | 9 | import org.springframework.security.access.prepost.PreAuthorize; |
9 | 10 | import org.springframework.validation.annotation.Validated; |
10 | 11 | import org.springframework.web.bind.annotation.*; |
... | ... | @@ -23,9 +24,7 @@ import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
23 | 24 | import org.thingsboard.server.controller.BaseController; |
24 | 25 | import org.thingsboard.server.dao.yunteng.service.TkDataBoardService; |
25 | 26 | |
26 | -import java.util.HashMap; | |
27 | -import java.util.List; | |
28 | -import java.util.Map; | |
27 | +import java.util.*; | |
29 | 28 | |
30 | 29 | import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*; |
31 | 30 | |
... | ... | @@ -35,7 +34,7 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant. |
35 | 34 | @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") |
36 | 35 | @Api(tags = {"数据看板"}) |
37 | 36 | public class TkDataBoardController extends BaseController { |
38 | - private final TkDataBoardService ytDataBoardService; | |
37 | + private final TkDataBoardService tkDataBoardService; | |
39 | 38 | |
40 | 39 | @GetMapping(params = {PAGE_SIZE, PAGE}) |
41 | 40 | @ApiOperation("分页查询") |
... | ... | @@ -59,22 +58,31 @@ public class TkDataBoardController extends BaseController { |
59 | 58 | if (StringUtils.isNotBlank(name)) { |
60 | 59 | queryMap.put("name", name); |
61 | 60 | } |
62 | - queryMap.put("userId",getCurrentUser().getCurrentUserId()); | |
63 | - return ytDataBoardService.dataBoardPage(queryMap, getCurrentUser().isTenantAdmin()); | |
61 | + queryMap.put("userId", getCurrentUser().getCurrentUserId()); | |
62 | + TkPageData<DataBoardDTO> pageData = | |
63 | + tkDataBoardService.dataBoardPage(queryMap, getCurrentUser().isTenantAdmin()); | |
64 | + if(!pageData.getItems().isEmpty()){ | |
65 | + for (DataBoardDTO dto : pageData.getItems()) { | |
66 | + setPublicCustomerIdToCache(dto); | |
67 | + } | |
68 | + } | |
69 | + return pageData; | |
64 | 70 | } |
65 | 71 | |
66 | 72 | @DeleteMapping |
67 | 73 | @ApiOperation(value = "删除数据看板") |
68 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:delete'})") | |
74 | + @PreAuthorize( | |
75 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:delete'})") | |
69 | 76 | public ResponseResult<Boolean> deleteDataBoard( |
70 | 77 | @Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) throws ThingsboardException { |
71 | 78 | deleteDTO.setTenantId(getCurrentUser().getCurrentTenantId()); |
72 | - return ResponseResult.success(ytDataBoardService.deleteDataBoard(deleteDTO)); | |
79 | + return ResponseResult.success(tkDataBoardService.deleteDataBoard(deleteDTO)); | |
73 | 80 | } |
74 | 81 | |
75 | 82 | @PostMapping("/add") |
76 | 83 | @ApiOperation(value = "新增数据看板") |
77 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:add:post'})") | |
84 | + @PreAuthorize( | |
85 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:add:post'})") | |
78 | 86 | public ResponseResult<DataBoardDTO> save( |
79 | 87 | @RequestBody @Validated(AddGroup.class) DataBoardDTO dataBoard) |
80 | 88 | throws SchedulerException, ThingsboardException { |
... | ... | @@ -85,7 +93,8 @@ public class TkDataBoardController extends BaseController { |
85 | 93 | } |
86 | 94 | |
87 | 95 | @PostMapping("/update") |
88 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:update:update'})") | |
96 | + @PreAuthorize( | |
97 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:data_board:update:update'})") | |
89 | 98 | @ApiOperation(value = "编辑数据看板") |
90 | 99 | public ResponseResult<DataBoardDTO> update( |
91 | 100 | @RequestBody @Validated(UpdateGroup.class) DataBoardDTO dataBoard) |
... | ... | @@ -102,13 +111,29 @@ public class TkDataBoardController extends BaseController { |
102 | 111 | @PathVariable("boardId") String boardId, @RequestBody List<ComponentLayoutDTO> layoutDTOList) |
103 | 112 | throws ThingsboardException { |
104 | 113 | return ResponseResult.success( |
105 | - ytDataBoardService.saveComponentLayout( | |
114 | + tkDataBoardService.saveComponentLayout( | |
106 | 115 | layoutDTOList, boardId, getCurrentUser().getCurrentTenantId())); |
107 | 116 | } |
108 | 117 | |
118 | + @PostMapping("share/{id}") | |
119 | + @ApiOperation("分享") | |
120 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:data_board:share'})") | |
121 | + public ResponseEntity<Boolean> share( | |
122 | + @PathVariable("id") String id, | |
123 | + @RequestParam(value = "accessCredentials", required = false) String accessCredentials, | |
124 | + @RequestParam(value = "isShare") boolean isShare) | |
125 | + throws ThingsboardException { | |
126 | + if (StringUtils.isEmpty(id)) { | |
127 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
128 | + } | |
129 | + return ResponseEntity.ok( | |
130 | + tkDataBoardService.shareOrMonopolyDataBoard( | |
131 | + isShare, id, accessCredentials, getCurrentUser().getCurrentTenantId())); | |
132 | + } | |
133 | + | |
109 | 134 | private ResponseResult<DataBoardDTO> saveOrUpdate(DataBoardDTO dataBoard) |
110 | 135 | throws ThingsboardException { |
111 | 136 | dataBoard.setTenantId(getCurrentUser().getCurrentTenantId()); |
112 | - return ResponseResult.success(ytDataBoardService.saveOrUpdateDataBoard(dataBoard)); | |
137 | + return ResponseResult.success(tkDataBoardService.saveOrUpdateDataBoard(dataBoard)); | |
113 | 138 | } |
114 | 139 | } | ... | ... |
... | ... | @@ -12,6 +12,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; |
12 | 12 | import org.thingsboard.server.common.data.yunteng.common.AddGroup; |
13 | 13 | import org.thingsboard.server.common.data.yunteng.common.DeleteGroup; |
14 | 14 | import org.thingsboard.server.common.data.yunteng.common.UpdateGroup; |
15 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
16 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
15 | 17 | import org.thingsboard.server.common.data.yunteng.dto.TkDataViewDTO; |
16 | 18 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
17 | 19 | import org.thingsboard.server.common.data.yunteng.dto.request.TkDataViewContentInfoDTO; |
... | ... | @@ -31,103 +33,125 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant. |
31 | 33 | @RequestMapping("/api/yt/data_view") |
32 | 34 | @RequiredArgsConstructor |
33 | 35 | @Api(tags = "大屏设计器") |
34 | -@PreAuthorize("@check.checkPermissions({},{})") | |
36 | +@PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") | |
35 | 37 | public class TkDataViewController extends BaseController { |
36 | 38 | |
37 | - private final TkDataViewService tkDataViewService; | |
39 | + private final TkDataViewService tkDataViewService; | |
38 | 40 | |
39 | - @GetMapping(params = {PAGE_SIZE, PAGE}) | |
40 | - @ApiOperation("分页") | |
41 | - public TkPageData<TkDataViewDTO> page( | |
42 | - @RequestParam(PAGE_SIZE) int pageSize, | |
43 | - @RequestParam(PAGE) int page, | |
44 | - @RequestParam(value = "name", required = false) String name, | |
45 | - @RequestParam(value = "state", required = false) String state, | |
46 | - @RequestParam(value = "organizationId", required = false) String organizationId, | |
47 | - @RequestParam(value = ORDER_FILED, required = false) String orderBy, | |
48 | - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) | |
49 | - throws ThingsboardException { | |
41 | + @GetMapping(params = {PAGE_SIZE, PAGE}) | |
42 | + @ApiOperation("分页") | |
43 | + public TkPageData<TkDataViewDTO> page( | |
44 | + @RequestParam(PAGE_SIZE) int pageSize, | |
45 | + @RequestParam(PAGE) int page, | |
46 | + @RequestParam(value = "name", required = false) String name, | |
47 | + @RequestParam(value = "state", required = false) String state, | |
48 | + @RequestParam(value = "organizationId", required = false) String organizationId, | |
49 | + @RequestParam(value = ORDER_FILED, required = false) String orderBy, | |
50 | + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) | |
51 | + throws ThingsboardException { | |
50 | 52 | |
51 | - HashMap<String, Object> queryMap = new HashMap<>(); | |
52 | - queryMap.put(PAGE_SIZE, pageSize); | |
53 | - queryMap.put(PAGE, page); | |
54 | - queryMap.put(ORDER_FILED, orderBy); | |
55 | - queryMap.put("tenantId", getCurrentUser().getCurrentTenantId()); | |
56 | - if (StringUtils.isNotBlank(name)) { | |
57 | - queryMap.put("name", name); | |
58 | - } | |
59 | - if (StringUtils.isNotBlank(organizationId)) { | |
60 | - queryMap.put("organizationId", organizationId); | |
61 | - } | |
62 | - if (StringUtils.isNotBlank(state)) { | |
63 | - queryMap.put("state", state); | |
64 | - } | |
65 | - if (null != orderType) { | |
66 | - queryMap.put(ORDER_TYPE, orderType.name()); | |
67 | - } | |
68 | - queryMap.put("userId", getCurrentUser().getCurrentUserId()); | |
69 | - return tkDataViewService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
53 | + HashMap<String, Object> queryMap = new HashMap<>(); | |
54 | + queryMap.put(PAGE_SIZE, pageSize); | |
55 | + queryMap.put(PAGE, page); | |
56 | + queryMap.put(ORDER_FILED, orderBy); | |
57 | + queryMap.put("tenantId", getCurrentUser().getCurrentTenantId()); | |
58 | + if (StringUtils.isNotBlank(name)) { | |
59 | + queryMap.put("name", name); | |
70 | 60 | } |
71 | - | |
72 | - @PostMapping | |
73 | - @ApiOperation("新增") | |
74 | - @PreAuthorize( | |
75 | - "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:post'})") | |
76 | - public ResponseEntity<TkDataViewDTO> save( | |
77 | - @Validated({AddGroup.class}) @RequestBody TkDataViewDTO TkDataViewDTO) | |
78 | - throws ThingsboardException { | |
79 | - TkDataViewDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
80 | - return ResponseEntity.ok( | |
81 | - tkDataViewService.saveDataView(TkDataViewDTO)); | |
61 | + if (StringUtils.isNotBlank(organizationId)) { | |
62 | + queryMap.put("organizationId", organizationId); | |
82 | 63 | } |
83 | - | |
84 | - @PutMapping | |
85 | - @ApiOperation("修改") | |
86 | - @PreAuthorize( | |
87 | - "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:update'})") | |
88 | - public ResponseEntity<TkDataViewDTO> update( | |
89 | - @Validated({UpdateGroup.class}) @RequestBody TkDataViewDTO TkDataViewDTO) | |
90 | - throws ThingsboardException { | |
91 | - TkDataViewDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
92 | - return ResponseEntity.ok( | |
93 | - tkDataViewService.updateDataView(TkDataViewDTO)); | |
64 | + if (StringUtils.isNotBlank(state)) { | |
65 | + queryMap.put("state", state); | |
94 | 66 | } |
95 | - | |
96 | - @DeleteMapping | |
97 | - @ApiOperation("删除") | |
98 | - @PreAuthorize( | |
99 | - "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:delete'})") | |
100 | - public ResponseEntity<Boolean> delete( | |
101 | - @Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) | |
102 | - throws ThingsboardException { | |
103 | - deleteDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
104 | - return ResponseEntity.ok(tkDataViewService.deleteDataView(deleteDTO)); | |
67 | + if (null != orderType) { | |
68 | + queryMap.put(ORDER_TYPE, orderType.name()); | |
105 | 69 | } |
106 | - | |
107 | - @GetMapping("/get_configuration_info/{id}") | |
108 | - @ApiOperation("获取大屏信息") | |
109 | - @PreAuthorize( | |
110 | - "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:get_dataview_info:design','api:yt:dataview:center:get_dataview_info:preview'})") | |
111 | - public ResponseEntity<TkDataViewContentInfoDTO> getConfigurationInfos( | |
112 | - @PathVariable("id") String id) throws ThingsboardException { | |
113 | - return ResponseEntity.ok( | |
114 | - tkDataViewService.getDataViewInfos( | |
115 | - id, getCurrentUser().getCurrentTenantId())); | |
70 | + queryMap.put("userId", getCurrentUser().getCurrentUserId()); | |
71 | + TkPageData<TkDataViewDTO> pageData = tkDataViewService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
72 | + if(!pageData.getItems().isEmpty()){ | |
73 | + for(TkDataViewDTO dto : pageData.getItems()){ | |
74 | + setPublicCustomerIdToCache(dto); | |
75 | + } | |
116 | 76 | } |
77 | + return pageData; | |
78 | + } | |
117 | 79 | |
118 | - @GetMapping("/publish/{id}") | |
119 | - @ApiOperation("发布") | |
120 | - @PreAuthorize("@check.checkPermissions({},{})") | |
121 | - public ResponseEntity<Boolean> publishDataView(@PathVariable("id") String id) throws ThingsboardException { | |
122 | - return ResponseEntity.ok( | |
123 | - tkDataViewService.publishDataView(id, getCurrentUser().getCurrentTenantId())); | |
124 | - } | |
80 | + @PostMapping | |
81 | + @ApiOperation("新增") | |
82 | + @PreAuthorize( | |
83 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:post'})") | |
84 | + public ResponseEntity<TkDataViewDTO> save( | |
85 | + @Validated({AddGroup.class}) @RequestBody TkDataViewDTO TkDataViewDTO) | |
86 | + throws ThingsboardException { | |
87 | + TkDataViewDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
88 | + return ResponseEntity.ok(tkDataViewService.saveDataView(TkDataViewDTO)); | |
89 | + } | |
90 | + | |
91 | + @PutMapping | |
92 | + @ApiOperation("修改") | |
93 | + @PreAuthorize( | |
94 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:update'})") | |
95 | + public ResponseEntity<TkDataViewDTO> update( | |
96 | + @Validated({UpdateGroup.class}) @RequestBody TkDataViewDTO TkDataViewDTO) | |
97 | + throws ThingsboardException { | |
98 | + TkDataViewDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
99 | + return ResponseEntity.ok(tkDataViewService.updateDataView(TkDataViewDTO)); | |
100 | + } | |
101 | + | |
102 | + @DeleteMapping | |
103 | + @ApiOperation("删除") | |
104 | + @PreAuthorize( | |
105 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:delete'})") | |
106 | + public ResponseEntity<Boolean> delete( | |
107 | + @Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) | |
108 | + throws ThingsboardException { | |
109 | + deleteDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
110 | + return ResponseEntity.ok(tkDataViewService.deleteDataView(deleteDTO)); | |
111 | + } | |
112 | + | |
113 | + @GetMapping("/get_configuration_info/{id}") | |
114 | + @ApiOperation("获取大屏信息") | |
115 | + @PreAuthorize( | |
116 | + "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:dataview:center:get_dataview_info:design'," | |
117 | + + "'api:yt:dataview:center:get_dataview_info:preview'})") | |
118 | + public ResponseEntity<TkDataViewContentInfoDTO> getConfigurationInfos( | |
119 | + @PathVariable("id") String id) throws ThingsboardException { | |
120 | + return ResponseEntity.ok( | |
121 | + tkDataViewService.getDataViewInfos(id, getCurrentUser().getCurrentTenantId())); | |
122 | + } | |
123 | + | |
124 | + @GetMapping("/publish/{id}") | |
125 | + @ApiOperation("发布") | |
126 | + @PreAuthorize("@check.checkPermissions({},{})") | |
127 | + public ResponseEntity<Boolean> publishDataView(@PathVariable("id") String id) | |
128 | + throws ThingsboardException { | |
129 | + return ResponseEntity.ok( | |
130 | + tkDataViewService.publishDataView(id, getCurrentUser().getCurrentTenantId())); | |
131 | + } | |
132 | + | |
133 | + @GetMapping("/cancel_publish/{id}") | |
134 | + @ApiOperation("取消发布") | |
135 | + @PreAuthorize("@check.checkPermissions({},{})") | |
136 | + public ResponseEntity<Boolean> cancelPublishDataView(@PathVariable("id") String id) | |
137 | + throws ThingsboardException { | |
138 | + return ResponseEntity.ok( | |
139 | + tkDataViewService.cancelPublishDataView(id, getCurrentUser().getCurrentTenantId())); | |
140 | + } | |
125 | 141 | |
126 | - @GetMapping("/cancel_publish/{id}") | |
127 | - @ApiOperation("取消发布") | |
128 | - @PreAuthorize("@check.checkPermissions({},{})") | |
129 | - public ResponseEntity<Boolean> cancelPublishDataView(@PathVariable("id") String id) throws ThingsboardException { | |
130 | - return ResponseEntity.ok( | |
131 | - tkDataViewService.cancelPublishDataView(id, getCurrentUser().getCurrentTenantId())); | |
142 | + @PostMapping("share/{id}") | |
143 | + @ApiOperation("分享") | |
144 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:dataview:center:share'})") | |
145 | + public ResponseEntity<Boolean> share( | |
146 | + @PathVariable("id") String id, | |
147 | + @RequestParam(value = "accessCredentials", required = false) String accessCredentials, | |
148 | + @RequestParam(value = "isShare") boolean isShare) | |
149 | + throws ThingsboardException { | |
150 | + if (StringUtils.isEmpty(id)) { | |
151 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
132 | 152 | } |
153 | + return ResponseEntity.ok( | |
154 | + tkDataViewService.shareOrMonopolyDataViewCenter( | |
155 | + isShare, id, accessCredentials, getCurrentUser().getCurrentTenantId())); | |
156 | + } | |
133 | 157 | } | ... | ... |
... | ... | @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio |
30 | 30 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
31 | 31 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
32 | 32 | import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; |
33 | +import org.thingsboard.server.common.data.yunteng.dto.TkDeviceRpcDTO; | |
33 | 34 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
34 | 35 | import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; |
35 | 36 | import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; |
... | ... | @@ -154,9 +155,9 @@ public class TkDeviceScriptController extends BaseController { |
154 | 155 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") |
155 | 156 | @GetMapping("/me/list") |
156 | 157 | @ApiOperation("选项列表") |
157 | - public ResponseEntity listDeviceScript() throws ThingsboardException { | |
158 | + public ResponseEntity listDeviceScript(@RequestParam(value = "scriptType", required = false) TkScriptFunctionType scriptType) throws ThingsboardException { | |
158 | 159 | List<TkDeviceScriptDTO> results = |
159 | - scriptService.findDeviceScript(getCurrentUser().getCurrentTenantId()); | |
160 | + scriptService.findDeviceScript(getCurrentUser().getCurrentTenantId(),scriptType); | |
160 | 161 | return ResponseEntity.ok(results); |
161 | 162 | } |
162 | 163 | |
... | ... | @@ -217,6 +218,17 @@ public class TkDeviceScriptController extends BaseController { |
217 | 218 | } |
218 | 219 | } |
219 | 220 | |
221 | + | |
222 | + | |
223 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | |
224 | + @PostMapping("/modbus") | |
225 | + @ApiOperation("生成Modbus指令") | |
226 | + public ResponseEntity<String> modbus(@RequestBody TkDeviceRpcDTO inputParams) | |
227 | + throws ThingsboardException { | |
228 | + return ResponseEntity.ok(scriptService.modbus(inputParams)); | |
229 | + } | |
230 | + | |
231 | + | |
220 | 232 | /** |
221 | 233 | * 构造调用TBDeviceProfile需要的参数 |
222 | 234 | * | ... | ... |
application/src/main/java/org/thingsboard/server/controller/yunteng/TkShareViewController.java
0 → 100644
1 | +package org.thingsboard.server.controller.yunteng; | |
2 | + | |
3 | +import io.swagger.annotations.Api; | |
4 | +import io.swagger.annotations.ApiOperation; | |
5 | +import lombok.RequiredArgsConstructor; | |
6 | +import org.springframework.web.bind.annotation.*; | |
7 | +import org.thingsboard.server.common.data.StringUtils; | |
8 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
9 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
10 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
11 | +import org.thingsboard.server.common.data.yunteng.enums.ShareViewType; | |
12 | +import org.thingsboard.server.common.data.yunteng.utils.tools.ResponseResult; | |
13 | +import org.thingsboard.server.controller.BaseController; | |
14 | +import org.thingsboard.server.dao.yunteng.service.TkShareViewService; | |
15 | + | |
16 | +@RestController | |
17 | +@RequiredArgsConstructor | |
18 | +@RequestMapping("api/yt/share") | |
19 | +@Api(tags = {"分享的视图"}) | |
20 | +public class TkShareViewController extends BaseController { | |
21 | + private final TkShareViewService tkShareViewService; | |
22 | + | |
23 | + @GetMapping("/check/{type}/{viewId}") | |
24 | + @ApiOperation(value = "检查分享视图是否需要访问凭证") | |
25 | + public ResponseResult<Boolean> checkPublicViewNeedCredentials( | |
26 | + @PathVariable("type") ShareViewType type, @PathVariable("viewId") String viewId) | |
27 | + throws ThingsboardException { | |
28 | + if (StringUtils.isEmpty(viewId)) { | |
29 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
30 | + } | |
31 | + return ResponseResult.success( | |
32 | + tkShareViewService.checkPublicViewNeedCredentials( | |
33 | + type, viewId, getCurrentUser().getCurrentTenantId())); | |
34 | + } | |
35 | + | |
36 | + @GetMapping("/{share_view_type}/share_data/{id}") | |
37 | + @ApiOperation(value = "查看分享的数据") | |
38 | + public ResponseResult<Object> viewDataComponentsByBoardId( | |
39 | + @PathVariable("id") String id, | |
40 | + @PathVariable("share_view_type") ShareViewType shareViewType, | |
41 | + @RequestParam(value = "accessCredentials",required = false) String accessCredentials) | |
42 | + throws ThingsboardException { | |
43 | + if (StringUtils.isEmpty(id) || null == shareViewType) { | |
44 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
45 | + } | |
46 | + return ResponseResult.success( | |
47 | + tkShareViewService.viewShareDataById( | |
48 | + shareViewType, id, accessCredentials, getCurrentUser().getCurrentTenantId())); | |
49 | + } | |
50 | +} | ... | ... |
application/src/main/java/org/thingsboard/server/controller/yunteng/TkTaskCenterController.java
0 → 100644
1 | +package org.thingsboard.server.controller.yunteng; | |
2 | + | |
3 | +import io.swagger.annotations.Api; | |
4 | +import io.swagger.annotations.ApiOperation; | |
5 | +import lombok.RequiredArgsConstructor; | |
6 | +import org.apache.commons.lang3.StringUtils; | |
7 | +import org.quartz.SchedulerException; | |
8 | +import org.springframework.security.access.prepost.PreAuthorize; | |
9 | +import org.springframework.validation.annotation.Validated; | |
10 | +import org.springframework.web.bind.annotation.*; | |
11 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | |
12 | +import org.thingsboard.server.common.data.yunteng.common.AddGroup; | |
13 | +import org.thingsboard.server.common.data.yunteng.common.UpdateGroup; | |
14 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
15 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
16 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
17 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
18 | +import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; | |
19 | +import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; | |
20 | +import org.thingsboard.server.common.data.yunteng.utils.tools.ResponseResult; | |
21 | +import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; | |
22 | +import org.thingsboard.server.controller.BaseController; | |
23 | +import org.thingsboard.server.dao.yunteng.service.TkTaskCenterService; | |
24 | + | |
25 | +import java.util.HashMap; | |
26 | + | |
27 | +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*; | |
28 | +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.ORDER_TYPE; | |
29 | + | |
30 | +@RestController | |
31 | +@RequestMapping("api/yt/task_center") | |
32 | +@Api(tags = {"任务中心"}) | |
33 | +@RequiredArgsConstructor | |
34 | +public class TkTaskCenterController extends BaseController { | |
35 | + private final TkTaskCenterService tkTaskCenterService; | |
36 | + | |
37 | + @GetMapping( | |
38 | + name = "page", | |
39 | + params = {PAGE_SIZE, PAGE}) | |
40 | + public TkPageData<TkTaskCenterDTO> pageDevice( | |
41 | + @RequestParam(PAGE_SIZE) int pageSize, | |
42 | + @RequestParam(PAGE) int page, | |
43 | + @RequestParam(value = "state", required = false) Integer state, | |
44 | + @RequestParam(value = "targetType", required = false) TargetTypeEnum targetType, | |
45 | + @RequestParam(value = ORDER_FILED, required = false) String orderBy, | |
46 | + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) | |
47 | + throws ThingsboardException { | |
48 | + HashMap<String, Object> queryMap = new HashMap<>(); | |
49 | + queryMap.put(PAGE_SIZE, pageSize); | |
50 | + queryMap.put(PAGE, page); | |
51 | + queryMap.put(ORDER_FILED, orderBy); | |
52 | + queryMap.put(ORDER_TYPE, orderType); | |
53 | + queryMap.put("state", state); | |
54 | + queryMap.put("targetType", targetType); | |
55 | + return tkTaskCenterService.taskCenterPage(queryMap, getCurrentUser().getCurrentTenantId()); | |
56 | + } | |
57 | + | |
58 | + @PostMapping("/add") | |
59 | + @ApiOperation(value = "新增任务中心") | |
60 | +// @PreAuthorize( | |
61 | +// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:add:post'})") | |
62 | + public ResponseResult<TkTaskCenterDTO> save( | |
63 | + @RequestBody @Validated(AddGroup.class) TkTaskCenterDTO taskCenter) | |
64 | + throws ThingsboardException, SchedulerException { | |
65 | + if (StringUtils.isNotEmpty(taskCenter.getId())) { | |
66 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
67 | + } | |
68 | + return ResponseResult.success(saveOrUpdate(taskCenter)); | |
69 | + } | |
70 | + | |
71 | + @PutMapping("/update") | |
72 | +// @PreAuthorize( | |
73 | +// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
74 | + @ApiOperation(value = "编辑任务中心") | |
75 | + public ResponseResult<TkTaskCenterDTO> update( | |
76 | + @RequestBody @Validated(UpdateGroup.class) TkTaskCenterDTO taskCenter) | |
77 | + throws ThingsboardException, SchedulerException { | |
78 | + if (StringUtils.isEmpty(taskCenter.getId())) { | |
79 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
80 | + } | |
81 | + return ResponseResult.success(saveOrUpdate(taskCenter)); | |
82 | + } | |
83 | + | |
84 | + @PutMapping("/{id}/update/{state}") | |
85 | +// @PreAuthorize( | |
86 | +// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
87 | + @ApiOperation(value = "更新状态") | |
88 | + public ResponseResult<Boolean> updateState( | |
89 | + @PathVariable("id") String id, @PathVariable("state") Integer state) | |
90 | + throws ThingsboardException, SchedulerException { | |
91 | + if (StringUtils.isEmpty(id) || null == state) { | |
92 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
93 | + } | |
94 | + return ResponseResult.success( | |
95 | + tkTaskCenterService.updateState(id, state, getCurrentUser().getCurrentTenantId())); | |
96 | + } | |
97 | + | |
98 | + @DeleteMapping | |
99 | +// @PreAuthorize( | |
100 | +// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:delete'})") | |
101 | + @ApiOperation(value = "删除任务中心") | |
102 | + public ResponseResult<Boolean> deleteTaskCenter(@RequestBody DeleteDTO deleteDTO) | |
103 | + throws ThingsboardException, SchedulerException { | |
104 | + deleteDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
105 | + return ResponseResult.success(tkTaskCenterService.deleteTaskCenter(deleteDTO)); | |
106 | + } | |
107 | + | |
108 | + @PutMapping("/{id}/cancel/{tbDeviceId}") | |
109 | +// @PreAuthorize( | |
110 | +// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:cancel'})") | |
111 | + @ApiOperation(value = "设备取消任务执行") | |
112 | + public ResponseResult<Boolean> cancelExecute( | |
113 | + @PathVariable("id") String taskId, @PathVariable("tbDeviceId") String tbDeviceId)throws ThingsboardException { | |
114 | + if(StringUtils.isEmpty(taskId) || StringUtils.isEmpty(tbDeviceId)){ | |
115 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
116 | + } | |
117 | + return ResponseResult.success( | |
118 | + tkTaskCenterService.cancelExecute( | |
119 | + taskId, tbDeviceId, getCurrentUser().getCurrentTenantId())); | |
120 | + } | |
121 | + | |
122 | + private TkTaskCenterDTO saveOrUpdate(TkTaskCenterDTO tkTaskCenterDTO) | |
123 | + throws ThingsboardException, SchedulerException { | |
124 | + tkTaskCenterDTO.setTenantId(getCurrentUser().getCurrentTenantId()); | |
125 | + return tkTaskCenterService.saveOrUpdateTaskCenter(tkTaskCenterDTO); | |
126 | + } | |
127 | +} | ... | ... |
1 | +package org.thingsboard.server.utils.yunteng; | |
2 | + | |
3 | +import com.fasterxml.jackson.databind.JsonNode; | |
4 | +import com.google.common.util.concurrent.FutureCallback; | |
5 | +import com.google.common.util.concurrent.Futures; | |
6 | +import com.google.common.util.concurrent.ListenableFuture; | |
7 | +import com.google.common.util.concurrent.MoreExecutors; | |
8 | +import lombok.RequiredArgsConstructor; | |
9 | +import lombok.extern.slf4j.Slf4j; | |
10 | +import org.checkerframework.checker.nullness.qual.Nullable; | |
11 | +import org.jetbrains.annotations.NotNull; | |
12 | +import org.springframework.beans.factory.annotation.Value; | |
13 | +import org.springframework.stereotype.Component; | |
14 | +import org.thingsboard.common.util.JacksonUtil; | |
15 | +import org.thingsboard.server.common.data.id.DeviceId; | |
16 | +import org.thingsboard.server.common.data.id.TenantId; | |
17 | +import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; | |
18 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
19 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
20 | +import org.thingsboard.server.common.data.yunteng.dto.task.TargetContentDTO; | |
21 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
22 | +import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; | |
23 | +import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | |
24 | +import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | |
25 | +import org.thingsboard.server.dao.yunteng.service.TkTaskCenterService; | |
26 | +import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; | |
27 | +import org.thingsboard.server.service.security.model.SecurityUser; | |
28 | +import java.util.*; | |
29 | + | |
30 | +@Component("rpcCommandTask") | |
31 | +@RequiredArgsConstructor | |
32 | +@Slf4j | |
33 | +public class RpcCommandTask { | |
34 | + @Value("${server.rest.server_side_rpc.default_timeout:10000}") | |
35 | + protected long defaultTimeout; | |
36 | + | |
37 | + @Value("${server.rest.server_side_rpc.min_timeout:5000}") | |
38 | + protected long minTimeout; | |
39 | + | |
40 | + private final TkTaskCenterService tkTaskCenterService; | |
41 | + private final TbCoreDeviceRpcService tbCoreDeviceRpcService; | |
42 | + private final TkDeviceService tkDeviceService; | |
43 | + public void process(String taskCenterId) { | |
44 | + // 通过任务中心ID查询执行命令及执行对象 | |
45 | + ListenableFuture<TkTaskCenterDTO> future = | |
46 | + tkTaskCenterService.getTaskCenterInfoById(taskCenterId); | |
47 | + Futures.addCallback( | |
48 | + future, | |
49 | + new FutureCallback<>() { | |
50 | + @Override | |
51 | + public void onSuccess(@Nullable TkTaskCenterDTO tkTaskCenterDTO) { | |
52 | + if (null != tkTaskCenterDTO) { | |
53 | + TargetTypeEnum targetType = tkTaskCenterDTO.getTargetType(); | |
54 | + TargetContentDTO targetContent = tkTaskCenterDTO.getExecuteTarget(); | |
55 | + JsonNode cmdJsonNode = tkTaskCenterDTO.getExecuteContent().getPushContent(); | |
56 | + SecurityUser securityUser = new SecurityUser(); | |
57 | + // send cmd | |
58 | + if (targetContent.getData() != null && null != cmdJsonNode) { | |
59 | + String tenantId = tkTaskCenterDTO.getTenantId(); | |
60 | + if (targetType.equals(TargetTypeEnum.DEVICES)) { | |
61 | + for (String deviceId : targetContent.getData()) { | |
62 | + sendRpcCommand(cmdJsonNode, tenantId, deviceId, securityUser); | |
63 | + } | |
64 | + } else { | |
65 | + sendRpcCommandByProducts(targetContent, cmdJsonNode, tenantId, securityUser); | |
66 | + } | |
67 | + } | |
68 | + } | |
69 | + } | |
70 | + | |
71 | + @Override | |
72 | + public void onFailure(@NotNull Throwable throwable) {} | |
73 | + }, | |
74 | + MoreExecutors.directExecutor()); | |
75 | + } | |
76 | + | |
77 | + private void sendRpcCommandByProducts( | |
78 | + TargetContentDTO targetContent, | |
79 | + JsonNode cmdJsonNode, | |
80 | + String tenantId, | |
81 | + SecurityUser securityUser) { | |
82 | + for (String deviceProfileId : targetContent.getData()) { | |
83 | + Futures.addCallback( | |
84 | + tkDeviceService.findDeviceListByDeviceProfileId(deviceProfileId, tenantId), | |
85 | + new FutureCallback<List<DeviceDTO>>() { | |
86 | + @Override | |
87 | + public void onSuccess(@Nullable List<DeviceDTO> deviceDTOS) { | |
88 | + if (null != deviceDTOS && !deviceDTOS.isEmpty()) { | |
89 | + for (DeviceDTO dto : deviceDTOS) { | |
90 | + Map<String, List<String>> map = targetContent.getCancelExecuteDevices(); | |
91 | + boolean needSendCommand = true; | |
92 | + if (null != map && !map.isEmpty() && !map.get(deviceProfileId).isEmpty()) { | |
93 | + for (String deviceId : map.get(deviceProfileId)) { | |
94 | + if (Objects.equals(deviceId, dto.getTbDeviceId())) { | |
95 | + needSendCommand = false; | |
96 | + break; | |
97 | + } | |
98 | + } | |
99 | + } | |
100 | + if (needSendCommand) { | |
101 | + sendRpcCommand(cmdJsonNode, tenantId, dto.getTbDeviceId(), securityUser); | |
102 | + } | |
103 | + } | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + @Override | |
108 | + public void onFailure(@NotNull Throwable throwable) {} | |
109 | + }, | |
110 | + MoreExecutors.directExecutor()); | |
111 | + } | |
112 | + } | |
113 | + | |
114 | + private void sendRpcCommand( | |
115 | + JsonNode cmdJsonNode, String tenantId, String originateId, SecurityUser securityUser) { | |
116 | + JsonNode rpcCommand = cmdJsonNode.get(FastIotConstants.RPC_COMMAND); | |
117 | + ToDeviceRpcRequestBody body = | |
118 | + new ToDeviceRpcRequestBody("methodThingskit", JacksonUtil.toString(rpcCommand)); | |
119 | + DeviceId deviceId = new DeviceId(UUID.fromString(originateId)); | |
120 | + ToDeviceRpcRequest request = | |
121 | + new ToDeviceRpcRequest( | |
122 | + UUID.randomUUID(), | |
123 | + new TenantId(UUID.fromString(tenantId)), | |
124 | + deviceId, | |
125 | + true, | |
126 | + System.currentTimeMillis() + Math.max(minTimeout, defaultTimeout), | |
127 | + body, | |
128 | + false, | |
129 | + null, | |
130 | + null); | |
131 | + tbCoreDeviceRpcService.processRestApiRpcRequest( | |
132 | + request, | |
133 | + fromDeviceRpcResponse -> { | |
134 | + log.trace("Device renamed RPC with id: [{}] ", request.getId()); | |
135 | + }, | |
136 | + securityUser); | |
137 | + } | |
138 | +} | ... | ... |
... | ... | @@ -431,18 +431,20 @@ caffeine: |
431 | 431 | timeToLiveInMinutes: "${CACHE_SPECS_EDGES_TTL:1440}" |
432 | 432 | maxSize: "${CACHE_SPECS_EDGES_MAX_SIZE:10000}" |
433 | 433 | yunTengIotCache: |
434 | - timeToLiveInMinutes: 1440 | |
435 | - maxSize: 10000 | |
434 | + timeToLiveInMinutes: "${CACHE_SPECS_YUN_TENG_IOT_CACHE_TTL:1440}" | |
435 | + maxSize: "${CACHE_SPECS_YUN_TENG_IOT_CACHE_MAX_SIZE:10000}" | |
436 | 436 | userPermissionFor: |
437 | - timeToLiveInMinutes: 1440 | |
438 | - maxSize: 10000 | |
437 | + timeToLiveInMinutes: "${CACHE_SPECS_USER_PERMISSION_FOR_TTL:1440}" | |
438 | + maxSize: "${CACHE_SPECS_USER_PERMISSION_FOR_MAX_SIZE:10000}" | |
439 | 439 | mobileLoginSmsCode: |
440 | - timeToLiveInMinutes: 2 | |
441 | - maxSize: 10000 | |
440 | + timeToLiveInMinutes: "${CACHE_SPECS_MOBILE_LOGIN_SMS_CODE_TTL:2}" | |
441 | + maxSize: "${CACHE_SPECS_MOBILE_LOGIN_SMS_CODE_MAX_SIZE:10000}" | |
442 | 442 | thingsArea: |
443 | - timeToLiveInMinutes: 1440 | |
444 | - maxSize: 500 | |
445 | - | |
443 | + timeToLiveInMinutes: "${CACHE_SPECS_THINGS_AREA_TTL:1440}" | |
444 | + maxSize: "${CACHE_SPECS_THINGS_AREA_MAX_SIZE:500}" | |
445 | + taskCenterInfos: | |
446 | + timeToLiveInMinutes: "${CACHE_SPECS_TASK_CENTER_TTL:1440}" | |
447 | + maxSize: "${CACHE_SPECS_TASK_CENTER_MAX_SIZE:10000}" | |
446 | 448 | redis: |
447 | 449 | # standalone or cluster |
448 | 450 | connection: |
... | ... | @@ -905,8 +907,8 @@ transport: |
905 | 907 | psm_activity_timer: "${LWM2M_PSM_ACTIVITY_TIMER:10000}" |
906 | 908 | paging_transmission_window: "${LWM2M_PAGING_TRANSMISSION_WINDOW:10000}" |
907 | 909 | network_config: # In this section you can specify custom parameters for LwM2M network configuration and expose the env variables to configure outside |
908 | -# - key: "PROTOCOL_STAGE_THREAD_COUNT" | |
909 | -# value: "${LWM2M_PROTOCOL_STAGE_THREAD_COUNT:4}" | |
910 | + # - key: "PROTOCOL_STAGE_THREAD_COUNT" | |
911 | + # value: "${LWM2M_PROTOCOL_STAGE_THREAD_COUNT:4}" | |
910 | 912 | snmp: |
911 | 913 | enabled: "${SNMP_ENABLED:true}" |
912 | 914 | response_processing: |
... | ... | @@ -989,9 +991,9 @@ queue: |
989 | 991 | tb_ota_package: |
990 | 992 | - key: max.poll.records |
991 | 993 | value: "${TB_QUEUE_KAFKA_OTA_MAX_POLL_RECORDS:10}" |
992 | -# tb_rule_engine.sq: | |
993 | -# - key: max.poll.records | |
994 | -# value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}" | |
994 | + # tb_rule_engine.sq: | |
995 | + # - key: max.poll.records | |
996 | + # value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}" | |
995 | 997 | other: # In this section you can specify custom parameters for Kafka consumer/producer and expose the env variables to configure outside |
996 | 998 | - key: "request.timeout.ms" # refer to https://docs.confluent.io/platform/current/installation/configuration/producer-configs.html#producerconfigs_request.timeout.ms |
997 | 999 | value: "${TB_QUEUE_KAFKA_REQUEST_TIMEOUT_MS:30000}" # (30 seconds) |
... | ... | @@ -1193,14 +1195,14 @@ file: |
1193 | 1195 | staticUrl: /static/files/** #oss静态访问路径 只有type = local需要 |
1194 | 1196 | randomFileName: ${file.storage.randomFileName} |
1195 | 1197 | minio: |
1196 | - minioUrl: ${MINIO_URL:https://dev.thingskit.com:9000} #minio储存地址 | |
1197 | - minioName: ${MINIO_NAME:test} #minio账户 | |
1198 | - minioPass: ${MINIO_PWD:test} #minio访问密码 | |
1199 | - bucketName: yunteng #minio储存桶名称 | |
1198 | + minioUrl: ${MINIO_URL:http://localhost:9000} #minio储存地址 | |
1199 | + minioName: ${MINIO_NAME:thingskit} #minio账户 | |
1200 | + minioPass: ${MINIO_PWD:thingskit} #minio访问密码 | |
1201 | + bucketName: yunteng #minio储存桶名称 | |
1200 | 1202 | randomFileName: ${file.storage.randomFileName} |
1201 | 1203 | account: |
1202 | 1204 | info: |
1203 | - emailSuffix: ${ACCOUNT_EMAIL_SUFFIX:yunteng.com} | |
1205 | + emailSuffix: ${ACCOUNT_EMAIL_SUFFIX:thingskit.com} | |
1204 | 1206 | defaultPassword: 123456 |
1205 | 1207 | reset: ${ACCOUNT_PASSWORD_FORCE_RESET:true} |
1206 | 1208 | third: | ... | ... |
... | ... | @@ -19,13 +19,17 @@ public interface FastIotConstants { |
19 | 19 | Pattern EMAIL_PATTERN = Pattern.compile(EMAIL, Pattern.CASE_INSENSITIVE); |
20 | 20 | Pattern CHINA_MOBILE_PATTERN = Pattern.compile(MOBILE); |
21 | 21 | String DEFAULT_DELIMITER = "#"; |
22 | + String RPC_COMMAND = "rpcCommand"; | |
23 | + | |
22 | 24 | interface CacheConfigKey { |
23 | 25 | String CACHE_CONFIG_KEY = "yunTengIotCache"; |
24 | 26 | String USER_PERMISSION_PREFIX = "userPermissionFor_"; |
25 | 27 | String MOBILE_LOGIN_SMS_CODE = "mobileLoginSmsCode"; |
26 | - | |
27 | 28 | String AREA = "thingsArea"; |
29 | + String PUBLIC_ID = "publicId_"; | |
30 | + String TASK_CENTER_INFOS = "taskCenterInfos_"; | |
28 | 31 | } |
32 | + | |
29 | 33 | interface TBCacheConfig { |
30 | 34 | String TB_CACHE_CONFIG_KEY = "TB_CONNECT_CACHE"; |
31 | 35 | String EXISTING_TENANT = "EXISTING_TENANT"; |
... | ... | @@ -48,7 +52,6 @@ public interface FastIotConstants { |
48 | 52 | int DRAFT = 0; |
49 | 53 | } |
50 | 54 | |
51 | - | |
52 | 55 | interface ConfigureLevel { |
53 | 56 | String CONFIGURE = "CONFIGURE"; |
54 | 57 | String CONTENT = "CONTENT"; |
... | ... | @@ -130,6 +133,12 @@ public interface FastIotConstants { |
130 | 133 | /** 在线 */ |
131 | 134 | public static final int ONLINE = 1; |
132 | 135 | |
136 | + /** 发布 */ | |
137 | + public static final int PUBLISH = 1; | |
138 | + | |
139 | + /** 取消发布 */ | |
140 | + public static final int CANCEL_PUBLISH = 0; | |
141 | + | |
133 | 142 | /** 删除成功 */ |
134 | 143 | public static final String DELETE_SUCCESS = "删除成功"; |
135 | 144 | ... | ... |
... | ... | @@ -118,6 +118,8 @@ public final class ModelConstants { |
118 | 118 | public static final String TK_CUSTOMER_DEVICE_NAME = "tk_customer_device"; |
119 | 119 | /** 设备上下线记录表 */ |
120 | 120 | public static final String TK_DEVICE_STATE_LOG = "tk_device_state_log"; |
121 | + /** 任务中心表 */ | |
122 | + public static final String TK_TASK_CENTER_NAME = "tk_task_center"; | |
121 | 123 | } |
122 | 124 | |
123 | 125 | public static class TableFields { | ... | ... |
... | ... | @@ -2,13 +2,14 @@ package org.thingsboard.server.common.data.yunteng.core.cache; |
2 | 2 | import org.springframework.cache.Cache; |
3 | 3 | import org.springframework.cache.CacheManager; |
4 | 4 | import org.springframework.stereotype.Component; |
5 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
5 | 6 | import java.util.Objects; |
6 | 7 | import java.util.Optional; |
7 | 8 | |
8 | 9 | @Component |
9 | 10 | public class CacheUtils { |
10 | 11 | |
11 | - private final String COMMON_STORE_AREA = "yun-teng-iot-common"; | |
12 | + private final String COMMON_STORE_AREA = FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY; | |
12 | 13 | |
13 | 14 | private final CacheManager cacheManager; |
14 | 15 | ... | ... |
... | ... | @@ -89,6 +89,11 @@ public enum ErrorMessage { |
89 | 89 | INVALID_TOPIC(400065,"无效Topic。"), |
90 | 90 | BUCKET_NOT_CONFORM_RENAME_RULE(400066,"存储桶不符合命名规范!!"), |
91 | 91 | MINIO_KEY_AND_SIGNATURE_ERROR(400067,"Minio签名不匹配!!"), |
92 | + CURRENT_VIEW_IS_PRIVATE(400068,"当前视图为私有视图,拒绝访问!"), | |
93 | + CURRENT_URL_REQUIRES_PERMISSION(400069,"当前视图需要访问凭证或凭证验证失败!"), | |
94 | + SHARE_VIEW_TYPE_NOT_EXIST(400070,"分享视图类型不存在"), | |
95 | + DATA_STATE_ENABLE_NOT_DELETE(400071,"【%s】数据为启用状态不能删除!!"), | |
96 | + EXECUTE_COMMAND_IS_NULL(400072,"执行命令不能为空"), | |
92 | 97 | HAVE_NO_PERMISSION(500002,"没有修改权限"); |
93 | 98 | private final int code; |
94 | 99 | private String message; | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/ConfigurationCenterDTO.java
... | ... | @@ -10,7 +10,7 @@ import javax.validation.constraints.NotEmpty; |
10 | 10 | |
11 | 11 | @EqualsAndHashCode(callSuper = true) |
12 | 12 | @Data |
13 | -public class ConfigurationCenterDTO extends TenantDTO { | |
13 | +public class ConfigurationCenterDTO extends PublicCustomerDTO { | |
14 | 14 | @ApiModelProperty(value = "组态名称", required = true) |
15 | 15 | @NotEmpty( |
16 | 16 | message = "组态名称不能为空或空字符串", | ... | ... |
... | ... | @@ -5,14 +5,13 @@ import lombok.Data; |
5 | 5 | import lombok.EqualsAndHashCode; |
6 | 6 | import org.thingsboard.server.common.data.yunteng.common.AddGroup; |
7 | 7 | import org.thingsboard.server.common.data.yunteng.dto.board.ComponentLayoutDTO; |
8 | -import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
9 | 8 | |
10 | 9 | import javax.validation.constraints.NotEmpty; |
11 | 10 | import java.util.List; |
12 | 11 | |
13 | 12 | @EqualsAndHashCode(callSuper = true) |
14 | 13 | @Data |
15 | -public class DataBoardDTO extends TenantDTO { | |
14 | +public class DataBoardDTO extends PublicCustomerDTO { | |
16 | 15 | @ApiModelProperty(value = "数据看板名称", required = true) |
17 | 16 | @NotEmpty(message = "数据看板名称不能为空或者空字符串", groups = AddGroup.class) |
18 | 17 | private String name; |
... | ... | @@ -21,9 +20,6 @@ public class DataBoardDTO extends TenantDTO { |
21 | 20 | @NotEmpty(message = "组织ID不能为空或者空字符串", groups = AddGroup.class) |
22 | 21 | private String organizationId; |
23 | 22 | |
24 | - @ApiModelProperty(value = "视图类型") | |
25 | - private ViewType viewType = ViewType.PRIVATE_VIEW; | |
26 | - | |
27 | 23 | @ApiModelProperty(value = "组件布局") |
28 | 24 | private List<ComponentLayoutDTO> layout; |
29 | 25 | ... | ... |
... | ... | @@ -121,6 +121,8 @@ public class DeviceDTO extends TenantDTO { |
121 | 121 | @ApiModelProperty(value = "启用/禁用") |
122 | 122 | private boolean enable; |
123 | 123 | |
124 | + private JsonNode customerAdditionalInfo; | |
125 | + | |
124 | 126 | public DeviceState getDeviceState() { |
125 | 127 | if (lastOnlineTime == null) { |
126 | 128 | return DeviceState.INACTIVE; | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/PublicCustomerDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
6 | + | |
7 | +@Data | |
8 | +public class PublicCustomerDTO extends TenantDTO { | |
9 | + @ApiModelProperty(value = "分享公共ID") | |
10 | + private String publicId; | |
11 | + | |
12 | + @ApiModelProperty(value = "视图类型") | |
13 | + private ViewType viewType = ViewType.PRIVATE_VIEW; | |
14 | + | |
15 | + @ApiModelProperty(value = "访问凭证") | |
16 | + private String accessCredentials; | |
17 | +} | ... | ... |
... | ... | @@ -11,33 +11,27 @@ import javax.validation.constraints.NotEmpty; |
11 | 11 | |
12 | 12 | @EqualsAndHashCode(callSuper = true) |
13 | 13 | @Data |
14 | -public class TkDataViewDTO extends TenantDTO { | |
15 | - @ApiModelProperty(value = "大屏名称", required = true) | |
16 | - @NotEmpty( | |
17 | - message = "大屏名称不能为空或空字符串", | |
18 | - groups = {UpdateGroup.class, AddGroup.class}) | |
19 | - private String name; | |
14 | +public class TkDataViewDTO extends PublicCustomerDTO { | |
15 | + @ApiModelProperty(value = "大屏名称", required = true) | |
16 | + @NotEmpty( | |
17 | + message = "大屏名称不能为空或空字符串", | |
18 | + groups = {UpdateGroup.class, AddGroup.class}) | |
19 | + private String name; | |
20 | 20 | |
21 | - @ApiModelProperty(value = "状态:0待发布 1发布") | |
22 | - private Integer state; | |
21 | + @ApiModelProperty(value = "状态:0待发布 1发布") | |
22 | + private Integer state; | |
23 | 23 | |
24 | - @ApiModelProperty(value = "大屏描述") | |
25 | - private String remark; | |
24 | + @ApiModelProperty(value = "大屏描述") | |
25 | + private String remark; | |
26 | 26 | |
27 | - @ApiModelProperty(value = "组织ID", required = true) | |
28 | - @NotEmpty( | |
29 | - message = "组织ID不能为空或空字符串", | |
30 | - groups = {UpdateGroup.class, AddGroup.class}) | |
31 | - private String organizationId; | |
27 | + @ApiModelProperty(value = "组织ID", required = true) | |
28 | + @NotEmpty( | |
29 | + message = "组织ID不能为空或空字符串", | |
30 | + groups = {UpdateGroup.class, AddGroup.class}) | |
31 | + private String organizationId; | |
32 | 32 | |
33 | - @ApiModelProperty(value = "组态缩略图") | |
34 | - private String thumbnail; | |
33 | + @ApiModelProperty(value = "组态缩略图") | |
34 | + private String thumbnail; | |
35 | 35 | |
36 | - private OrganizationDTO organizationDTO; | |
37 | - | |
38 | - @ApiModelProperty(value = "视图类型") | |
39 | - private ViewType viewType; | |
40 | - | |
41 | - @ApiModelProperty(value = "访问凭证") | |
42 | - private String accessCredentials; | |
36 | + private OrganizationDTO organizationDTO; | |
43 | 37 | } | ... | ... |
... | ... | @@ -5,24 +5,33 @@ import lombok.Data; |
5 | 5 | |
6 | 6 | import javax.validation.constraints.NotEmpty; |
7 | 7 | import java.io.Serializable; |
8 | +import java.util.List; | |
8 | 9 | import java.util.Map; |
9 | 10 | |
10 | 11 | |
11 | 12 | @Data |
12 | 13 | public class TkDeviceRpcDTO implements Serializable { |
13 | 14 | |
14 | - @ApiModelProperty(value = "命令下发方法名、功能名") | |
15 | - @NotEmpty(message = "功能名不能为空或者空字符串") | |
15 | + @ApiModelProperty(value = "功能码,16进制",required = true) | |
16 | + @NotEmpty(message = "功能码不能为空或者空字符串") | |
16 | 17 | private String method; |
17 | 18 | |
18 | - @ApiModelProperty(value = "设备名称。添加设备时,设备名称的内容必须与脚本用到的设备标识一致。") | |
19 | - @NotEmpty(message = "设备名称不能为空或者空字符串") | |
19 | + @ApiModelProperty(value = "从设备地址码,16进制。添加设备时,设备名称的内容必须与脚本用到的设备标识一致。",required = true) | |
20 | + @NotEmpty(message = "从设备地址码不能为空或者空字符串") | |
20 | 21 | private String deviceCode; |
21 | 22 | |
22 | - @ApiModelProperty(value = "数据校验算法") | |
23 | - private String check; | |
23 | + @ApiModelProperty(value = "数据校验算法",required = true) | |
24 | + private String crc; | |
24 | 25 | |
25 | - @ApiModelProperty(value = "数据相关信息,例如:寄存器地址和寄存器数") | |
26 | + @ApiModelProperty(value = "寄存器地址",required = true) | |
27 | + private Integer registerAddr; | |
28 | + @ApiModelProperty(value = "寄存器数量") | |
29 | + private Integer registerNum; | |
30 | + | |
31 | + | |
32 | + | |
33 | + | |
34 | + @ApiModelProperty(value = "寄存器值") | |
26 | 35 | @NotEmpty(message = "数据相关信息不能为空或者空字符串") |
27 | - private Map<String, Object> params; | |
36 | + private List<Integer> registerVales; | |
28 | 37 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/task/TargetContentDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto.task; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | +import java.util.List; | |
6 | +import java.util.Map; | |
7 | + | |
8 | +@Data | |
9 | +public class TargetContentDTO { | |
10 | + @ApiModelProperty(value = "执行的数据:目标类型如果是产品则为deviceProfileId,如果是设备则为tbDeviceId") | |
11 | + List<String> data; | |
12 | + | |
13 | + @ApiModelProperty(value = "设备类型") | |
14 | + String deviceType; | |
15 | + | |
16 | + @ApiModelProperty(value = "组织ID") | |
17 | + String organizationId; | |
18 | + | |
19 | + @ApiModelProperty(value = "设备配置ID") | |
20 | + String deviceProfileId; | |
21 | + | |
22 | + @ApiModelProperty(value = "取消执行的数据:只有目标类型是产品时才会有值,且List<String>里面为tbDeviceId") | |
23 | + Map<String, List<String>> cancelExecuteDevices; | |
24 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.dto.task; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | +import org.thingsboard.server.common.data.yunteng.enums.ExecuteTypeEnum; | |
6 | + | |
7 | +@Data | |
8 | +public class TaskExecuteTimeDTO { | |
9 | + | |
10 | + @ApiModelProperty(value = "执行类型") | |
11 | + private ExecuteTypeEnum type = ExecuteTypeEnum.CUSTOM; | |
12 | + | |
13 | + @ApiModelProperty(value = "周期类型") | |
14 | + private String periodType; | |
15 | + | |
16 | + @ApiModelProperty(value = "周期") | |
17 | + private String period; | |
18 | + | |
19 | + @ApiModelProperty(value = "时间") | |
20 | + private String time; | |
21 | + | |
22 | + @ApiModelProperty(value = "轮询单位:秒 分 时") | |
23 | + private String pollUnit; | |
24 | + | |
25 | + @ApiModelProperty(value = "cron表达式") | |
26 | + private String cron; | |
27 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/task/TaskTypeDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto.task; | |
2 | + | |
3 | +import com.fasterxml.jackson.databind.JsonNode; | |
4 | +import io.swagger.annotations.ApiModelProperty; | |
5 | +import lombok.Data; | |
6 | +import org.thingsboard.server.common.data.yunteng.enums.TaskTypeEnum; | |
7 | + | |
8 | +@Data | |
9 | +public class TaskTypeDTO { | |
10 | + @ApiModelProperty(value = "类型") | |
11 | + private TaskTypeEnum type = TaskTypeEnum.CUSTOM; | |
12 | + | |
13 | + @ApiModelProperty(value = "推送方式:MQTT TCP") | |
14 | + private String pushWay; | |
15 | + | |
16 | + @ApiModelProperty(value = "推送内容:即下发的命令内容") | |
17 | + private JsonNode pushContent; | |
18 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/task/TkTaskCenterDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto.task; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.common.AddGroup; | |
7 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
8 | +import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; | |
9 | +import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; | |
10 | + | |
11 | +import javax.validation.constraints.NotEmpty; | |
12 | +import javax.validation.constraints.NotNull; | |
13 | + | |
14 | +@Data | |
15 | +@EqualsAndHashCode(callSuper = true) | |
16 | +public class TkTaskCenterDTO extends TenantDTO { | |
17 | + @NotEmpty(message = "任务名称不能为空或空字符串", groups = AddGroup.class) | |
18 | + @ApiModelProperty(value = "任务名称") | |
19 | + private String name; | |
20 | + | |
21 | + @ApiModelProperty(value = "目标类型") | |
22 | + private TargetTypeEnum targetType = TargetTypeEnum.DEVICES; | |
23 | + | |
24 | + @NotNull(message = "执行目标不能为空", groups = AddGroup.class) | |
25 | + @ApiModelProperty(value = "执行目标") | |
26 | + private TargetContentDTO executeTarget; | |
27 | + | |
28 | + @NotNull(message = "执行内容不能为空", groups = AddGroup.class) | |
29 | + @ApiModelProperty(value = "执行内容") | |
30 | + private TaskTypeDTO executeContent; | |
31 | + | |
32 | + @ApiModelProperty(value = "执行时间") | |
33 | + @NotNull(message = "执行时间不能为空", groups = AddGroup.class) | |
34 | + private TaskExecuteTimeDTO executeTime; | |
35 | + | |
36 | + @ApiModelProperty(value = "0禁用 1启用") | |
37 | + private Integer state = FastIotConstants.StateValue.DISABLE; | |
38 | + | |
39 | + @ApiModelProperty(value = "备注") | |
40 | + private String remark; | |
41 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/ByteUtils.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +import org.apache.commons.lang3.ArrayUtils; | |
4 | + | |
5 | +import java.io.*; | |
6 | +import java.nio.charset.Charset; | |
7 | +import java.util.regex.Pattern; | |
8 | + | |
9 | +/** | |
10 | + * @Description :数据类型转换工具类 | |
11 | + * 二进制的最高位是符号位,0表示正,1表示负。 | |
12 | + * 负数采用二进制的补码表示,10进制转为二进制得到的是源码,将源码按位取反得到的是反码,反码加1得到补码 | |
13 | + * <p> | |
14 | + * <p> | |
15 | + * *¥¥¥【基本数据类型】¥¥¥¥¥¥¥¥¥¥¥¥ | |
16 | + * 1/8:boolean【1 位】 | |
17 | + * 3/8:byte 【1个字节,8 位】 | |
18 | + * 3/8:short 【2个字节,16位】 | |
19 | + * 4/8:int 【4个字节,32位】 | |
20 | + * 5/8:long 【8个字节,64位】 | |
21 | + * 6/8:float 【4个字节,32位】 | |
22 | + * 7/8:double 【8个字节,64位】 | |
23 | + * 8/8:chart 【2个字节,16位】 | |
24 | + * <p> | |
25 | + * <p> | |
26 | + * <p> | |
27 | + * *¥¥¥【位运算】¥¥¥¥¥¥¥¥¥¥¥¥ | |
28 | + * 左移【<< n】:向左移动,左边高位舍弃,右边的低位补0,例如:2左移3位,结果为16 | |
29 | + * 右移【>>n】:向右移动,右边的舍弃掉,左边补的值取决于原来最高位,原来是1就补1,原来是0就补0 | |
30 | + * 无符号右移【>>>n】向右移动,右边的舍弃掉,左边补0。 | |
31 | + * <p> | |
32 | + * <p> | |
33 | + * <p> | |
34 | + * 1.其它地方抛出异常,交由控制层统一处理 | |
35 | + * 2.服务层注意持久化的事务管理 | |
36 | + * @Author: junlianglee | |
37 | + * @Date Created in 2019/12/11. | |
38 | + * @Modified by Administrator on 2019/12/11. | |
39 | + */ | |
40 | +public class ByteUtils { | |
41 | + public static final char[] ascii = "0123456789ABCDEF".toCharArray(); | |
42 | + private static char[] HEX_VOCABLE = {'0', '1', '2', '3', '4', '5', '6', '7', | |
43 | + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |
44 | + | |
45 | + public static final String UTF_8 = "UTF-8"; | |
46 | + | |
47 | + private static String hexString = "0123456789ABCDEF"; | |
48 | + | |
49 | + /** | |
50 | + * 将short整型数值转换为字节数组 | |
51 | + * | |
52 | + * @param data | |
53 | + * @return | |
54 | + */ | |
55 | + public static byte[] getBytes(short data) { | |
56 | + byte[] bytes = new byte[2]; | |
57 | + bytes[0] = (byte) ((data & 0xff00) >> 8);//1个十六进制位匹配4个二进制位 | |
58 | + bytes[1] = (byte) (data & 0xff); | |
59 | + return bytes; | |
60 | + } | |
61 | + | |
62 | + /** | |
63 | + * 将字符转换为字节数组 | |
64 | + * | |
65 | + * @param data | |
66 | + * @return | |
67 | + */ | |
68 | + public static byte[] getBytes(char data) { | |
69 | + byte[] bytes = new byte[2]; | |
70 | + bytes[0] = (byte) (data >> 8); | |
71 | + bytes[1] = (byte) (data); | |
72 | + return bytes; | |
73 | + } | |
74 | + | |
75 | + /** | |
76 | + * 将布尔值转换为字节数组 | |
77 | + * | |
78 | + * @param data | |
79 | + * @return | |
80 | + */ | |
81 | + public static byte[] getBytes(boolean data) { | |
82 | + byte[] bytes = new byte[1]; | |
83 | + bytes[0] = (byte) (data ? 1 : 0); | |
84 | + return bytes; | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * 将整型数值转换为字节数组 | |
89 | + * | |
90 | + * @param data | |
91 | + * @return | |
92 | + */ | |
93 | + public static byte[] getBytes(int data) { | |
94 | + byte[] bytes = new byte[4]; | |
95 | + bytes[0] = (byte) ((data & 0xff000000) >> 24); | |
96 | + bytes[1] = (byte) ((data & 0xff0000) >> 16); | |
97 | + bytes[2] = (byte) ((data & 0xff00) >> 8); | |
98 | + bytes[3] = (byte) (data & 0xff); | |
99 | + return bytes; | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * 将long整型数值转换为字节数组 | |
104 | + * | |
105 | + * @param data | |
106 | + * @return | |
107 | + */ | |
108 | + public static byte[] getBytes(long data) { | |
109 | + byte[] bytes = new byte[8]; | |
110 | + bytes[0] = (byte) ((data >> 56) & 0xff); | |
111 | + bytes[1] = (byte) ((data >> 48) & 0xff); | |
112 | + bytes[2] = (byte) ((data >> 40) & 0xff); | |
113 | + bytes[3] = (byte) ((data >> 32) & 0xff); | |
114 | + bytes[4] = (byte) ((data >> 24) & 0xff); | |
115 | + bytes[5] = (byte) ((data >> 16) & 0xff); | |
116 | + bytes[6] = (byte) ((data >> 8) & 0xff); | |
117 | + bytes[7] = (byte) (data & 0xff); | |
118 | + return bytes; | |
119 | + } | |
120 | + | |
121 | + /** | |
122 | + * 将float型数值转换为字节数组 | |
123 | + * | |
124 | + * @param data | |
125 | + * @return | |
126 | + */ | |
127 | + public static byte[] getBytes(float data) { | |
128 | + int intBits = Float.floatToIntBits(data); | |
129 | + return getBytes(intBits); | |
130 | + } | |
131 | + | |
132 | + /** | |
133 | + * 将double型数值转换为字节数组 | |
134 | + * | |
135 | + * @param data | |
136 | + * @return | |
137 | + */ | |
138 | + public static byte[] getBytes(double data) { | |
139 | + long intBits = Double.doubleToLongBits(data); | |
140 | + return getBytes(intBits); | |
141 | + } | |
142 | + | |
143 | + /** | |
144 | + * 将字符串按照charsetName编码格式的字节数组 | |
145 | + * | |
146 | + * @param data 字符串 | |
147 | + * @param charsetName 编码格式 | |
148 | + * @return | |
149 | + */ | |
150 | + public static byte[] getBytes(String data, String charsetName) { | |
151 | + Charset charset = Charset.forName(charsetName); | |
152 | + return data.getBytes(charset); | |
153 | + } | |
154 | + | |
155 | + | |
156 | + /** | |
157 | + * 将字节数组前8字节转换为long整型数值 | |
158 | + * | |
159 | + * @param bytes | |
160 | + * @return | |
161 | + */ | |
162 | + public static long getLong(byte[] bytes) { | |
163 | + return (0xff00000000000000L & ((long) bytes[0] << 56) | |
164 | + | (0xff000000000000L & ((long) bytes[1] << 48)) | |
165 | + | (0xff0000000000L & ((long) bytes[2] << 40)) | |
166 | + | (0xff00000000L & ((long) bytes[3] << 32)) | |
167 | + | (0xff000000L & ((long) bytes[4] << 24)) | |
168 | + | (0xff0000L & ((long) bytes[5] << 16)) | |
169 | + | (0xff00L & ((long) bytes[6] << 8)) | |
170 | + | (0xffL & (long) bytes[7])); | |
171 | + } | |
172 | + | |
173 | + | |
174 | + /** | |
175 | + * 将charsetName编码格式的字节数组转换为字符串 | |
176 | + * | |
177 | + * @param bytes | |
178 | + * @param charsetName | |
179 | + * @return | |
180 | + */ | |
181 | + public static String getString(byte[] bytes, String charsetName) { | |
182 | + return new String(bytes, Charset.forName(charsetName)); | |
183 | + } | |
184 | + | |
185 | + | |
186 | + public static byte[] hexStr2Bytes(String hexString) { | |
187 | + if (hexString == null || hexString.equals("")) { | |
188 | + return null; | |
189 | + } | |
190 | + // toUpperCase将字符串中的所有字符转换为大写 | |
191 | + hexString = hexString.toUpperCase(); | |
192 | + int length = hexString.length() / 2;// 2个16进制字符表示一个字节,所以字节数组长度是字符串长度除以2 | |
193 | + // toCharArray将此字符串转换为一个新的字符数组。 | |
194 | + char[] hexChars = hexString.toCharArray(); | |
195 | + byte[] d = new byte[length]; | |
196 | + for (int i = 0; i < length; i++) { | |
197 | + int pos = i * 2; | |
198 | + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | |
199 | + | charToByte(hexChars[pos + 1])); | |
200 | + } | |
201 | + return d; | |
202 | + } | |
203 | + | |
204 | + // charToByte返回在指定字符的第一个发生的字符串中的索引,即返回匹配字符 | |
205 | + private static byte charToByte(char c) { | |
206 | + return (byte) "0123456789ABCDEF".indexOf(c); | |
207 | + } | |
208 | + | |
209 | + /** | |
210 | + * 将16进制字符串转换为字节数组 | |
211 | + * | |
212 | + * @param hex | |
213 | + * @return | |
214 | + */ | |
215 | + public static byte[] hexToBytes(String hex) { | |
216 | + if (hex.length() % 2 != 0) | |
217 | + throw new IllegalArgumentException( | |
218 | + "input string should be any multiple of 2!"); | |
219 | + hex.toUpperCase(); | |
220 | + | |
221 | + byte[] byteBuffer = new byte[hex.length() / 2]; | |
222 | + | |
223 | + byte padding = 0x00; | |
224 | + boolean paddingTurning = false; | |
225 | + for (int i = 0; i < hex.length(); i++) { | |
226 | + if (paddingTurning) { | |
227 | + char c = hex.charAt(i); | |
228 | + int index = indexOf(hex, c); | |
229 | + padding = (byte) ((padding << 4) | index); | |
230 | + byteBuffer[i / 2] = padding; | |
231 | + padding = 0x00; | |
232 | + paddingTurning = false; | |
233 | + } else { | |
234 | + char c = hex.charAt(i); | |
235 | + int index = indexOf(hex, c); | |
236 | + padding = (byte) (padding | index); | |
237 | + paddingTurning = true; | |
238 | + } | |
239 | + | |
240 | + } | |
241 | + return byteBuffer; | |
242 | + } | |
243 | + | |
244 | + private static int indexOf(String input, char c) { | |
245 | + int index = ArrayUtils.indexOf(HEX_VOCABLE, c); | |
246 | + | |
247 | + if (index < 0) { | |
248 | + throw new IllegalArgumentException("err input:" + input); | |
249 | + } | |
250 | + return index; | |
251 | + | |
252 | + } | |
253 | + | |
254 | + /** | |
255 | + * 字节数组转16进制字符串 | |
256 | + * | |
257 | + * @param bs | |
258 | + * @return | |
259 | + */ | |
260 | + public static String bytesToHex(byte[] bs) { | |
261 | + StringBuilder sb = new StringBuilder(); | |
262 | + for (byte b : bs) { | |
263 | + int high = (b >> 4) & 0x0f; | |
264 | + int low = b & 0x0f; | |
265 | + sb.append(HEX_VOCABLE[high]); | |
266 | + sb.append(HEX_VOCABLE[low]); | |
267 | + } | |
268 | + return sb.toString(); | |
269 | + } | |
270 | + | |
271 | + private static final String messageRegular = "^[A-Za-z0-9!@#$%^&*()]+$"; | |
272 | + | |
273 | + public static String bytesToStr(byte[] bs) { | |
274 | + String result = getString(bs, ByteUtils.UTF_8); | |
275 | + if (!Pattern.compile(messageRegular).matcher(result).matches()) { | |
276 | + result = bytesToHex(bs); | |
277 | + } | |
278 | + return result; | |
279 | + } | |
280 | + | |
281 | + public static byte[] strToBytes(String str) { | |
282 | + if (Pattern.compile(messageRegular).matcher(str).matches()) { | |
283 | + return hexStr2Bytes(str); | |
284 | + } | |
285 | + return getBytes(str, ByteUtils.UTF_8); | |
286 | + } | |
287 | + | |
288 | + /** | |
289 | + * 字节数组取前len个字节转16进制字符串 | |
290 | + * | |
291 | + * @param bs | |
292 | + * @param len | |
293 | + * @return | |
294 | + */ | |
295 | + public static String bytesToHex(byte[] bs, int len) { | |
296 | + StringBuilder sb = new StringBuilder(); | |
297 | + for (int i = 0; i < len; i++) { | |
298 | + byte b = bs[i]; | |
299 | + int high = (b >> 4) & 0x0f; | |
300 | + int low = b & 0x0f; | |
301 | + sb.append(HEX_VOCABLE[high]); | |
302 | + sb.append(HEX_VOCABLE[low]); | |
303 | + } | |
304 | + return sb.toString(); | |
305 | + } | |
306 | + | |
307 | + /** | |
308 | + * 字节数组偏移offset长度之后的取len个字节转16进制字符串 | |
309 | + * | |
310 | + * @param bs | |
311 | + * @param offset | |
312 | + * @param len | |
313 | + * @return | |
314 | + */ | |
315 | + public static String bytesToHex(byte[] bs, int offset, int len) { | |
316 | + StringBuilder sb = new StringBuilder(); | |
317 | + for (int i = 0; i < len; i++) { | |
318 | + byte b = bs[offset + i]; | |
319 | + int high = (b >> 4) & 0x0f; | |
320 | + int low = b & 0x0f; | |
321 | + sb.append(HEX_VOCABLE[high]); | |
322 | + sb.append(HEX_VOCABLE[low]); | |
323 | + } | |
324 | + return sb.toString(); | |
325 | + } | |
326 | + | |
327 | + /** | |
328 | + * 字节数组转16进制字符串 | |
329 | + * | |
330 | + * @param bs | |
331 | + * @return | |
332 | + */ | |
333 | + public static String byteToHex(byte bs) { | |
334 | + StringBuilder sb = new StringBuilder(); | |
335 | + int high = (bs >> 4) & 0x0f; | |
336 | + int low = bs & 0x0f; | |
337 | + sb.append(HEX_VOCABLE[high]); | |
338 | + sb.append(HEX_VOCABLE[low]); | |
339 | + return sb.toString(); | |
340 | + } | |
341 | + | |
342 | + /** | |
343 | + * 将字节数组取反 | |
344 | + * | |
345 | + * @param src | |
346 | + * @return | |
347 | + */ | |
348 | + public static String negate(byte[] src) { | |
349 | + if (src == null || src.length == 0) { | |
350 | + return null; | |
351 | + } | |
352 | + byte[] temp = new byte[2 * src.length]; | |
353 | + for (int i = 0; i < src.length; i++) { | |
354 | + byte tmp = (byte) (0xFF ^ src[i]); | |
355 | + temp[i * 2] = (byte) ((tmp >> 4) & 0x0f); | |
356 | + temp[i * 2 + 1] = (byte) (tmp & 0x0f); | |
357 | + } | |
358 | + StringBuffer res = new StringBuffer(); | |
359 | + for (int i = 0; i < temp.length; i++) { | |
360 | + res.append(ascii[temp[i]]); | |
361 | + } | |
362 | + return res.toString(); | |
363 | + } | |
364 | + | |
365 | + | |
366 | + /** | |
367 | + * 数组合并 | |
368 | + * | |
369 | + * @param before | |
370 | + * @param end | |
371 | + * @return | |
372 | + */ | |
373 | + public static byte[] merge(byte[] before, byte[] end) { | |
374 | + byte[] result = new byte[before.length + end.length]; | |
375 | + System.arraycopy(before, 0, result, 0, before.length); | |
376 | + System.arraycopy(end, 0, result, before.length, end.length); | |
377 | + return result; | |
378 | + } | |
379 | + | |
380 | + public static byte[] subBytes(byte[] before, Integer start, Integer length) { | |
381 | + byte[] result = new byte[length]; | |
382 | + System.arraycopy(before, start, result, 0, length); | |
383 | + return result; | |
384 | + } | |
385 | + | |
386 | + /** | |
387 | + * 比较字节数组是否相同 | |
388 | + * | |
389 | + * @param a | |
390 | + * @param b | |
391 | + * @return | |
392 | + */ | |
393 | + public static boolean compareBytes(byte[] a, byte[] b) { | |
394 | + if (a == null || a.length == 0 || b == null || b.length == 0 | |
395 | + || a.length != b.length) { | |
396 | + return false; | |
397 | + } | |
398 | + if (a.length == b.length) { | |
399 | + for (int i = 0; i < a.length; i++) { | |
400 | + if (a[i] != b[i]) { | |
401 | + return false; | |
402 | + } | |
403 | + } | |
404 | + } else { | |
405 | + return false; | |
406 | + } | |
407 | + return true; | |
408 | + } | |
409 | + | |
410 | + /** | |
411 | + * 只比对指定长度byte | |
412 | + * | |
413 | + * @param a | |
414 | + * @param b | |
415 | + * @param len | |
416 | + * @return | |
417 | + */ | |
418 | + public static boolean compareBytes(byte[] a, byte[] b, int len) { | |
419 | + if (a == null || a.length == 0 || b == null || b.length == 0 | |
420 | + || a.length < len || b.length < len) { | |
421 | + return false; | |
422 | + } | |
423 | + for (int i = 0; i < len; i++) { | |
424 | + if (a[i] != b[i]) { | |
425 | + return false; | |
426 | + } | |
427 | + } | |
428 | + return true; | |
429 | + } | |
430 | + | |
431 | + /** | |
432 | + * 将字节数组转换为二进制字符串 | |
433 | + * | |
434 | + * @param items | |
435 | + * @return | |
436 | + */ | |
437 | + public static String bytesToBinaryString(byte[] items) { | |
438 | + if (items == null || items.length == 0) { | |
439 | + return null; | |
440 | + } | |
441 | + StringBuffer buf = new StringBuffer(); | |
442 | + for (byte item : items) { | |
443 | + buf.append(byteToBinaryString(item)); | |
444 | + } | |
445 | + return buf.toString(); | |
446 | + } | |
447 | + | |
448 | + /** | |
449 | + * 将字节转换为二进制字符串 | |
450 | + * | |
451 | + * @param item | |
452 | + * @return | |
453 | + */ | |
454 | + public static String byteToBinaryString(byte item) { | |
455 | + byte a = item; | |
456 | + StringBuffer buf = new StringBuffer(); | |
457 | + for (int i = 0; i < 8; i++) { | |
458 | + buf.insert(0, a % 2); | |
459 | + a = (byte) (a >> 1); | |
460 | + } | |
461 | + return buf.toString(); | |
462 | + } | |
463 | + | |
464 | + /** | |
465 | + * 对数组a,b进行异或运算 | |
466 | + * | |
467 | + * @param a | |
468 | + * @param b | |
469 | + * @return | |
470 | + */ | |
471 | + public static byte[] xor(byte[] a, byte[] b) { | |
472 | + if (a == null || a.length == 0 || b == null || b.length == 0 | |
473 | + || a.length != b.length) { | |
474 | + return null; | |
475 | + } | |
476 | + byte[] result = new byte[a.length]; | |
477 | + for (int i = 0; i < a.length; i++) { | |
478 | + result[i] = (byte) (a[i] ^ b[i]); | |
479 | + } | |
480 | + return result; | |
481 | + } | |
482 | + | |
483 | + /** | |
484 | + * 对数组a,b进行异或运算 运算长度len | |
485 | + * | |
486 | + * @param a | |
487 | + * @param b | |
488 | + * @param len | |
489 | + * @return | |
490 | + */ | |
491 | + public static byte[] xor(byte[] a, byte[] b, int len) { | |
492 | + if (a == null || a.length == 0 || b == null || b.length == 0) { | |
493 | + return null; | |
494 | + } | |
495 | + if (a.length < len || b.length < len) { | |
496 | + return null; | |
497 | + } | |
498 | + byte[] result = new byte[len]; | |
499 | + for (int i = 0; i < len; i++) { | |
500 | + result[i] = (byte) (a[i] ^ b[i]); | |
501 | + } | |
502 | + return result; | |
503 | + } | |
504 | + | |
505 | + /** | |
506 | + * 将short整型数值转换为字节数组 | |
507 | + * | |
508 | + * @param num | |
509 | + * @return | |
510 | + */ | |
511 | + public static byte[] shortToBytes(int num) { | |
512 | + byte[] temp = new byte[2]; | |
513 | + for (int i = 0; i < 2; i++) { | |
514 | + temp[i] = (byte) ((num >>> (8 - i * 8)) & 0xFF); | |
515 | + } | |
516 | + return temp; | |
517 | + } | |
518 | + | |
519 | + /** | |
520 | + * 将字节数组转为整型 | |
521 | + * | |
522 | + * @param arr | |
523 | + * @return | |
524 | + */ | |
525 | + public static int bytesToShort(byte[] arr) { | |
526 | + int mask = 0xFF; | |
527 | + int temp = 0; | |
528 | + int result = 0; | |
529 | + for (int i = 0; i < 2; i++) { | |
530 | + result <<= 8; | |
531 | + temp = arr[i] & mask; | |
532 | + result |= temp; | |
533 | + } | |
534 | + return result; | |
535 | + } | |
536 | + | |
537 | + /** | |
538 | + * 将整型数值转换为指定长度的字节数组 | |
539 | + * | |
540 | + * @param num | |
541 | + * @return | |
542 | + */ | |
543 | + public static byte[] intToBytes(int num) { | |
544 | + byte[] temp = new byte[4]; | |
545 | + for (int i = 0; i < 4; i++) { | |
546 | + temp[i] = (byte) ((num >>> (24 - i * 8)) & 0xFF); | |
547 | + } | |
548 | + return temp; | |
549 | + } | |
550 | + | |
551 | + /** | |
552 | + * 将整型数值转换为指定长度的字节数组 | |
553 | + * | |
554 | + * @param src | |
555 | + * @param len | |
556 | + * @return | |
557 | + */ | |
558 | + public static byte[] intToBytes(int src, int len) { | |
559 | + if (len < 1 || len > 4) { | |
560 | + return null; | |
561 | + } | |
562 | + byte[] temp = new byte[len]; | |
563 | + for (int i = 0; i < len; i++) { | |
564 | + temp[len - 1 - i] = (byte) ((src >>> (8 * i)) & 0xFF); | |
565 | + } | |
566 | + return temp; | |
567 | + } | |
568 | + | |
569 | + /** | |
570 | + * 将字节数组转换为整型数值 | |
571 | + * | |
572 | + * @param arr | |
573 | + * @return | |
574 | + */ | |
575 | + public static int bytesToInt(byte[] arr) { | |
576 | + int mask = 0xFF; | |
577 | + int temp = 0; | |
578 | + int result = 0; | |
579 | + for (int i = 0; i < 4; i++) { | |
580 | + result <<= 8; | |
581 | + temp = arr[i] & mask; | |
582 | + result |= temp; | |
583 | + } | |
584 | + return result; | |
585 | + } | |
586 | + | |
587 | + /** | |
588 | + * 将long整型数值转换为字节数组 | |
589 | + * | |
590 | + * @param num | |
591 | + * @return | |
592 | + */ | |
593 | + public static byte[] longToBytes(long num) { | |
594 | + byte[] temp = new byte[8]; | |
595 | + for (int i = 0; i < 8; i++) { | |
596 | + temp[i] = (byte) ((num >>> (56 - i * 8)) & 0xFF); | |
597 | + } | |
598 | + return temp; | |
599 | + } | |
600 | + | |
601 | + /** | |
602 | + * 将字节数组转换为long整型数值 | |
603 | + * | |
604 | + * @param arr | |
605 | + * @return | |
606 | + */ | |
607 | + public static long bytesToLong(byte[] arr) { | |
608 | + int mask = 0xFF; | |
609 | + int temp = 0; | |
610 | + long result = 0; | |
611 | + int len = Math.min(8, arr.length); | |
612 | + for (int i = 0; i < len; i++) { | |
613 | + result <<= 8; | |
614 | + temp = arr[i] & mask; | |
615 | + result |= temp; | |
616 | + } | |
617 | + return result; | |
618 | + } | |
619 | + | |
620 | + /** | |
621 | + * 将16进制字符转换为字节 | |
622 | + * | |
623 | + * @param c | |
624 | + * @return | |
625 | + */ | |
626 | + public static byte toByte(char c) { | |
627 | + byte b = (byte) "0123456789ABCDEF".indexOf(c); | |
628 | + return b; | |
629 | + } | |
630 | + | |
631 | + /** | |
632 | + * 功能描述:把两个字节的字节数组转化为整型数据,高位补零,例如:<br/> | |
633 | + * 有字节数组byte[] data = new byte[]{1,2};转换后int数据的字节分布如下:<br/> | |
634 | + * 00000000 00000000 00000001 00000010,函数返回258 | |
635 | + * | |
636 | + * @param lenData 需要进行转换的字节数组 | |
637 | + * @return 字节数组所表示整型值的大小 | |
638 | + */ | |
639 | + public static int bytesToIntWhereByteLengthEquals2(byte lenData[]) { | |
640 | + if (lenData.length != 2) { | |
641 | + return -1; | |
642 | + } | |
643 | + byte fill[] = new byte[]{0, 0}; | |
644 | + byte real[] = new byte[4]; | |
645 | + System.arraycopy(fill, 0, real, 0, 2); | |
646 | + System.arraycopy(lenData, 0, real, 2, 2); | |
647 | + int len = byteToInt(real); | |
648 | + return len; | |
649 | + | |
650 | + } | |
651 | + | |
652 | + /** | |
653 | + * 功能描述:将byte数组转化为int类型的数据 | |
654 | + * | |
655 | + * @param byteVal 需要转化的字节数组 | |
656 | + * @return 字节数组所表示的整型数据 | |
657 | + */ | |
658 | + public static int byteToInt(byte[] byteVal) { | |
659 | + int result = 0; | |
660 | + for (int i = 0; i < byteVal.length; i++) { | |
661 | + int tmpVal = (byteVal[i] << (8 * (3 - i))); | |
662 | + switch (i) { | |
663 | + case 0: | |
664 | + tmpVal = tmpVal & 0xFF000000; | |
665 | + break; | |
666 | + case 1: | |
667 | + tmpVal = tmpVal & 0x00FF0000; | |
668 | + break; | |
669 | + case 2: | |
670 | + tmpVal = tmpVal & 0x0000FF00; | |
671 | + break; | |
672 | + case 3: | |
673 | + tmpVal = tmpVal & 0x000000FF; | |
674 | + break; | |
675 | + } | |
676 | + | |
677 | + result = result | tmpVal; | |
678 | + } | |
679 | + return result; | |
680 | + } | |
681 | + | |
682 | + public static byte CheckXORSum(byte[] bData) { | |
683 | + byte sum = 0x00; | |
684 | + for (int i = 0; i < bData.length; i++) { | |
685 | + sum ^= bData[i]; | |
686 | + } | |
687 | + return sum; | |
688 | + } | |
689 | + | |
690 | + /** | |
691 | + * 从offset开始 将后续长度为len的byte字节转为int | |
692 | + * | |
693 | + * @param data | |
694 | + * @param offset | |
695 | + * @param len | |
696 | + * @return | |
697 | + */ | |
698 | + public static int bytesToInt(byte[] data, int offset, int len) { | |
699 | + int mask = 0xFF; | |
700 | + int temp = 0; | |
701 | + int result = 0; | |
702 | + len = Math.min(len, 4); | |
703 | + for (int i = 0; i < len; i++) { | |
704 | + result <<= 8; | |
705 | + temp = data[offset + i] & mask; | |
706 | + result |= temp; | |
707 | + } | |
708 | + return result; | |
709 | + } | |
710 | + | |
711 | + /** | |
712 | + * byte字节数组中的字符串的长度 | |
713 | + * | |
714 | + * @param data | |
715 | + * @return | |
716 | + */ | |
717 | + public static int getBytesStringLen(byte[] data) { | |
718 | + int count = 0; | |
719 | + for (byte b : data) { | |
720 | + if (b == 0x00) | |
721 | + break; | |
722 | + count++; | |
723 | + } | |
724 | + return count; | |
725 | + } | |
726 | + | |
727 | + /** | |
728 | + * 校验和 | |
729 | + * | |
730 | + * @param msg 需要计算校验和的byte数组 | |
731 | + * @param length 校验和位数 | |
732 | + * @return 计算出的校验和数组 | |
733 | + */ | |
734 | + public static byte[] SumCheck(byte[] msg, int length) { | |
735 | + long mSum = 0; | |
736 | + byte[] mByte = new byte[length]; | |
737 | + | |
738 | + /** 逐Byte添加位数和 */ | |
739 | + for (byte byteMsg : msg) { | |
740 | + long mNum = ((long) byteMsg >= 0) | |
741 | + ? (long) byteMsg | |
742 | + : ((long) byteMsg + 256); | |
743 | + mSum += mNum; | |
744 | + } /** end of for (byte byteMsg : msg) */ | |
745 | + | |
746 | + /** 位数和转化为Byte数组 */ | |
747 | + for (int liv_Count = 0; liv_Count < length; liv_Count++) { | |
748 | + mByte[length - liv_Count | |
749 | + - 1] = (byte) (mSum >> (liv_Count * 8) & 0xff); | |
750 | + } /** end of for (int liv_Count = 0; liv_Count < length; liv_Count++) */ | |
751 | + | |
752 | + return mByte; | |
753 | + } | |
754 | + | |
755 | + /** | |
756 | + * 字节数据转十进制字符(补码-无符号) | |
757 | + * | |
758 | + * @param data | |
759 | + * @return | |
760 | + */ | |
761 | + public static String getByteToStr(byte[] data) { | |
762 | + StringBuffer str = new StringBuffer(); | |
763 | + for (int i = 0; i < data.length; i++) { | |
764 | + if (data[i] < 0) { | |
765 | + int tem = data[i] + 256; | |
766 | + str.append(tem + " "); | |
767 | + } else { | |
768 | + str.append(data[i] + " "); | |
769 | + } | |
770 | + } | |
771 | + return str.toString(); | |
772 | + } | |
773 | + | |
774 | + | |
775 | + public static byte[] fileBytes(String pathname) throws IOException { | |
776 | + File filename = new File(pathname); | |
777 | + BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename)); | |
778 | + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); | |
779 | + byte[] temp = new byte[1024]; | |
780 | + int size = 0; | |
781 | + while ((size = in.read(temp)) != -1) { | |
782 | + out.write(temp, 0, size); | |
783 | + } | |
784 | + in.close(); | |
785 | + out.close(); | |
786 | + byte[] content = out.toByteArray(); | |
787 | + return content; | |
788 | + } | |
789 | + | |
790 | + /** | |
791 | + * 单字节高低位互换 | |
792 | + * | |
793 | + * @param src | |
794 | + * @return | |
795 | + */ | |
796 | + public static int revert(int src) { | |
797 | + int lowByte = (src & 0xFF00) >> 8; | |
798 | + int highByte = (src & 0x00FF) << 8; | |
799 | + return lowByte | highByte; | |
800 | + } | |
801 | + | |
802 | + /** | |
803 | + * 将字符串编码成16进制数字,适用于所有字符(包括中文) | |
804 | + * | |
805 | + * @param str 字符串 | |
806 | + * @return | |
807 | + */ | |
808 | + public static String stringEncodeToHex(String str) { | |
809 | + //根据默认编码获取字节数组 | |
810 | + byte[] bytes = str.getBytes(); | |
811 | + StringBuilder sb = new StringBuilder(bytes.length * 2); | |
812 | + //将字节数组中每个字节拆解成2位16进制整数 | |
813 | + for (int i = 0; i < bytes.length; i++) { | |
814 | + sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4)); | |
815 | + sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0)); | |
816 | + } | |
817 | + return sb.toString(); | |
818 | + | |
819 | + } | |
820 | + | |
821 | + /** | |
822 | + * 将16进制数字解码成字符串,适用于所有字符(包括中文) | |
823 | + * | |
824 | + * @param hex 16进制 | |
825 | + * @return | |
826 | + */ | |
827 | + public static String hexDecodeToString(String hex) { | |
828 | + try { | |
829 | + byte[] baKeyword = new byte[hex.length() / 2]; | |
830 | + for (int i = 0; i < baKeyword.length; i++) { | |
831 | + baKeyword[i] = (byte) (0xff & Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16)); | |
832 | + } | |
833 | + return new String(baKeyword, "UTF-8"); | |
834 | + } catch (UnsupportedEncodingException e) { | |
835 | + return null; | |
836 | + } | |
837 | + } | |
838 | + | |
839 | + public static byte[] hexToByteArray(String inHex) { | |
840 | + inHex.replace(" ", ""); | |
841 | + int hexlen = inHex.length(); | |
842 | + byte[] result; | |
843 | + if (hexlen % 2 == 1) { | |
844 | + //奇数 | |
845 | + hexlen++; | |
846 | + result = new byte[(hexlen / 2)]; | |
847 | + inHex = "0" + inHex; | |
848 | + } else { | |
849 | + //偶数 | |
850 | + result = new byte[(hexlen / 2)]; | |
851 | + } | |
852 | + int j = 0; | |
853 | + for (int i = 0; i < hexlen; i += 2) { | |
854 | + result[j] = hexToByte(inHex.substring(i, i + 2)); | |
855 | + j++; | |
856 | + } | |
857 | + return result; | |
858 | + } | |
859 | + | |
860 | + public static byte hexToByte(String inHex) { | |
861 | + return (byte) Integer.parseInt(inHex, 16); | |
862 | + } | |
863 | + | |
864 | + /** | |
865 | + * 数字转16进制字符串 | |
866 | + * @param input | |
867 | + * @return | |
868 | + */ | |
869 | + public static String integerToHex(Integer input){ | |
870 | + byte[] bytes = ByteUtils.getBytes(input); | |
871 | + return ByteUtils.bytesToHex(bytes); | |
872 | + } | |
873 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +public class CrcUtils { | |
4 | +/** | |
5 | + * crc16 for modbus | |
6 | + * @param buf buffer to be crc | |
7 | + * @return crc result word | |
8 | + */ | |
9 | + static int alex_crc16(byte[] buf) { | |
10 | + int i, j; | |
11 | + int c, crc = 0xFFFF; | |
12 | + for (i = 0; i < buf.length; i++) { | |
13 | + c = buf[i] & 0x00FF;//原始数据高8位和初始值进行异或运算保持不变 | |
14 | + crc ^= c; | |
15 | + for (j = 0; j < 8; j++) {//原始数据左移8位 | |
16 | + if ((crc & 0x0001) != 0) { | |
17 | + crc >>= 1; | |
18 | + crc ^= 0xA001;//把处理之后的数据和多项式进行模2除法,求得余数 | |
19 | + } else | |
20 | + crc >>= 1; | |
21 | + } | |
22 | + } | |
23 | + return (crc); | |
24 | + } | |
25 | +/** | |
26 | + * convert string to buffer and append the crc check word to the end of buffer | |
27 | + * @param toSend string to be convert | |
28 | + * @return buffer with crc word, high byte if after low byte according the modbus | |
29 | + */ | |
30 | + public static String getSendBuf(String toSend) { | |
31 | + byte[] bb = ByteUtils.hexToBytes(toSend); | |
32 | + int ri = alex_crc16(bb); | |
33 | + byte[] crc = new byte[2]; | |
34 | + crc[0] = (byte) (0xff & ri); | |
35 | + crc[1] = (byte) ((0xff00 & ri) >> 8); | |
36 | + return ByteUtils.bytesToStr(crc); | |
37 | + } | |
38 | + | |
39 | + | |
40 | + public static void main(String[] args) { | |
41 | + // TODO Auto-generated method stub | |
42 | + String str = "FF0300000004"; | |
43 | + System.out.println(CrcUtils.getSendBuf(str)); | |
44 | + } | |
45 | +} | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | - * <p> | |
3 | + * | |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
... | ... | @@ -40,6 +40,8 @@ import org.thingsboard.server.common.data.DeviceProfile; |
40 | 40 | import org.thingsboard.server.common.data.DeviceTransportType; |
41 | 41 | import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration; |
42 | 42 | import org.thingsboard.server.common.data.id.DeviceId; |
43 | +import org.thingsboard.server.common.data.id.OtaPackageId; | |
44 | +import org.thingsboard.server.common.data.ota.OtaPackageType; | |
43 | 45 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
44 | 46 | import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; |
45 | 47 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
... | ... | @@ -63,7 +65,6 @@ import org.thingsboard.server.transport.tcp.session.TcpGatewaySessionHandler; |
63 | 65 | import org.thingsboard.server.transport.tcp.util.ByteUtils; |
64 | 66 | |
65 | 67 | import java.io.IOException; |
66 | -import java.io.UnsupportedEncodingException; | |
67 | 68 | import java.net.InetSocketAddress; |
68 | 69 | import java.util.List; |
69 | 70 | import java.util.Map; |
... | ... | @@ -156,7 +157,7 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
156 | 157 | if (msg instanceof ByteBuf) { |
157 | 158 | ByteBuf message = (ByteBuf) msg; |
158 | 159 | byte[] byteMsg = ByteUtils.buf2Bytes(message); |
159 | - String msgStr = ByteUtils.getString(byteMsg, ByteUtils.UTF_8); | |
160 | + String msgStr = ByteUtils.bytesToStr(byteMsg); | |
160 | 161 | log.error("会话【{}】收到设备【{}】来自【{}】数据【{}】", sessionId, deviceSessionCtx.getDeviceId(), address, msgStr); |
161 | 162 | deviceSessionCtx.setChannel(ctx); |
162 | 163 | if (deviceSessionCtx.getDeviceInfo() == null || deviceSessionCtx.getDeviceProfile() == null) { |
... | ... | @@ -589,15 +590,10 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
589 | 590 | * @return |
590 | 591 | */ |
591 | 592 | private ChannelFuture pushDeviceMsg(ChannelHandlerContext ctx, String message) { |
592 | - try { | |
593 | - byte[] payloadInBytes = message.getBytes(ByteUtils.UTF_8); | |
594 | - ByteBuf payload = Unpooled.copiedBuffer(payloadInBytes); | |
593 | + byte[] payloadInBytes = ByteUtils.strToBytes(message); | |
594 | + ByteBuf payload = Unpooled.copiedBuffer(payloadInBytes); | |
595 | 595 | |
596 | - return ctx.writeAndFlush(payload); | |
597 | - } catch (UnsupportedEncodingException e) { | |
598 | - log.error(e.getMessage(), e); | |
599 | - throw new RuntimeException(e); | |
600 | - } | |
596 | + return ctx.writeAndFlush(payload); | |
601 | 597 | } |
602 | 598 | |
603 | 599 | |
... | ... | @@ -617,5 +613,4 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
617 | 613 | ChannelHandlerContext ctx = deviceSessionCtx.getChannel(); |
618 | 614 | ctx.close(); |
619 | 615 | } |
620 | - | |
621 | 616 | } | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/adaptors/JsonTcpAdaptor.java
... | ... | @@ -126,8 +126,15 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
126 | 126 | |
127 | 127 | @Override |
128 | 128 | public Optional<TcpDownEntry> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws ExecutionException, InterruptedException { |
129 | - ListenableFuture<Object> result = ctx.getContext().getJsEngine().invokeFunction(ctx.getRpcScriptId(), rpcRequest.getParams()); | |
130 | - return Optional.of(Futures.transform(result, t -> JacksonUtil.fromString(t.toString(), TcpDownEntry.class), MoreExecutors.directExecutor()).get()); | |
129 | +// ListenableFuture<Object> result = ctx.getContext().getJsEngine().invokeFunction(ctx.getRpcScriptId(), rpcRequest.getParams()); | |
130 | +// return Optional.of(Futures.transform(result, t -> JacksonUtil.fromString(t.toString(), TcpDownEntry.class), MoreExecutors.directExecutor()).get()); | |
131 | + String payload = rpcRequest.getParams();//methodThingskit | |
132 | + if (!payload.startsWith("{") && !payload.endsWith("}")) { | |
133 | + payload = payload.replace("\"","");; | |
134 | + } | |
135 | + TcpDownEntry data = new TcpDownEntry(); | |
136 | + data.setDatas(payload); | |
137 | + return Optional.of(data); | |
131 | 138 | } |
132 | 139 | |
133 | 140 | @Override | ... | ... |
... | ... | @@ -2,6 +2,7 @@ package org.thingsboard.server.transport.tcp.adaptors; |
2 | 2 | |
3 | 3 | import lombok.AllArgsConstructor; |
4 | 4 | import lombok.Data; |
5 | +import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
5 | 6 | |
6 | 7 | import java.io.Serializable; |
7 | 8 | import java.util.UUID; |
... | ... | @@ -10,7 +11,6 @@ import java.util.UUID; |
10 | 11 | * 下行脚本 |
11 | 12 | */ |
12 | 13 | @Data |
13 | -@AllArgsConstructor | |
14 | 14 | public class TcpDownEntry implements Serializable { |
15 | 15 | |
16 | 16 | /** |
... | ... | @@ -25,4 +25,7 @@ public class TcpDownEntry implements Serializable { |
25 | 25 | * 下发给设备的最终内容 |
26 | 26 | */ |
27 | 27 | private String datas; |
28 | + | |
29 | + /**下发给设备的字符串编码*/ | |
30 | + private TcpDataTypeEnum dataType; | |
28 | 31 | } | ... | ... |
... | ... | @@ -5,6 +5,7 @@ import org.apache.commons.lang3.ArrayUtils; |
5 | 5 | |
6 | 6 | import java.io.*; |
7 | 7 | import java.nio.charset.Charset; |
8 | +import java.util.regex.Pattern; | |
8 | 9 | |
9 | 10 | /** |
10 | 11 | * @Description :数据类型转换工具类 |
... | ... | @@ -43,6 +44,8 @@ public class ByteUtils { |
43 | 44 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; |
44 | 45 | |
45 | 46 | public static final String UTF_8 = "UTF-8"; |
47 | + | |
48 | + private static String hexString="0123456789ABCDEF"; | |
46 | 49 | /** |
47 | 50 | * 将short整型数值转换为字节数组 |
48 | 51 | * |
... | ... | @@ -269,6 +272,22 @@ public class ByteUtils { |
269 | 272 | return sb.toString(); |
270 | 273 | } |
271 | 274 | |
275 | + private static final String messageRegular = "^[A-Za-z0-9!@#$%^&*()]+$"; | |
276 | + public static String bytesToStr(byte[] bs){ | |
277 | + String result = getString(bs, ByteUtils.UTF_8); | |
278 | + if(!Pattern.compile(messageRegular).matcher(result).matches()){ | |
279 | + result = bytesToHex(bs); | |
280 | + } | |
281 | + return result; | |
282 | + } | |
283 | + | |
284 | + public static byte[] strToBytes(String str){ | |
285 | + if(Pattern.compile("^[A-Fa-f0-9]+$").matcher(str).matches()){ | |
286 | + return hexStr2Bytes(str); | |
287 | + } | |
288 | + return getBytes(str,ByteUtils.UTF_8); | |
289 | + } | |
290 | + | |
272 | 291 | /** |
273 | 292 | * 字节数组取前len个字节转16进制字符串 |
274 | 293 | * |
... | ... | @@ -785,4 +804,64 @@ public class ByteUtils { |
785 | 804 | int highByte = (src & 0x00FF) << 8; |
786 | 805 | return lowByte | highByte; |
787 | 806 | } |
807 | + | |
808 | + /** | |
809 | + * 将字符串编码成16进制数字,适用于所有字符(包括中文) | |
810 | + * @param str 字符串 | |
811 | + * @return | |
812 | + */ | |
813 | + public static String stringEncodeToHex(String str) { | |
814 | + //根据默认编码获取字节数组 | |
815 | + byte[] bytes=str.getBytes(); | |
816 | + StringBuilder sb=new StringBuilder(bytes.length*2); | |
817 | + //将字节数组中每个字节拆解成2位16进制整数 | |
818 | + for(int i=0;i<bytes.length;i++) | |
819 | + { | |
820 | + sb.append(hexString.charAt((bytes[i]&0xf0)>>4)); | |
821 | + sb.append(hexString.charAt((bytes[i]&0x0f)>>0)); | |
822 | + } | |
823 | + return sb.toString(); | |
824 | + | |
825 | + } | |
826 | + | |
827 | + /** | |
828 | + * 将16进制数字解码成字符串,适用于所有字符(包括中文) | |
829 | + * @param hex 16进制 | |
830 | + * @return | |
831 | + */ | |
832 | + public static String hexDecodeToString(String hex) { | |
833 | + try{ | |
834 | + byte[] baKeyword = new byte[hex.length()/2]; | |
835 | + for(int i = 0; i < baKeyword.length; i++) { | |
836 | + baKeyword[i] = (byte)(0xff & Integer.parseInt(hex.substring(i*2, i*2+2),16)); | |
837 | + } | |
838 | + return new String(baKeyword,"UTF-8"); | |
839 | + }catch (UnsupportedEncodingException e){ | |
840 | + return null; | |
841 | + } | |
842 | + } | |
843 | + | |
844 | + public static byte[] hexToByteArray(String inHex){ | |
845 | + inHex.replace(" ",""); | |
846 | + int hexlen = inHex.length(); | |
847 | + byte[] result; | |
848 | + if (hexlen % 2 == 1){ | |
849 | + //奇数 | |
850 | + hexlen++; | |
851 | + result = new byte[(hexlen/2)]; | |
852 | + inHex="0"+inHex; | |
853 | + }else { | |
854 | + //偶数 | |
855 | + result = new byte[(hexlen/2)]; | |
856 | + } | |
857 | + int j=0; | |
858 | + for (int i = 0; i < hexlen; i+=2){ | |
859 | + result[j]=hexToByte(inHex.substring(i,i+2)); | |
860 | + j++; | |
861 | + } | |
862 | + return result; | |
863 | + } | |
864 | + public static byte hexToByte(String inHex){ | |
865 | + return (byte)Integer.parseInt(inHex,16); | |
866 | + } | |
788 | 867 | } | ... | ... |
... | ... | @@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.annotation.TableField; |
5 | 5 | import com.baomidou.mybatisplus.annotation.TableName; |
6 | 6 | import lombok.Data; |
7 | 7 | import lombok.EqualsAndHashCode; |
8 | +import org.apache.ibatis.type.EnumTypeHandler; | |
8 | 9 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; |
10 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
9 | 11 | |
10 | 12 | @EqualsAndHashCode(callSuper = true) |
11 | 13 | @TableName(ModelConstants.Table.TK_CONFIGURATION_CENTER_NAME) |
... | ... | @@ -16,6 +18,13 @@ public class TkConfigurationCenterEntity extends TenantBaseEntity { |
16 | 18 | private String remark; |
17 | 19 | private String organizationId; |
18 | 20 | private String platform; |
21 | + | |
19 | 22 | @TableField(updateStrategy = FieldStrategy.IGNORED) |
20 | 23 | private String thumbnail; |
24 | + | |
25 | + @TableField(typeHandler = EnumTypeHandler.class) | |
26 | + private ViewType viewType; | |
27 | + | |
28 | + @TableField(updateStrategy = FieldStrategy.IGNORED) | |
29 | + private String accessCredentials; | |
21 | 30 | } | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.entities; |
2 | 2 | |
3 | +import com.baomidou.mybatisplus.annotation.FieldStrategy; | |
3 | 4 | import com.baomidou.mybatisplus.annotation.TableField; |
4 | 5 | import com.baomidou.mybatisplus.annotation.TableName; |
5 | 6 | import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; |
... | ... | @@ -30,4 +31,7 @@ public class TkDataBoardEntity extends TenantBaseEntity { |
30 | 31 | private Integer componentNum; |
31 | 32 | |
32 | 33 | private String organizationId; |
34 | + | |
35 | + @TableField(updateStrategy = FieldStrategy.IGNORED) | |
36 | + private String accessCredentials; | |
33 | 37 | } | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableField; | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.Data; | |
8 | +import lombok.EqualsAndHashCode; | |
9 | +import org.apache.ibatis.type.EnumTypeHandler; | |
10 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
11 | +import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; | |
12 | + | |
13 | +@Data | |
14 | +@EqualsAndHashCode(callSuper = true) | |
15 | +@TableName(value = ModelConstants.Table.TK_TASK_CENTER_NAME, autoResultMap = true) | |
16 | +public class TkTaskCenterEntity extends TenantBaseEntity { | |
17 | + private String name; | |
18 | + | |
19 | + @TableField(typeHandler = EnumTypeHandler.class) | |
20 | + private TargetTypeEnum targetType; | |
21 | + | |
22 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
23 | + private JsonNode executeTarget; | |
24 | + | |
25 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
26 | + private JsonNode executeContent; | |
27 | + | |
28 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
29 | + private JsonNode executeTime; | |
30 | + | |
31 | + private Integer state; | |
32 | + | |
33 | + private String remark; | |
34 | +} | ... | ... |
... | ... | @@ -8,6 +8,7 @@ import org.springframework.cache.CacheManager; |
8 | 8 | import org.springframework.stereotype.Service; |
9 | 9 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
10 | 10 | import org.thingsboard.server.common.data.yunteng.dto.SysAreaDTO; |
11 | +import org.thingsboard.server.common.data.yunteng.enums.AreaLevelEnum; | |
11 | 12 | import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; |
12 | 13 | import org.thingsboard.server.dao.yunteng.entities.SysAreaEntity; |
13 | 14 | import org.thingsboard.server.dao.yunteng.mapper.SysAreaMapper; |
... | ... | @@ -30,37 +31,47 @@ public class SysAreaServiceImpl implements SysAreaService { |
30 | 31 | @Override |
31 | 32 | public List<SysAreaDTO> list(SysAreaDTO sysAreaDTO) { |
32 | 33 | String areaKey = sysAreaDTO.getParentId() + "-" + sysAreaDTO.getLevel(); |
33 | - List<SysAreaDTO> result = cacheManager.getCache(FastIotConstants.CacheConfigKey.AREA).get(areaKey,List.class); | |
34 | - if(result == null || result.isEmpty()){ | |
35 | - result = ReflectUtils.sourceToTarget( | |
34 | + List<SysAreaDTO> result = | |
35 | + cacheManager.getCache(FastIotConstants.CacheConfigKey.AREA).get(areaKey, List.class); | |
36 | + if (result == null || result.isEmpty()) { | |
37 | + result = | |
38 | + ReflectUtils.sourceToTarget( | |
36 | 39 | sysAreaMapper.selectList( |
37 | - new LambdaQueryWrapper<SysAreaEntity>() | |
38 | - .eq(sysAreaDTO.getLevel() != null, SysAreaEntity::getLevel, sysAreaDTO.getLevel()) | |
39 | - .eq( | |
40 | - sysAreaDTO.getParentId() != null, | |
41 | - SysAreaEntity::getParentId, | |
42 | - sysAreaDTO.getParentId()) | |
43 | - .eq(sysAreaDTO.getCode() != null, SysAreaEntity::getCode, sysAreaDTO.getCode()) | |
44 | - .like( | |
45 | - StringUtils.isNotEmpty(sysAreaDTO.getName()), | |
46 | - SysAreaEntity::getName, | |
47 | - sysAreaDTO.getName())), | |
40 | + new LambdaQueryWrapper<SysAreaEntity>() | |
41 | + .eq( | |
42 | + sysAreaDTO.getLevel() != null, | |
43 | + SysAreaEntity::getLevel, | |
44 | + sysAreaDTO.getLevel()) | |
45 | + .eq( | |
46 | + sysAreaDTO.getParentId() != null, | |
47 | + SysAreaEntity::getParentId, | |
48 | + sysAreaDTO.getParentId()) | |
49 | + .eq( | |
50 | + sysAreaDTO.getCode() != null, | |
51 | + SysAreaEntity::getCode, | |
52 | + sysAreaDTO.getCode()) | |
53 | + .like( | |
54 | + StringUtils.isNotEmpty(sysAreaDTO.getName()), | |
55 | + SysAreaEntity::getName, | |
56 | + sysAreaDTO.getName())), | |
48 | 57 | SysAreaDTO.class); |
49 | - cacheManager.getCache(FastIotConstants.CacheConfigKey.AREA).put(areaKey,result); | |
58 | + cacheManager.getCache(FastIotConstants.CacheConfigKey.AREA).put(areaKey, result); | |
50 | 59 | } |
51 | 60 | |
52 | - | |
53 | 61 | return result; |
54 | 62 | } |
55 | 63 | |
56 | 64 | @Override |
57 | - public SysAreaDTO getSysAreaInfoByCode(Long code) { | |
65 | + public SysAreaDTO getSysAreaInfoByCode(Long code, AreaLevelEnum levelEnum) { | |
58 | 66 | if (null == code) { |
59 | 67 | return null; |
60 | 68 | } |
61 | 69 | SysAreaDTO target = new SysAreaDTO(); |
62 | 70 | SysAreaEntity source = |
63 | - sysAreaMapper.selectOne(new LambdaQueryWrapper<SysAreaEntity>().eq(SysAreaEntity::getCode, code)); | |
71 | + sysAreaMapper.selectOne( | |
72 | + new LambdaQueryWrapper<SysAreaEntity>() | |
73 | + .eq(SysAreaEntity::getCode, code) | |
74 | + .eq(SysAreaEntity::getLevel, levelEnum)); | |
64 | 75 | if (null != source) { |
65 | 76 | BeanUtils.copyProperties(source, target); |
66 | 77 | } | ... | ... |
... | ... | @@ -10,6 +10,7 @@ import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
10 | 10 | import org.thingsboard.server.common.data.yunteng.dto.SysAreaDTO; |
11 | 11 | import org.thingsboard.server.common.data.yunteng.dto.SysEnterpriseDTO; |
12 | 12 | import org.thingsboard.server.common.data.yunteng.dto.AreaInfoDTO; |
13 | +import org.thingsboard.server.common.data.yunteng.enums.AreaLevelEnum; | |
13 | 14 | import org.thingsboard.server.dao.yunteng.entities.SysEnterpriseEntity; |
14 | 15 | import org.thingsboard.server.dao.yunteng.mapper.SysEnterpriseMapper; |
15 | 16 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; |
... | ... | @@ -34,7 +35,8 @@ public class SysEnterpriseServiceImpl |
34 | 35 | public boolean save(SysEnterpriseDTO sysAppDesignDTO, String tenantId) { |
35 | 36 | SysEnterpriseEntity checkSysEnterprise = |
36 | 37 | baseMapper.selectOne( |
37 | - new LambdaQueryWrapper<SysEnterpriseEntity>().eq(SysEnterpriseEntity::getTenantId, tenantId)); | |
38 | + new LambdaQueryWrapper<SysEnterpriseEntity>() | |
39 | + .eq(SysEnterpriseEntity::getTenantId, tenantId)); | |
38 | 40 | if (null != checkSysEnterprise) { |
39 | 41 | throw new TkDataValidationException(ErrorMessage.DATA_ALREADY_EXISTS.getMessage()); |
40 | 42 | } |
... | ... | @@ -51,19 +53,24 @@ public class SysEnterpriseServiceImpl |
51 | 53 | } |
52 | 54 | if (null != sysEnterpriseDTO.getCodeTown()) { |
53 | 55 | AreaInfoDTO sourceArea = new AreaInfoDTO(); |
54 | - SysAreaDTO town = sysAreaService.getSysAreaInfoByCode(sysEnterpriseDTO.getCodeTown()); | |
56 | + SysAreaDTO town = | |
57 | + sysAreaService.getSysAreaInfoByCode(sysEnterpriseDTO.getCodeTown(), AreaLevelEnum.TOWN); | |
55 | 58 | sourceArea.setNameTown(town.getName()); |
56 | 59 | sourceArea.setCodeTown(town.getCode()); |
57 | - SysAreaDTO county = sysAreaService.getSysAreaInfoByCode(town.getParentId()); | |
60 | + SysAreaDTO county = | |
61 | + sysAreaService.getSysAreaInfoByCode(town.getParentId(), AreaLevelEnum.COUNTY); | |
58 | 62 | sourceArea.setNameCoun(county.getName()); |
59 | 63 | sourceArea.setCodeCoun(county.getCode()); |
60 | - SysAreaDTO city = sysAreaService.getSysAreaInfoByCode(county.getParentId()); | |
64 | + SysAreaDTO city = | |
65 | + sysAreaService.getSysAreaInfoByCode(county.getParentId(), AreaLevelEnum.CITY); | |
61 | 66 | sourceArea.setNameCity(city.getName()); |
62 | 67 | sourceArea.setCodeCity(city.getCode()); |
63 | - SysAreaDTO province = sysAreaService.getSysAreaInfoByCode(city.getParentId()); | |
68 | + SysAreaDTO province = | |
69 | + sysAreaService.getSysAreaInfoByCode(city.getParentId(), AreaLevelEnum.PROVINCE); | |
64 | 70 | sourceArea.setNameProv(province.getName()); |
65 | 71 | sourceArea.setCodeProv(province.getCode()); |
66 | - SysAreaDTO country = sysAreaService.getSysAreaInfoByCode(province.getParentId()); | |
72 | + SysAreaDTO country = | |
73 | + sysAreaService.getSysAreaInfoByCode(province.getParentId(), AreaLevelEnum.COUNTRY); | |
67 | 74 | sourceArea.setNameCountry(country.getName()); |
68 | 75 | sourceArea.setCodeCountry(country.getCode()); |
69 | 76 | |
... | ... | @@ -98,7 +105,8 @@ public class SysEnterpriseServiceImpl |
98 | 105 | if (sysAppDesignDTO.getId() != null) { |
99 | 106 | return baseMapper.update( |
100 | 107 | sysAppDesignDTO.getEntity(SysEnterpriseEntity.class), |
101 | - new LambdaQueryWrapper<SysEnterpriseEntity>().eq(SysEnterpriseEntity::getTenantId, tenantId)) | |
108 | + new LambdaQueryWrapper<SysEnterpriseEntity>() | |
109 | + .eq(SysEnterpriseEntity::getTenantId, tenantId)) | |
102 | 110 | > 0; |
103 | 111 | } else { |
104 | 112 | return save(sysAppDesignDTO, tenantId); | ... | ... |
... | ... | @@ -2,6 +2,8 @@ package org.thingsboard.server.dao.yunteng.impl; |
2 | 2 | |
3 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; |
5 | +import com.google.common.util.concurrent.Futures; | |
6 | +import com.google.common.util.concurrent.ListenableFuture; | |
5 | 7 | import lombok.RequiredArgsConstructor; |
6 | 8 | import org.apache.commons.lang3.StringUtils; |
7 | 9 | import org.quartz.*; |
... | ... | @@ -15,12 +17,14 @@ import org.thingsboard.server.common.data.yunteng.enums.StatusEnum; |
15 | 17 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
16 | 18 | import org.thingsboard.server.dao.util.yunteng.CronUtils; |
17 | 19 | import org.thingsboard.server.dao.util.yunteng.ScheduleUtils; |
20 | +import org.thingsboard.server.dao.yunteng.entities.BaseEntity; | |
18 | 21 | import org.thingsboard.server.dao.yunteng.entities.SysJobEntity; |
19 | 22 | import org.thingsboard.server.dao.yunteng.mapper.SysJobMapper; |
20 | 23 | import org.thingsboard.server.dao.yunteng.service.*; |
21 | 24 | |
22 | 25 | import javax.annotation.PostConstruct; |
23 | 26 | import java.util.*; |
27 | +import java.util.stream.Collectors; | |
24 | 28 | |
25 | 29 | /** 定时任务调度信息 服务层 */ |
26 | 30 | @Service |
... | ... | @@ -35,10 +39,12 @@ public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJobE |
35 | 39 | scheduler.clear(); |
36 | 40 | List<SysJobEntity> jobList = new ArrayList<>(); |
37 | 41 | try { |
38 | - jobList.addAll(baseMapper.selectList( | |
39 | - new LambdaQueryWrapper<SysJobEntity>().eq(SysJobEntity::getStatus, StatusEnum.ENABLE.getIndex()))); | |
40 | - }catch (Exception e){ | |
41 | - //TODO: 兼容ThingsboardInstallApplication。执行数据库脚本前,会跑表不存在异常。 | |
42 | + jobList.addAll( | |
43 | + baseMapper.selectList( | |
44 | + new LambdaQueryWrapper<SysJobEntity>() | |
45 | + .eq(SysJobEntity::getStatus, StatusEnum.ENABLE.getIndex()))); | |
46 | + } catch (Exception e) { | |
47 | + // TODO: 兼容ThingsboardInstallApplication。执行数据库脚本前,会跑表不存在异常。 | |
42 | 48 | } |
43 | 49 | |
44 | 50 | for (SysJobEntity job : jobList) { |
... | ... | @@ -72,15 +78,22 @@ public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJobE |
72 | 78 | public SysJobDTO selectJobById(String id) { |
73 | 79 | |
74 | 80 | return Optional.ofNullable( |
75 | - baseMapper.selectOne(new LambdaQueryWrapper<SysJobEntity>().eq(SysJobEntity::getId, id))) | |
81 | + baseMapper.selectOne( | |
82 | + new LambdaQueryWrapper<SysJobEntity>().eq(SysJobEntity::getId, id))) | |
76 | 83 | .map(obj -> obj.getDTO(SysJobDTO.class)) |
77 | 84 | .orElseThrow( |
78 | - () -> { | |
79 | - throw new TkDataValidationException( | |
80 | - ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage()); | |
81 | - }); | |
85 | + () -> | |
86 | + new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage())); | |
82 | 87 | } |
83 | 88 | |
89 | + @Override | |
90 | + public ListenableFuture<SysJobDTO> selectJobInfoById(String id) { | |
91 | + return Optional.ofNullable( | |
92 | + baseMapper.selectOne( | |
93 | + new LambdaQueryWrapper<SysJobEntity>().eq(SysJobEntity::getId, id))) | |
94 | + .map(obj -> Futures.immediateFuture(obj.getDTO(SysJobDTO.class))) | |
95 | + .orElse(Futures.immediateFuture(null)); | |
96 | + } | |
84 | 97 | /** |
85 | 98 | * 暂停任务 |
86 | 99 | * |
... | ... | @@ -130,6 +143,40 @@ public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJobE |
130 | 143 | } |
131 | 144 | return rows > 0; |
132 | 145 | } |
146 | + /** | |
147 | + * 批量删除任务后,所对应的trigger也将被删除 | |
148 | + * | |
149 | + * @param sourceIds 源ID | |
150 | + * @param jobGroup 分组 | |
151 | + * @param tenantId 租户ID | |
152 | + */ | |
153 | + @Override | |
154 | + @Transactional(rollbackFor = Exception.class) | |
155 | + public boolean deleteJobs(List<String> sourceIds, String jobGroup, String tenantId) | |
156 | + throws SchedulerException { | |
157 | + List<String> jobIds = | |
158 | + Optional.ofNullable( | |
159 | + baseMapper.selectList( | |
160 | + new LambdaQueryWrapper<SysJobEntity>() | |
161 | + .eq(SysJobEntity::getTenantId, tenantId) | |
162 | + .eq(SysJobEntity::getJobGroup, jobGroup) | |
163 | + .in(SysJobEntity::getSourceId, sourceIds))) | |
164 | + .map(list -> list.stream().map(BaseEntity::getId).collect(Collectors.toList())) | |
165 | + .orElse(null); | |
166 | + if (null != jobIds && !jobIds.isEmpty()) { | |
167 | + int rows = baseMapper.deleteBatchIds(jobIds); | |
168 | + if (rows > 0) { | |
169 | + List<JobKey> jobKeys = new ArrayList<>(); | |
170 | + for (String jobId : jobIds) { | |
171 | + jobKeys.add(ScheduleUtils.getJobKey(jobId, jobGroup)); | |
172 | + } | |
173 | + if (!jobKeys.isEmpty()) { | |
174 | + return scheduler.deleteJobs(jobKeys); | |
175 | + } | |
176 | + } | |
177 | + } | |
178 | + return false; | |
179 | + } | |
133 | 180 | |
134 | 181 | /** |
135 | 182 | * 批量删除调度信息 | ... | ... |
... | ... | @@ -12,6 +12,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio |
12 | 12 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
13 | 13 | import org.thingsboard.server.common.data.yunteng.dto.*; |
14 | 14 | import org.thingsboard.server.common.data.yunteng.dto.request.ConfigurationContentInfoDTO; |
15 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
15 | 16 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
16 | 17 | import org.thingsboard.server.dao.yunteng.entities.TkConfigurationCenterEntity; |
17 | 18 | import org.thingsboard.server.dao.yunteng.mapper.ConfigurationCenterMapper; |
... | ... | @@ -128,4 +129,52 @@ public class TkConfigurationCenterServiceImpl |
128 | 129 | ? list.get(FastIotConstants.MagicNumber.ZERO) |
129 | 130 | : null; |
130 | 131 | } |
132 | + | |
133 | + @Override | |
134 | + public ConfigurationCenterDTO getConfigurationCenterInfoById(String id, String tenantId) { | |
135 | + TkConfigurationCenterEntity entity = | |
136 | + baseMapper.selectOne( | |
137 | + new LambdaQueryWrapper<TkConfigurationCenterEntity>() | |
138 | + .eq(TkConfigurationCenterEntity::getTenantId, tenantId) | |
139 | + .eq(TkConfigurationCenterEntity::getId, id)); | |
140 | + if (null == entity) { | |
141 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
142 | + } | |
143 | + return entity.getDTO(ConfigurationCenterDTO.class); | |
144 | + } | |
145 | + | |
146 | + @Override | |
147 | + public boolean isNeedCredentialsForPublicView(String id, String tenantId) { | |
148 | + TkConfigurationCenterEntity entity = | |
149 | + baseMapper.selectOne( | |
150 | + new LambdaQueryWrapper<TkConfigurationCenterEntity>() | |
151 | + .eq(TkConfigurationCenterEntity::getTenantId, tenantId) | |
152 | + .eq(TkConfigurationCenterEntity::getId, id)); | |
153 | + if (null == entity) { | |
154 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
155 | + } | |
156 | + return StringUtils.isNotEmpty(entity.getAccessCredentials()); | |
157 | + } | |
158 | + | |
159 | + @Override | |
160 | + @Transactional | |
161 | + public boolean shareOrMonopolyConfigurationCenter( | |
162 | + boolean isShare, String id, String accessCredentials, String tenantId) { | |
163 | + TkConfigurationCenterEntity entity = | |
164 | + baseMapper.selectOne( | |
165 | + new LambdaQueryWrapper<TkConfigurationCenterEntity>() | |
166 | + .eq(TkConfigurationCenterEntity::getTenantId, tenantId) | |
167 | + .eq(TkConfigurationCenterEntity::getId, id)); | |
168 | + if (null == entity) { | |
169 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
170 | + } | |
171 | + if (isShare) { | |
172 | + entity.setViewType(ViewType.PUBLIC_VIEW); | |
173 | + entity.setAccessCredentials(accessCredentials); | |
174 | + } else { | |
175 | + entity.setViewType(ViewType.PRIVATE_VIEW); | |
176 | + entity.setAccessCredentials(null); | |
177 | + } | |
178 | + return baseMapper.updateById(entity) > FastIotConstants.MagicNumber.ZERO; | |
179 | + } | |
131 | 180 | } | ... | ... |
... | ... | @@ -12,6 +12,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio |
12 | 12 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
13 | 13 | import org.thingsboard.server.common.data.yunteng.dto.*; |
14 | 14 | import org.thingsboard.server.common.data.yunteng.dto.board.ComponentLayoutDTO; |
15 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
15 | 16 | import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; |
16 | 17 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
17 | 18 | import org.thingsboard.server.dao.yunteng.entities.TkDataBoardEntity; |
... | ... | @@ -82,12 +83,11 @@ public class TkDataBoardServiceImpl extends AbstractBaseService<DataBoardMapper, |
82 | 83 | @Transactional |
83 | 84 | public DataBoardDTO saveOrUpdateDataBoard(DataBoardDTO dataBoardDTO) { |
84 | 85 | TkDataBoardEntity dataBoard = dataBoardDTO.getEntity(TkDataBoardEntity.class); |
86 | + if(dataBoardDTO.getViewType().equals(ViewType.PRIVATE_VIEW)){ | |
87 | + dataBoard.setAccessCredentials(null); | |
88 | + } | |
85 | 89 | if (StringUtils.isEmpty(dataBoardDTO.getId())) { |
86 | - try { | |
87 | - baseMapper.insert(dataBoard); | |
88 | - } catch (Exception e) { | |
89 | - e.printStackTrace(); | |
90 | - } | |
90 | + baseMapper.insert(dataBoard); | |
91 | 91 | } else { |
92 | 92 | if (null != dataBoardDTO.getLayout() && !dataBoardDTO.getLayout().isEmpty()) { |
93 | 93 | dataBoard.setLayout(JacksonUtil.convertValue(dataBoardDTO.getLayout(), JsonNode.class)); |
... | ... | @@ -111,9 +111,9 @@ public class TkDataBoardServiceImpl extends AbstractBaseService<DataBoardMapper, |
111 | 111 | @Transactional |
112 | 112 | public boolean deleteDataBoard(DeleteDTO deleteDTO) { |
113 | 113 | dataComponentMapper.delete( |
114 | - new LambdaQueryWrapper<TkDataComponentEntity>() | |
115 | - .eq(TkDataComponentEntity::getTenantId, deleteDTO.getTenantId()) | |
116 | - .in(TkDataComponentEntity::getDataBoardId, deleteDTO.getIds())); | |
114 | + new LambdaQueryWrapper<TkDataComponentEntity>() | |
115 | + .eq(TkDataComponentEntity::getTenantId, deleteDTO.getTenantId()) | |
116 | + .in(TkDataComponentEntity::getDataBoardId, deleteDTO.getIds())); | |
117 | 117 | return baseMapper.delete( |
118 | 118 | new LambdaQueryWrapper<TkDataBoardEntity>() |
119 | 119 | .eq(TkDataBoardEntity::getTenantId, deleteDTO.getTenantId()) |
... | ... | @@ -170,4 +170,38 @@ public class TkDataBoardServiceImpl extends AbstractBaseService<DataBoardMapper, |
170 | 170 | public boolean updateDataBoardComponentNum(String id, String tenantId, int count) { |
171 | 171 | return baseMapper.updateDataBoardComponentNum(id, tenantId, count); |
172 | 172 | } |
173 | + | |
174 | + @Override | |
175 | + public boolean isNeedCredentialsForPublicView(String id, String tenantId) { | |
176 | + TkDataBoardEntity entity = | |
177 | + baseMapper.selectOne( | |
178 | + new LambdaQueryWrapper<TkDataBoardEntity>() | |
179 | + .eq(TkDataBoardEntity::getTenantId, tenantId) | |
180 | + .eq(TkDataBoardEntity::getId, id)); | |
181 | + if (null == entity) { | |
182 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
183 | + } | |
184 | + return StringUtils.isNotEmpty(entity.getAccessCredentials()); | |
185 | + } | |
186 | + | |
187 | + @Override | |
188 | + public boolean shareOrMonopolyDataBoard( | |
189 | + boolean isShare, String id, String accessCredentials, String tenantId) { | |
190 | + TkDataBoardEntity entity = | |
191 | + baseMapper.selectOne( | |
192 | + new LambdaQueryWrapper<TkDataBoardEntity>() | |
193 | + .eq(TkDataBoardEntity::getTenantId, tenantId) | |
194 | + .eq(TkDataBoardEntity::getId, id)); | |
195 | + if (null == entity) { | |
196 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
197 | + } | |
198 | + if (isShare) { | |
199 | + entity.setViewType(ViewType.PUBLIC_VIEW); | |
200 | + entity.setAccessCredentials(accessCredentials); | |
201 | + } else { | |
202 | + entity.setViewType(ViewType.PRIVATE_VIEW); | |
203 | + entity.setAccessCredentials(null); | |
204 | + } | |
205 | + return baseMapper.updateById(entity) > FastIotConstants.MagicNumber.ZERO; | |
206 | + } | |
173 | 207 | } | ... | ... |
... | ... | @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; |
5 | 5 | import lombok.RequiredArgsConstructor; |
6 | 6 | import lombok.extern.slf4j.Slf4j; |
7 | +import org.apache.commons.lang3.StringUtils; | |
7 | 8 | import org.springframework.stereotype.Service; |
8 | 9 | import org.springframework.transaction.annotation.Transactional; |
9 | 10 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
... | ... | @@ -11,9 +12,9 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio |
11 | 12 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
12 | 13 | import org.thingsboard.server.common.data.yunteng.dto.*; |
13 | 14 | import org.thingsboard.server.common.data.yunteng.dto.request.TkDataViewContentInfoDTO; |
15 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
14 | 16 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
15 | 17 | import org.thingsboard.server.dao.yunteng.entities.TkDataViewEntity; |
16 | -import org.thingsboard.server.dao.yunteng.entities.TkDataViewInterfaceEntity; | |
17 | 18 | import org.thingsboard.server.dao.yunteng.mapper.TkDataViewMapper; |
18 | 19 | import org.thingsboard.server.dao.yunteng.mapper.OrganizationMapper; |
19 | 20 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; |
... | ... | @@ -31,116 +32,161 @@ import java.util.stream.Collectors; |
31 | 32 | @Slf4j |
32 | 33 | @Service |
33 | 34 | @RequiredArgsConstructor |
34 | -public class TkDataViewServiceImpl | |
35 | - extends AbstractBaseService<TkDataViewMapper, TkDataViewEntity> | |
36 | - implements TkDataViewService { | |
37 | - private final OrganizationMapper organizationMapper; | |
38 | - private final TkDataViewContentService ytDataViewContentService; | |
39 | - private final UserOrganizationMappingService userOrganizationMappingService; | |
35 | +public class TkDataViewServiceImpl extends AbstractBaseService<TkDataViewMapper, TkDataViewEntity> | |
36 | + implements TkDataViewService { | |
37 | + private final OrganizationMapper organizationMapper; | |
38 | + private final TkDataViewContentService ytDataViewContentService; | |
39 | + private final UserOrganizationMappingService userOrganizationMappingService; | |
40 | 40 | |
41 | - @Override | |
42 | - public TkPageData<TkDataViewDTO> page( | |
43 | - Map<String, Object> queryMap, boolean tenantAdmin) { | |
44 | - List<String> organizationIds = null; | |
45 | - if (null != queryMap.get("organizationId")) { | |
46 | - String organizationId = (String) queryMap.get("organizationId"); | |
47 | - List<OrganizationDTO> organizationList = | |
48 | - organizationMapper.findOrganizationTreeList( | |
49 | - (String) queryMap.get("tenantId"), new HashSet<>(List.of(organizationId))); | |
50 | - if (organizationList.size() == FastIotConstants.MagicNumber.ZERO) { | |
51 | - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
52 | - } | |
53 | - organizationIds = | |
54 | - organizationList.stream().map(BaseDTO::getId).distinct().collect(Collectors.toList()); | |
55 | - } | |
56 | - if (!tenantAdmin && null != queryMap.get("userId")) { | |
57 | - // 获取客户的组织关系 | |
58 | - String userId = (String) queryMap.get("userId"); | |
59 | - organizationIds = userOrganizationMappingService.compareOrganizationIdsByCustomerId(organizationIds, userId); | |
60 | - } | |
61 | - if (null != organizationIds && organizationIds.size() > FastIotConstants.MagicNumber.ZERO) { | |
62 | - queryMap.put("organizationIds", organizationIds); | |
63 | - } | |
64 | - IPage<TkDataViewEntity> page = | |
65 | - getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); | |
66 | - IPage<TkDataViewDTO> DataViewIPage = | |
67 | - baseMapper.getDataViewPage(page, queryMap); | |
68 | - return getPageData(DataViewIPage, TkDataViewDTO.class); | |
41 | + @Override | |
42 | + public TkPageData<TkDataViewDTO> page(Map<String, Object> queryMap, boolean tenantAdmin) { | |
43 | + List<String> organizationIds = null; | |
44 | + if (null != queryMap.get("organizationId")) { | |
45 | + String organizationId = (String) queryMap.get("organizationId"); | |
46 | + List<OrganizationDTO> organizationList = | |
47 | + organizationMapper.findOrganizationTreeList( | |
48 | + (String) queryMap.get("tenantId"), new HashSet<>(List.of(organizationId))); | |
49 | + if (organizationList.size() == FastIotConstants.MagicNumber.ZERO) { | |
50 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
51 | + } | |
52 | + organizationIds = | |
53 | + organizationList.stream().map(BaseDTO::getId).distinct().collect(Collectors.toList()); | |
69 | 54 | } |
55 | + if (!tenantAdmin && null != queryMap.get("userId")) { | |
56 | + // 获取客户的组织关系 | |
57 | + String userId = (String) queryMap.get("userId"); | |
58 | + organizationIds = | |
59 | + userOrganizationMappingService.compareOrganizationIdsByCustomerId( | |
60 | + organizationIds, userId); | |
61 | + } | |
62 | + if (null != organizationIds && organizationIds.size() > FastIotConstants.MagicNumber.ZERO) { | |
63 | + queryMap.put("organizationIds", organizationIds); | |
64 | + } | |
65 | + IPage<TkDataViewEntity> page = | |
66 | + getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); | |
67 | + IPage<TkDataViewDTO> DataViewIPage = baseMapper.getDataViewPage(page, queryMap); | |
68 | + return getPageData(DataViewIPage, TkDataViewDTO.class); | |
69 | + } | |
70 | + | |
71 | + @Override | |
72 | + @Transactional | |
73 | + public TkDataViewDTO saveDataView(TkDataViewDTO tkDataViewDTO) { | |
74 | + TkDataViewEntity dataView = tkDataViewDTO.getEntity(TkDataViewEntity.class); | |
75 | + dataView.setState(0); | |
76 | + baseMapper.insert(dataView); | |
77 | + TkDataViewContentDTO contentDTO = new TkDataViewContentDTO(); | |
78 | + contentDTO.setTenantId(dataView.getTenantId()); | |
79 | + contentDTO.setViewId(dataView.getId()); | |
80 | + ytDataViewContentService.saveDataViewContent(contentDTO); | |
81 | + return tkDataViewDTO; | |
82 | + } | |
70 | 83 | |
71 | - @Override | |
72 | - @Transactional | |
73 | - public TkDataViewDTO saveDataView(TkDataViewDTO TkDataViewDTO) { | |
74 | - TkDataViewEntity dataView = | |
75 | - TkDataViewDTO.getEntity(TkDataViewEntity.class); | |
76 | - dataView.setState(0); | |
77 | - baseMapper.insert(dataView); | |
78 | - TkDataViewContentDTO contentDTO = new TkDataViewContentDTO(); | |
79 | - contentDTO.setTenantId(dataView.getTenantId()); | |
80 | - contentDTO.setViewId(dataView.getId()); | |
81 | - contentDTO.setContent( | |
82 | - "<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/></root></mxGraphModel>"); | |
83 | - ytDataViewContentService.saveDataViewContent(contentDTO); | |
84 | - return TkDataViewDTO; | |
84 | + @Override | |
85 | + @Transactional | |
86 | + public TkDataViewDTO updateDataView(TkDataViewDTO tkDataViewDTO) { | |
87 | + TkDataViewEntity dataView = baseMapper.selectById(tkDataViewDTO.getId()); | |
88 | + if (!dataView.getTenantId().equals(tkDataViewDTO.getTenantId())) { | |
89 | + throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
85 | 90 | } |
91 | + //设计不修改状态 | |
92 | + tkDataViewDTO.setViewType(null); | |
93 | + baseMapper.updateById(tkDataViewDTO.getEntity(TkDataViewEntity.class)); | |
94 | + return tkDataViewDTO; | |
95 | + } | |
86 | 96 | |
87 | - @Override | |
88 | - @Transactional | |
89 | - public TkDataViewDTO updateDataView(TkDataViewDTO TkDataViewDTO) { | |
90 | - TkDataViewEntity DataView = baseMapper.selectById(TkDataViewDTO.getId()); | |
91 | - if (!DataView.getTenantId().equals(TkDataViewDTO.getTenantId())) { | |
92 | - throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
93 | - } | |
94 | - baseMapper.updateById(TkDataViewDTO.getEntity(TkDataViewEntity.class)); | |
95 | - return TkDataViewDTO; | |
97 | + @Override | |
98 | + @Transactional | |
99 | + public boolean deleteDataView(DeleteDTO deleteDTO) { | |
100 | + List<TkDataViewEntity> centerList = | |
101 | + baseMapper.selectList( | |
102 | + new LambdaQueryWrapper<TkDataViewEntity>() | |
103 | + .in(TkDataViewEntity::getId, deleteDTO.getIds())); | |
104 | + for (TkDataViewEntity center : centerList) { | |
105 | + if (!center.getTenantId().equals(deleteDTO.getTenantId())) { | |
106 | + throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
107 | + } | |
96 | 108 | } |
109 | + ytDataViewContentService.deleteDataViewContentByCenterId(deleteDTO.getIds()); | |
110 | + return baseMapper.deleteBatchIds(deleteDTO.getIds()) > FastIotConstants.MagicNumber.ZERO; | |
111 | + } | |
97 | 112 | |
98 | - @Override | |
99 | - @Transactional | |
100 | - public boolean deleteDataView(DeleteDTO deleteDTO) { | |
101 | - List<TkDataViewEntity> centerList = | |
102 | - baseMapper.selectList( | |
103 | - new LambdaQueryWrapper<TkDataViewEntity>() | |
104 | - .in(TkDataViewEntity::getId, deleteDTO.getIds())); | |
105 | - for (TkDataViewEntity center : centerList) { | |
106 | - if (!center.getTenantId().equals(deleteDTO.getTenantId())) { | |
107 | - throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
108 | - } | |
109 | - } | |
110 | - ytDataViewContentService.deleteDataViewContentByCenterId(deleteDTO.getIds()); | |
111 | - return baseMapper.deleteBatchIds(deleteDTO.getIds()) > FastIotConstants.MagicNumber.ZERO; | |
113 | + @Override | |
114 | + public TkDataViewContentInfoDTO getDataViewInfos(String id, String tenantId) { | |
115 | + List<TkDataViewContentInfoDTO> list = baseMapper.getDataViewInfoById(id, tenantId); | |
116 | + return list.size() > FastIotConstants.MagicNumber.ZERO | |
117 | + ? list.get(FastIotConstants.MagicNumber.ZERO) | |
118 | + : null; | |
119 | + } | |
120 | + | |
121 | + @Override | |
122 | + public TkDataViewDTO getDataViewById(String id, String tenantId) { | |
123 | + TkDataViewEntity entity = | |
124 | + baseMapper.selectOne( | |
125 | + new LambdaQueryWrapper<TkDataViewEntity>() | |
126 | + .eq(TkDataViewEntity::getTenantId, tenantId) | |
127 | + .eq(TkDataViewEntity::getId, id)); | |
128 | + if (null == entity) { | |
129 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
112 | 130 | } |
131 | + return entity.getDTO(TkDataViewDTO.class); | |
132 | + } | |
113 | 133 | |
114 | - @Override | |
115 | - public TkDataViewContentInfoDTO getDataViewInfos(String id, String tenantId) { | |
116 | - List<TkDataViewContentInfoDTO> list = baseMapper.getDataViewInfoById(id, tenantId); | |
117 | - return list.size() > FastIotConstants.MagicNumber.ZERO | |
118 | - ? list.get(FastIotConstants.MagicNumber.ZERO) | |
119 | - : null; | |
134 | + @Override | |
135 | + public boolean isNeedCredentialsForPublicView(String id, String tenantId) { | |
136 | + TkDataViewEntity entity = | |
137 | + baseMapper.selectOne( | |
138 | + new LambdaQueryWrapper<TkDataViewEntity>() | |
139 | + .eq(TkDataViewEntity::getTenantId, tenantId) | |
140 | + .eq(TkDataViewEntity::getId, id)); | |
141 | + if (null == entity) { | |
142 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
120 | 143 | } |
144 | + return StringUtils.isNotEmpty(entity.getAccessCredentials()); | |
145 | + } | |
121 | 146 | |
147 | + @Override | |
148 | + @Transactional | |
149 | + public boolean shareOrMonopolyDataViewCenter( | |
150 | + boolean isShare, String id, String accessCredentials, String tenantId) { | |
151 | + TkDataViewEntity entity = | |
152 | + baseMapper.selectOne( | |
153 | + new LambdaQueryWrapper<TkDataViewEntity>() | |
154 | + .eq(TkDataViewEntity::getTenantId, tenantId) | |
155 | + .eq(TkDataViewEntity::getId, id)); | |
156 | + if (null == entity) { | |
157 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
158 | + } | |
159 | + if (isShare) { | |
160 | + entity.setViewType(ViewType.PUBLIC_VIEW); | |
161 | + entity.setAccessCredentials(accessCredentials); | |
162 | + } else { | |
163 | + entity.setViewType(ViewType.PRIVATE_VIEW); | |
164 | + entity.setAccessCredentials(null); | |
165 | + } | |
166 | + return baseMapper.updateById(entity) > FastIotConstants.MagicNumber.ZERO; | |
167 | + } | |
122 | 168 | |
123 | - @Override | |
124 | - public boolean publishDataView(String id, String tenantId) { | |
125 | - TkDataViewEntity dataView = baseMapper.selectById(id); | |
126 | - if (!dataView.getTenantId().equals(tenantId)) { | |
127 | - throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
128 | - } | |
129 | - //Modify dataView state is publish | |
130 | - dataView.setState(1); | |
131 | - int resultInt = baseMapper.updateById(dataView); | |
132 | - return resultInt > 0 ? true : false; | |
169 | + @Override | |
170 | + public boolean publishDataView(String id, String tenantId) { | |
171 | + TkDataViewEntity dataView = baseMapper.selectById(id); | |
172 | + if (!dataView.getTenantId().equals(tenantId)) { | |
173 | + throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
133 | 174 | } |
175 | + // Modify dataView state is publish | |
176 | + dataView.setState(FastIotConstants.StateValue.PUBLISH); | |
177 | + int resultInt = baseMapper.updateById(dataView); | |
178 | + return resultInt > FastIotConstants.MagicNumber.ZERO; | |
179 | + } | |
134 | 180 | |
135 | - @Override | |
136 | - public boolean cancelPublishDataView(String id, String tenantId) { | |
137 | - TkDataViewEntity dataView = baseMapper.selectById(id); | |
138 | - if (!dataView.getTenantId().equals(tenantId)) { | |
139 | - throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
140 | - } | |
141 | - //Modify dataView state is cancelPublish | |
142 | - dataView.setState(0); | |
143 | - int resultInt = baseMapper.updateById(dataView); | |
144 | - return resultInt > 0 ? true : false; | |
181 | + @Override | |
182 | + public boolean cancelPublishDataView(String id, String tenantId) { | |
183 | + TkDataViewEntity dataView = baseMapper.selectById(id); | |
184 | + if (!dataView.getTenantId().equals(tenantId)) { | |
185 | + throw new TkDataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
145 | 186 | } |
187 | + // Modify dataView state is cancelPublish | |
188 | + dataView.setState(FastIotConstants.StateValue.CANCEL_PUBLISH); | |
189 | + int resultInt = baseMapper.updateById(dataView); | |
190 | + return resultInt > FastIotConstants.MagicNumber.ZERO; | |
191 | + } | |
146 | 192 | } | ... | ... |
... | ... | @@ -9,17 +9,17 @@ import org.apache.commons.lang3.StringUtils; |
9 | 9 | import org.springframework.stereotype.Service; |
10 | 10 | import org.springframework.transaction.annotation.Transactional; |
11 | 11 | import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration; |
12 | +import org.thingsboard.server.common.data.id.EntityId; | |
12 | 13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
13 | 14 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; |
14 | 15 | import org.thingsboard.server.common.data.yunteng.constant.QueryConstant; |
15 | 16 | import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; |
16 | 17 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
17 | -import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
18 | -import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; | |
19 | -import org.thingsboard.server.common.data.yunteng.dto.TkCustomerDeviceDTO; | |
20 | -import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; | |
18 | +import org.thingsboard.server.common.data.yunteng.dto.*; | |
21 | 19 | import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; |
22 | 20 | import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; |
21 | +import org.thingsboard.server.common.data.yunteng.utils.ByteUtils; | |
22 | +import org.thingsboard.server.common.data.yunteng.utils.CrcUtils; | |
23 | 23 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
24 | 24 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity; |
25 | 25 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceScriptEntity; |
... | ... | @@ -246,11 +246,12 @@ public class TkDeviceScriptServiceImpl |
246 | 246 | } |
247 | 247 | |
248 | 248 | @Override |
249 | - public List<TkDeviceScriptDTO> findDeviceScript(String tenantId) { | |
249 | + public List<TkDeviceScriptDTO> findDeviceScript(String tenantId,TkScriptFunctionType scriptType) { | |
250 | 250 | LambdaQueryWrapper<TkDeviceScriptEntity> queryWrapper = |
251 | 251 | new QueryWrapper<TkDeviceScriptEntity>() |
252 | 252 | .lambda() |
253 | - .eq(TkDeviceScriptEntity::getTenantId, tenantId); | |
253 | + .eq(scriptType!=null,TkDeviceScriptEntity::getScriptType, scriptType).and(s->s | |
254 | + .eq(TkDeviceScriptEntity::getTenantId, tenantId).or(r->r.eq(TkDeviceScriptEntity::getTenantId, EntityId.NULL_UUID.toString()))); | |
254 | 255 | return baseMapper.selectList(queryWrapper).stream() |
255 | 256 | .map(item -> item.getDTO(TkDeviceScriptDTO.class)) |
256 | 257 | .collect(Collectors.toList()); |
... | ... | @@ -295,4 +296,68 @@ public class TkDeviceScriptServiceImpl |
295 | 296 | } |
296 | 297 | return scriptIds; |
297 | 298 | } |
299 | + | |
300 | + @Override | |
301 | + public String modbus(TkDeviceRpcDTO config) { | |
302 | + StringBuilder result = new StringBuilder(config.getDeviceCode()); | |
303 | + String functionCode = config.getMethod(); | |
304 | + result.append(functionCode); | |
305 | + String addrStr = ByteUtils.integerToHex(config.getRegisterAddr()); | |
306 | + result.append(addrStr.substring(addrStr.length()-4)); | |
307 | + | |
308 | + List<Integer> values = config.getRegisterVales(); | |
309 | + if(values ==null || values.isEmpty()){ | |
310 | + //读寄存器数据 | |
311 | + result.append(modelHex(config.getRegisterNum())); | |
312 | + }else if(values.size() == 1){ | |
313 | + //单个写入 | |
314 | + result.append(modelHex(values.get(0))); | |
315 | + }else{ | |
316 | + //多个写入 | |
317 | + result.append(modelHex(config.getRegisterNum())); | |
318 | + result.append(multData(functionCode,values)); | |
319 | + } | |
320 | + result.append(CrcUtils.getSendBuf(result.toString())); | |
321 | + | |
322 | + | |
323 | + return result.toString(); | |
324 | + } | |
325 | + | |
326 | + | |
327 | + private String modelHex(Integer max){ | |
328 | + String addrStr = ByteUtils.integerToHex(max); | |
329 | + return addrStr.substring(addrStr.length()-4); | |
330 | + } | |
331 | + | |
332 | + private String dataLength(Integer max){ | |
333 | + String addrStr = ByteUtils.integerToHex(max); | |
334 | + return addrStr.substring(addrStr.length()-2); | |
335 | + } | |
336 | + private String multData(String functionCode,List<Integer>datas){ | |
337 | + StringBuilder dataStr = new StringBuilder(); | |
338 | + if("16".equals(functionCode)){ | |
339 | + dataStr.append(dataLength(datas.size()*2)); | |
340 | + for(Integer item: datas){ | |
341 | + dataStr.append(modelHex(item)); | |
342 | + } | |
343 | + }else{ | |
344 | + Integer filter = datas.size()%8; | |
345 | + Integer num = datas.size()/8; | |
346 | + dataStr.append(dataLength(filter == 0 ?num:num+1)); | |
347 | + byte one = 0x00; | |
348 | + int index =1; | |
349 | + for(Integer item: datas){ | |
350 | + byte byteVal=item.byteValue(); | |
351 | + one =(byte)(one<< 1); | |
352 | + one ^= byteVal; | |
353 | + if(index%8==0 || datas.size() == index){ | |
354 | + dataStr.append(ByteUtils.byteToHex(one)); | |
355 | + one=0x00; | |
356 | + } | |
357 | + index++; | |
358 | + | |
359 | + } | |
360 | + } | |
361 | + return dataStr.toString(); | |
362 | + } | |
298 | 363 | } | ... | ... |
... | ... | @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
5 | 5 | import com.baomidou.mybatisplus.core.metadata.IPage; |
6 | 6 | import com.fasterxml.jackson.databind.JsonNode; |
7 | +import com.google.common.util.concurrent.Futures; | |
8 | +import com.google.common.util.concurrent.ListenableFuture; | |
7 | 9 | import lombok.RequiredArgsConstructor; |
8 | 10 | import lombok.extern.slf4j.Slf4j; |
9 | 11 | import org.apache.commons.lang3.StringUtils; |
... | ... | @@ -365,7 +367,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
365 | 367 | List<String> queryOrganizationIds = organizationAllIds(tenantId, organizationId); |
366 | 368 | queryMap.put("organizationIds", queryOrganizationIds); |
367 | 369 | } |
368 | - //用于数据流转已选,待选过滤============开始 | |
370 | + // 用于数据流转已选,待选过滤============开始 | |
369 | 371 | if (StringUtils.isNotEmpty(convertConfigId)) { |
370 | 372 | ConvertConfigDTO configDTO = |
371 | 373 | convertConfigService.findConvertConfigDTOById(tenantId, convertConfigId); |
... | ... | @@ -382,7 +384,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
382 | 384 | } |
383 | 385 | } |
384 | 386 | } |
385 | - //用于数据流转已选,待选过滤============结束 | |
387 | + // 用于数据流转已选,待选过滤============结束 | |
386 | 388 | IPage<TkDeviceEntity> page = |
387 | 389 | getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); |
388 | 390 | IPage<DeviceDTO> deviceIPage = baseMapper.getDevicePage(page, queryMap); |
... | ... | @@ -668,12 +670,16 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
668 | 670 | public List<String> rpcDevices(String tenantId, String organizationId, String projectId) { |
669 | 671 | List<String> orgIds = organizationAllIds(tenantId, organizationId); |
670 | 672 | |
671 | - List<TkDeviceEntity> organizationDevices = baseMapper.selectList(new LambdaQueryWrapper<TkDeviceEntity>().eq(TkDeviceEntity::getDeviceProfileId, projectId).in(TkDeviceEntity::getOrganizationId,orgIds)); | |
673 | + List<TkDeviceEntity> organizationDevices = | |
674 | + baseMapper.selectList( | |
675 | + new LambdaQueryWrapper<TkDeviceEntity>() | |
676 | + .eq(TkDeviceEntity::getDeviceProfileId, projectId) | |
677 | + .in(TkDeviceEntity::getOrganizationId, orgIds)); | |
672 | 678 | List<String> allDevices = new ArrayList<>(); |
673 | - if(organizationDevices != null && !organizationDevices.isEmpty()){ | |
679 | + if (organizationDevices != null && !organizationDevices.isEmpty()) { | |
674 | 680 | for (TkDeviceEntity item : organizationDevices) { |
675 | 681 | DeviceTypeEnum deviceType = item.getDeviceType(); |
676 | - if(DeviceTypeEnum.SENSOR.equals(deviceType)){ | |
682 | + if (DeviceTypeEnum.SENSOR.equals(deviceType)) { | |
677 | 683 | allDevices.add(item.getGatewayId()); |
678 | 684 | continue; |
679 | 685 | } |
... | ... | @@ -682,4 +688,26 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
682 | 688 | } |
683 | 689 | return allDevices; |
684 | 690 | } |
691 | + | |
692 | + @Override | |
693 | + public ListenableFuture<List<DeviceDTO>> findDeviceListByDeviceProfileId( | |
694 | + String deviceProfileId, String tenantId) { | |
695 | + if (StringUtils.isEmpty(deviceProfileId) || StringUtils.isEmpty(tenantId)) { | |
696 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
697 | + } | |
698 | + List<DeviceDTO> devices = new ArrayList<>(); | |
699 | + List<TkDeviceEntity> entityList = | |
700 | + baseMapper.selectList( | |
701 | + new LambdaQueryWrapper<TkDeviceEntity>() | |
702 | + .eq(TkDeviceEntity::getTenantId, tenantId) | |
703 | + .eq(TkDeviceEntity::getDeviceProfileId, deviceProfileId)); | |
704 | + return Optional.ofNullable(entityList) | |
705 | + .map( | |
706 | + list -> | |
707 | + Futures.immediateFuture( | |
708 | + list.stream() | |
709 | + .map(obj -> obj.getDTO(DeviceDTO.class)) | |
710 | + .collect(Collectors.toList()))) | |
711 | + .orElse(Futures.immediateFuture(devices)); | |
712 | + } | |
685 | 713 | } | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.google.common.base.Objects; | |
4 | +import lombok.RequiredArgsConstructor; | |
5 | +import org.springframework.stereotype.Service; | |
6 | +import org.thingsboard.server.common.data.StringUtils; | |
7 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
8 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
9 | +import org.thingsboard.server.common.data.yunteng.dto.ConfigurationCenterDTO; | |
10 | +import org.thingsboard.server.common.data.yunteng.dto.DataBoardDTO; | |
11 | +import org.thingsboard.server.common.data.yunteng.dto.DataComponentDTO; | |
12 | +import org.thingsboard.server.common.data.yunteng.dto.TkDataViewDTO; | |
13 | +import org.thingsboard.server.common.data.yunteng.dto.board.MoreDataComponentInfoDTO; | |
14 | +import org.thingsboard.server.common.data.yunteng.dto.request.ConfigurationContentInfoDTO; | |
15 | +import org.thingsboard.server.common.data.yunteng.dto.request.TkDataViewContentInfoDTO; | |
16 | +import org.thingsboard.server.common.data.yunteng.enums.ShareViewType; | |
17 | +import org.thingsboard.server.common.data.yunteng.enums.ViewType; | |
18 | +import org.thingsboard.server.dao.yunteng.service.*; | |
19 | + | |
20 | +import java.util.List; | |
21 | + | |
22 | +@Service | |
23 | +@RequiredArgsConstructor | |
24 | +public class TkShareViewServiceImpl implements TkShareViewService { | |
25 | + | |
26 | + private final TkDataComponentService tkDataComponentService; | |
27 | + private final TkDataBoardService tkDataBoardService; | |
28 | + private final TkDataViewService tkDataViewService; | |
29 | + private final TkConfigurationCenterService tkConfigurationCenterService; | |
30 | + | |
31 | + private MoreDataComponentInfoDTO viewDataComponentsByBoardId( | |
32 | + String boardId, String accessCredentials, String tenantId) { | |
33 | + DataBoardDTO dto = tkDataBoardService.findDataBoardInfoById(boardId, tenantId); | |
34 | + checkParams(dto, dto.getViewType(), dto.getAccessCredentials(), accessCredentials); | |
35 | + MoreDataComponentInfoDTO moreDataComponentInfoDTO = new MoreDataComponentInfoDTO(); | |
36 | + List<DataComponentDTO> data = | |
37 | + tkDataComponentService.getDataComponentsByBoardId(tenantId, boardId); | |
38 | + moreDataComponentInfoDTO.setComponentLayout(dto.getLayout()); | |
39 | + moreDataComponentInfoDTO.setComponentData(data); | |
40 | + return moreDataComponentInfoDTO; | |
41 | + } | |
42 | + | |
43 | + private ConfigurationContentInfoDTO viewConfigurationById( | |
44 | + String id, String accessCredentials, String tenantId) { | |
45 | + ConfigurationCenterDTO centerDTO = | |
46 | + tkConfigurationCenterService.getConfigurationCenterInfoById(id, tenantId); | |
47 | + checkParams( | |
48 | + centerDTO, centerDTO.getViewType(), centerDTO.getAccessCredentials(), accessCredentials); | |
49 | + return tkConfigurationCenterService.getConfigurationInfos(id, tenantId); | |
50 | + } | |
51 | + | |
52 | + private TkDataViewContentInfoDTO viewDataViewInfosById( | |
53 | + String id, String accessCredentials, String tenantId) { | |
54 | + TkDataViewDTO dto = tkDataViewService.getDataViewById(id, tenantId); | |
55 | + checkParams(dto, dto.getViewType(), dto.getAccessCredentials(), accessCredentials); | |
56 | + return tkDataViewService.getDataViewInfos(id, tenantId); | |
57 | + } | |
58 | + | |
59 | + private void checkParams( | |
60 | + Object dto, ViewType viewType, String targetCredentials, String sourceCredentials) { | |
61 | + if (null == dto) { | |
62 | + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage()); | |
63 | + } | |
64 | + if (!Objects.equal(viewType, ViewType.PUBLIC_VIEW)) { | |
65 | + throw new TkDataValidationException(ErrorMessage.CURRENT_VIEW_IS_PRIVATE.getMessage()); | |
66 | + } | |
67 | + if (StringUtils.isNotEmpty(targetCredentials)) { | |
68 | + if (!Objects.equal(targetCredentials, sourceCredentials)) { | |
69 | + throw new TkDataValidationException( | |
70 | + ErrorMessage.CURRENT_URL_REQUIRES_PERMISSION.getMessage()); | |
71 | + } | |
72 | + } | |
73 | + } | |
74 | + | |
75 | + @Override | |
76 | + public Object viewShareDataById( | |
77 | + ShareViewType shareViewType, String id, String accessCredentials, String tenantId) { | |
78 | + Object result; | |
79 | + switch (shareViewType) { | |
80 | + case DATA_BOARD: | |
81 | + result = viewDataComponentsByBoardId(id, accessCredentials, tenantId); | |
82 | + break; | |
83 | + case SCADA: | |
84 | + result = viewConfigurationById(id, accessCredentials, tenantId); | |
85 | + break; | |
86 | + case LARGE_SCREEN: | |
87 | + result = viewDataViewInfosById(id, accessCredentials, tenantId); | |
88 | + break; | |
89 | + default: | |
90 | + throw new TkDataValidationException(ErrorMessage.SHARE_VIEW_TYPE_NOT_EXIST.getMessage()); | |
91 | + } | |
92 | + return result; | |
93 | + } | |
94 | + | |
95 | + @Override | |
96 | + public boolean checkPublicViewNeedCredentials( | |
97 | + ShareViewType type, String viewId, String tenantId) { | |
98 | + boolean result; | |
99 | + switch (type) { | |
100 | + case SCADA: | |
101 | + result = tkConfigurationCenterService.isNeedCredentialsForPublicView(viewId, tenantId); | |
102 | + break; | |
103 | + case DATA_BOARD: | |
104 | + result = tkDataBoardService.isNeedCredentialsForPublicView(viewId, tenantId); | |
105 | + break; | |
106 | + case LARGE_SCREEN: | |
107 | + result = tkDataViewService.isNeedCredentialsForPublicView(viewId, tenantId); | |
108 | + break; | |
109 | + default: | |
110 | + throw new TkDataValidationException(ErrorMessage.SHARE_VIEW_TYPE_NOT_EXIST.getMessage()); | |
111 | + } | |
112 | + return result; | |
113 | + } | |
114 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import com.fasterxml.jackson.databind.JsonNode; | |
6 | +import com.google.common.util.concurrent.Futures; | |
7 | +import com.google.common.util.concurrent.ListenableFuture; | |
8 | +import lombok.RequiredArgsConstructor; | |
9 | +import lombok.extern.slf4j.Slf4j; | |
10 | +import org.apache.commons.lang3.StringUtils; | |
11 | +import org.quartz.SchedulerException; | |
12 | +import org.springframework.stereotype.Service; | |
13 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
14 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
15 | +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | |
16 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
17 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
18 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
19 | +import org.thingsboard.server.common.data.yunteng.dto.SysJobDTO; | |
20 | +import org.thingsboard.server.common.data.yunteng.dto.task.TargetContentDTO; | |
21 | +import org.thingsboard.server.common.data.yunteng.dto.task.TaskExecuteTimeDTO; | |
22 | +import org.thingsboard.server.common.data.yunteng.dto.task.TaskTypeDTO; | |
23 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
24 | +import org.thingsboard.server.common.data.yunteng.enums.JobGroupEnum; | |
25 | +import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; | |
26 | +import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; | |
27 | +import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; | |
28 | +import org.thingsboard.server.dao.yunteng.entities.TkTaskCenterEntity; | |
29 | +import org.thingsboard.server.dao.yunteng.mapper.TaskCenterMapper; | |
30 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
31 | +import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | |
32 | +import org.thingsboard.server.dao.yunteng.service.TkSysJobService; | |
33 | +import org.thingsboard.server.dao.yunteng.service.TkTaskCenterService; | |
34 | + | |
35 | +import javax.transaction.Transactional; | |
36 | +import java.util.*; | |
37 | +import java.util.stream.Collectors; | |
38 | + | |
39 | +@Service | |
40 | +@RequiredArgsConstructor | |
41 | +@Slf4j | |
42 | +public class TkTaskCenterServiceImpl | |
43 | + extends AbstractBaseService<TaskCenterMapper, TkTaskCenterEntity> | |
44 | + implements TkTaskCenterService { | |
45 | + private final TkSysJobService tkSysJobService; | |
46 | + private final TkDeviceService tkDeviceService; | |
47 | + private final CacheUtils cacheUtils; | |
48 | + | |
49 | + @Override | |
50 | + public TkPageData<TkTaskCenterDTO> taskCenterPage(Map<String, Object> queryMap, String tenantId) { | |
51 | + Integer state = (Integer) queryMap.get("state"); | |
52 | + TargetTypeEnum targetTypeEnum = (TargetTypeEnum) queryMap.get("targetType"); | |
53 | + IPage<TkTaskCenterEntity> page = | |
54 | + getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); | |
55 | + IPage<TkTaskCenterEntity> taskCenterIPage = | |
56 | + baseMapper.selectPage( | |
57 | + page, | |
58 | + new LambdaQueryWrapper<TkTaskCenterEntity>() | |
59 | + .eq(TkTaskCenterEntity::getTenantId, tenantId) | |
60 | + .eq(null != state, TkTaskCenterEntity::getState, state) | |
61 | + .eq(null != targetTypeEnum, TkTaskCenterEntity::getTargetType, targetTypeEnum)); | |
62 | + if (!taskCenterIPage.getRecords().isEmpty()) { | |
63 | + List<TkTaskCenterDTO> listRecords = | |
64 | + taskCenterIPage.getRecords().stream() | |
65 | + .map( | |
66 | + entity -> { | |
67 | + TkTaskCenterDTO dto = entity.getDTO(TkTaskCenterDTO.class); | |
68 | + dto.setExecuteContent( | |
69 | + JacksonUtil.convertValue(entity.getExecuteContent(), TaskTypeDTO.class)); | |
70 | + dto.setExecuteTime( | |
71 | + JacksonUtil.convertValue( | |
72 | + entity.getExecuteTime(), TaskExecuteTimeDTO.class)); | |
73 | + dto.setExecuteTarget( | |
74 | + JacksonUtil.convertValue( | |
75 | + entity.getExecuteTarget(), TargetContentDTO.class)); | |
76 | + return dto; | |
77 | + }) | |
78 | + .collect(Collectors.toList()); | |
79 | + return new TkPageData<>(listRecords, taskCenterIPage.getTotal()); | |
80 | + } | |
81 | + return getPageData(taskCenterIPage, TkTaskCenterDTO.class); | |
82 | + } | |
83 | + | |
84 | + @Override | |
85 | + @Transactional | |
86 | + public TkTaskCenterDTO saveOrUpdateTaskCenter(TkTaskCenterDTO tkTaskCenterDTO) { | |
87 | + TkTaskCenterEntity entity = tkTaskCenterDTO.getEntity(TkTaskCenterEntity.class); | |
88 | + JsonNode jsonNode = tkTaskCenterDTO.getExecuteContent().getPushContent(); | |
89 | + if (null == jsonNode || null == jsonNode.get(FastIotConstants.RPC_COMMAND)) { | |
90 | + throw new TkDataValidationException(ErrorMessage.EXECUTE_COMMAND_IS_NULL.getMessage()); | |
91 | + } | |
92 | + TaskExecuteTimeDTO executeTime = tkTaskCenterDTO.getExecuteTime(); | |
93 | + if (null == executeTime || StringUtils.isEmpty(executeTime.getCron())) { | |
94 | + throw new TkDataValidationException(ErrorMessage.CRON_INVALID.getMessage()); | |
95 | + } | |
96 | + entity.setExecuteContent( | |
97 | + JacksonUtil.convertValue(tkTaskCenterDTO.getExecuteContent(), JsonNode.class)); | |
98 | + entity.setExecuteTarget( | |
99 | + JacksonUtil.convertValue(tkTaskCenterDTO.getExecuteTarget(), JsonNode.class)); | |
100 | + entity.setExecuteTime( | |
101 | + JacksonUtil.convertValue(tkTaskCenterDTO.getExecuteTime(), JsonNode.class)); | |
102 | + if (StringUtils.isEmpty(tkTaskCenterDTO.getId())) { | |
103 | + entity.setState(FastIotConstants.StateValue.DISABLE); | |
104 | + baseMapper.insert(entity); | |
105 | + } else { | |
106 | + TkTaskCenterDTO queryDTO = | |
107 | + findTaskCenterInfoById(tkTaskCenterDTO.getId(), tkTaskCenterDTO.getTenantId()); | |
108 | + if (null == queryDTO) { | |
109 | + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage()); | |
110 | + } | |
111 | + // 只有通过修改状态接口,才可以修改状态 | |
112 | + entity.setState(null); | |
113 | + baseMapper.updateById(entity); | |
114 | + updateTaskCenterCache(entity); | |
115 | + } | |
116 | + return tkTaskCenterDTO; | |
117 | + } | |
118 | + | |
119 | + @Override | |
120 | + @Transactional | |
121 | + public boolean deleteTaskCenter(DeleteDTO deleteDTO) throws SchedulerException { | |
122 | + List<TkTaskCenterEntity> list = | |
123 | + baseMapper.selectList( | |
124 | + new LambdaQueryWrapper<TkTaskCenterEntity>() | |
125 | + .eq(TkTaskCenterEntity::getTenantId, deleteDTO.getTenantId()) | |
126 | + .in(TkTaskCenterEntity::getId, deleteDTO.getIds())); | |
127 | + if (null == list || list.isEmpty()) { | |
128 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
129 | + } | |
130 | + List<String> sourceIds = new ArrayList<>(); | |
131 | + for (TkTaskCenterEntity entity : list) { | |
132 | + // 任务中心,是启用状态不能删除 | |
133 | + if (entity.getState() == FastIotConstants.StateValue.ENABLE) { | |
134 | + throw new TkDataValidationException( | |
135 | + String.format( | |
136 | + ErrorMessage.DATA_STATE_ENABLE_NOT_DELETE.getMessage(), entity.getName())); | |
137 | + } | |
138 | + sourceIds.add(entity.getId()); | |
139 | + } | |
140 | + int result = baseMapper.deleteBatchIds(sourceIds); | |
141 | + if (result > FastIotConstants.MagicNumber.ZERO) { | |
142 | + return tkSysJobService.deleteJobs( | |
143 | + sourceIds, JobGroupEnum.TASK_CENTER.name(), deleteDTO.getTenantId()); | |
144 | + } | |
145 | + // 移除任务中心缓存 | |
146 | + for (String taskCenterId : sourceIds) { | |
147 | + String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + taskCenterId; | |
148 | + cacheUtils.invalidate(key); | |
149 | + } | |
150 | + return false; | |
151 | + } | |
152 | + | |
153 | + @Override | |
154 | + public TkTaskCenterDTO findTaskCenterInfoById(String id, String tenantId) { | |
155 | + if (StringUtils.isEmpty(id) || StringUtils.isEmpty(tenantId)) { | |
156 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
157 | + } | |
158 | + TkTaskCenterEntity entity = | |
159 | + baseMapper.selectOne( | |
160 | + new LambdaQueryWrapper<TkTaskCenterEntity>() | |
161 | + .eq(TkTaskCenterEntity::getTenantId, tenantId) | |
162 | + .eq(TkTaskCenterEntity::getId, id)); | |
163 | + return Optional.ofNullable(entity) | |
164 | + .map( | |
165 | + object -> { | |
166 | + TkTaskCenterDTO tkTaskCenterDTO = object.getDTO(TkTaskCenterDTO.class); | |
167 | + tkTaskCenterDTO.setExecuteTarget( | |
168 | + JacksonUtil.convertValue(object.getExecuteTarget(), TargetContentDTO.class)); | |
169 | + tkTaskCenterDTO.setExecuteContent( | |
170 | + JacksonUtil.convertValue(object.getExecuteContent(), TaskTypeDTO.class)); | |
171 | + tkTaskCenterDTO.setExecuteTime( | |
172 | + JacksonUtil.convertValue(object.getExecuteTime(), TaskExecuteTimeDTO.class)); | |
173 | + return tkTaskCenterDTO; | |
174 | + }) | |
175 | + .orElse(null); | |
176 | + } | |
177 | + | |
178 | + @Override | |
179 | + public ListenableFuture<TkTaskCenterDTO> getTaskCenterInfoById(String id) { | |
180 | + if (StringUtils.isEmpty(id)) { | |
181 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
182 | + } | |
183 | + String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + id; | |
184 | + Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(key); | |
185 | + TkTaskCenterEntity entity = | |
186 | + entityCache.orElseGet( | |
187 | + () -> | |
188 | + baseMapper.selectOne( | |
189 | + new LambdaQueryWrapper<TkTaskCenterEntity>() | |
190 | + .eq(TkTaskCenterEntity::getId, id))); | |
191 | + return Optional.ofNullable(entity) | |
192 | + .map( | |
193 | + object -> { | |
194 | + TkTaskCenterDTO tkTaskCenterDTO = object.getDTO(TkTaskCenterDTO.class); | |
195 | + tkTaskCenterDTO.setExecuteTarget( | |
196 | + JacksonUtil.convertValue(object.getExecuteTarget(), TargetContentDTO.class)); | |
197 | + tkTaskCenterDTO.setExecuteContent( | |
198 | + JacksonUtil.convertValue(object.getExecuteContent(), TaskTypeDTO.class)); | |
199 | + tkTaskCenterDTO.setExecuteTime( | |
200 | + JacksonUtil.convertValue(object.getExecuteTime(), TaskExecuteTimeDTO.class)); | |
201 | + return Futures.immediateFuture(tkTaskCenterDTO); | |
202 | + }) | |
203 | + .orElse(null); | |
204 | + } | |
205 | + | |
206 | + @Override | |
207 | + @Transactional | |
208 | + public boolean updateState(String id, Integer state, String tenantId) throws SchedulerException { | |
209 | + TkTaskCenterEntity entity = | |
210 | + baseMapper.selectOne( | |
211 | + new LambdaQueryWrapper<TkTaskCenterEntity>().eq(TkTaskCenterEntity::getId, id)); | |
212 | + boolean result = false; | |
213 | + if (null == entity) { | |
214 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
215 | + } | |
216 | + if (!Objects.equals(entity.getTenantId(), tenantId)) { | |
217 | + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage()); | |
218 | + } | |
219 | + entity.setState(state); | |
220 | + if (baseMapper.updateById(entity) > FastIotConstants.MagicNumber.ZERO) { | |
221 | + String sourceId = entity.getId(); | |
222 | + SysJobDTO queryJob = tkSysJobService.findSysJobBySourceId(sourceId); | |
223 | + if (null == queryJob) { | |
224 | + TaskExecuteTimeDTO executeTime = | |
225 | + JacksonUtil.convertValue(entity.getExecuteTime(), TaskExecuteTimeDTO.class); | |
226 | + if (null == executeTime || StringUtils.isEmpty(executeTime.getCron())) { | |
227 | + throw new TkDataValidationException(ErrorMessage.CRON_INVALID.getMessage()); | |
228 | + } | |
229 | + queryJob = new SysJobDTO(); | |
230 | + queryJob.setSourceId(sourceId); | |
231 | + queryJob.setJobName(entity.getName()); | |
232 | + queryJob.setInvokeTarget("rpcCommandTask.process('" + sourceId + "')"); | |
233 | + queryJob.setJobGroup(JobGroupEnum.TASK_CENTER.name()); | |
234 | + queryJob.setCronExpression(executeTime.getCron()); | |
235 | + queryJob.setTenantId(entity.getTenantId()); | |
236 | + } | |
237 | + queryJob.setStatus(state); | |
238 | + tkSysJobService.saveOrUpdateJob(queryJob); | |
239 | + result = true; | |
240 | + } | |
241 | + return result; | |
242 | + } | |
243 | + | |
244 | + @Override | |
245 | + @Transactional | |
246 | + public boolean cancelExecute(String id, String tbDeviceId, String tenantId) { | |
247 | + boolean result = false; | |
248 | + TkTaskCenterEntity entity = baseMapper.selectById(id); | |
249 | + if (entity != null) { | |
250 | + if (!Objects.equals(entity.getTenantId(), tenantId)) { | |
251 | + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage()); | |
252 | + } | |
253 | + TargetContentDTO targetContent = | |
254 | + JacksonUtil.convertValue(entity.getExecuteTarget(), TargetContentDTO.class); | |
255 | + if (null != targetContent) { | |
256 | + // 按设备执行 | |
257 | + if (Objects.equals(entity.getTargetType(), TargetTypeEnum.DEVICES)) { | |
258 | + List<String> data = targetContent.getData(); | |
259 | + List<String> removeResult = new ArrayList<>(); | |
260 | + if (null != data && !data.isEmpty()) { | |
261 | + for (String deviceId : data) { | |
262 | + if (!Objects.equals(deviceId, tbDeviceId)) { | |
263 | + removeResult.add(deviceId); | |
264 | + } | |
265 | + } | |
266 | + targetContent.setData(removeResult); | |
267 | + } | |
268 | + } else { | |
269 | + // 按产品执行 | |
270 | + Map<String, List<String>> map = targetContent.getCancelExecuteDevices(); | |
271 | + DeviceDTO deviceDTO = tkDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId); | |
272 | + for (String key : map.keySet()) { | |
273 | + if (Objects.equals(key, deviceDTO.getDeviceProfileId())) { | |
274 | + map.get(key).add(tbDeviceId); | |
275 | + break; | |
276 | + } | |
277 | + } | |
278 | + } | |
279 | + entity.setExecuteTarget(JacksonUtil.convertValue(targetContent, JsonNode.class)); | |
280 | + baseMapper.updateById(entity); | |
281 | + updateTaskCenterCache(entity); | |
282 | + } | |
283 | + } | |
284 | + return result; | |
285 | + } | |
286 | + | |
287 | + private void updateTaskCenterCache(TkTaskCenterEntity entity) { | |
288 | + String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + entity.getId(); | |
289 | + Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(key); | |
290 | + if (entityCache.isPresent()) { | |
291 | + cacheUtils.put(key, entity); | |
292 | + } | |
293 | + } | |
294 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.TkTaskCenterEntity; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface TaskCenterMapper extends BaseMapper<TkTaskCenterEntity> { | |
9 | +} | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | import org.thingsboard.server.common.data.yunteng.dto.SysAreaDTO; |
3 | +import org.thingsboard.server.common.data.yunteng.enums.AreaLevelEnum; | |
4 | + | |
3 | 5 | import java.util.List; |
4 | 6 | |
5 | 7 | /** |
... | ... | @@ -10,5 +12,5 @@ import java.util.List; |
10 | 12 | public interface SysAreaService { |
11 | 13 | List<SysAreaDTO> list(SysAreaDTO sysAreaDTO); |
12 | 14 | |
13 | - SysAreaDTO getSysAreaInfoByCode(Long code); | |
15 | + SysAreaDTO getSysAreaInfoByCode(Long code, AreaLevelEnum levelEnum); | |
14 | 16 | } | ... | ... |
... | ... | @@ -16,5 +16,28 @@ public interface TkConfigurationCenterService { |
16 | 16 | |
17 | 17 | boolean deleteConfigurationCenter(DeleteDTO deleteDTO); |
18 | 18 | |
19 | - ConfigurationContentInfoDTO getConfigurationInfos(String id,String tenantId); | |
19 | + ConfigurationContentInfoDTO getConfigurationInfos(String id, String tenantId); | |
20 | + | |
21 | + ConfigurationCenterDTO getConfigurationCenterInfoById(String id,String tenantId); | |
22 | + | |
23 | + /** | |
24 | + * 根据租户ID和数据看板ID,判断是否需要密码 | |
25 | + * | |
26 | + * @param id 数据看板ID | |
27 | + * @param tenantId 租户ID | |
28 | + * @return 需要true,不需要false | |
29 | + */ | |
30 | + boolean isNeedCredentialsForPublicView(String id, String tenantId); | |
31 | + | |
32 | + /** | |
33 | + * 分享或取消分享组态中心 | |
34 | + * | |
35 | + * @param isShare true分享 false取消分享 | |
36 | + * @param id 组态ID | |
37 | + * @param accessCredentials 分享的密码:不用密码则为null | |
38 | + * @param tenantId 租户ID | |
39 | + * @return true成功 false失败 | |
40 | + */ | |
41 | + boolean shareOrMonopolyConfigurationCenter( | |
42 | + boolean isShare, String id, String accessCredentials, String tenantId); | |
20 | 43 | } | ... | ... |
... | ... | @@ -56,4 +56,23 @@ public interface TkDataBoardService { |
56 | 56 | * @return false失败 true成功 |
57 | 57 | */ |
58 | 58 | boolean updateDataBoardComponentNum(String id,String tenantId,int count); |
59 | + | |
60 | + /** | |
61 | + * 根据租户ID和数据看板ID,判断是否需要密码 | |
62 | + * @param id 数据看板ID | |
63 | + * @param tenantId 租户ID | |
64 | + * @return 需要true,不需要false | |
65 | + */ | |
66 | + boolean isNeedCredentialsForPublicView(String id,String tenantId); | |
67 | + | |
68 | + /** | |
69 | + * 分享或取消分享数据刊本 | |
70 | + * @param isShare 分享 | |
71 | + * @param id 数据看板ID | |
72 | + * @param accessCredentials 访问凭证 | |
73 | + * @param tenantId 租户ID | |
74 | + * @return true成功 false失败 | |
75 | + */ | |
76 | + boolean shareOrMonopolyDataBoard( | |
77 | + boolean isShare, String id, String accessCredentials, String tenantId); | |
59 | 78 | } | ... | ... |
... | ... | @@ -10,17 +10,40 @@ import java.util.Map; |
10 | 10 | * @author tianfuLei |
11 | 11 | */ |
12 | 12 | public interface TkDataViewService { |
13 | - TkPageData<TkDataViewDTO> page(Map<String, Object> queryMap, boolean tenantAdmin); | |
13 | + TkPageData<TkDataViewDTO> page(Map<String, Object> queryMap, boolean tenantAdmin); | |
14 | 14 | |
15 | - TkDataViewDTO saveDataView(TkDataViewDTO TkDataViewDTO); | |
15 | + TkDataViewDTO saveDataView(TkDataViewDTO TkDataViewDTO); | |
16 | 16 | |
17 | - TkDataViewDTO updateDataView(TkDataViewDTO TkDataViewDTO); | |
17 | + TkDataViewDTO updateDataView(TkDataViewDTO TkDataViewDTO); | |
18 | 18 | |
19 | - boolean deleteDataView(DeleteDTO deleteDTO); | |
19 | + boolean deleteDataView(DeleteDTO deleteDTO); | |
20 | 20 | |
21 | - TkDataViewContentInfoDTO getDataViewInfos(String id, String tenantId); | |
21 | + TkDataViewContentInfoDTO getDataViewInfos(String id, String tenantId); | |
22 | 22 | |
23 | - boolean publishDataView(String id, String tenantId); | |
23 | + TkDataViewDTO getDataViewById(String id, String tenantId); | |
24 | 24 | |
25 | - boolean cancelPublishDataView(String id, String tenantId); | |
25 | + /** | |
26 | + * 根据租户ID和大屏ID,判断是否需要密码 | |
27 | + * | |
28 | + * @param id 大屏ID | |
29 | + * @param tenantId 租户ID | |
30 | + * @return 需要true,不需要false | |
31 | + */ | |
32 | + boolean isNeedCredentialsForPublicView(String id, String tenantId); | |
33 | + | |
34 | + /** | |
35 | + * 分享或取消分享大屏 | |
36 | + * | |
37 | + * @param isShare true分享 false取消分享 | |
38 | + * @param id 大屏ID | |
39 | + * @param accessCredentials 分享的密码:不用密码则为null | |
40 | + * @param tenantId 租户ID | |
41 | + * @return true成功 false失败 | |
42 | + */ | |
43 | + boolean shareOrMonopolyDataViewCenter( | |
44 | + boolean isShare, String id, String accessCredentials, String tenantId); | |
45 | + | |
46 | + boolean publishDataView(String id, String tenantId); | |
47 | + | |
48 | + boolean cancelPublishDataView(String id, String tenantId); | |
26 | 49 | } | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | |
3 | +import org.springframework.web.bind.annotation.RequestBody; | |
4 | +import org.thingsboard.server.common.data.yunteng.dto.TkDeviceRpcDTO; | |
3 | 5 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
4 | 6 | import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; |
5 | 7 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
... | ... | @@ -27,7 +29,7 @@ public interface TkDeviceScriptService extends BaseService<TkDeviceScriptEntity> |
27 | 29 | |
28 | 30 | TkPageData<TkDeviceScriptDTO> page(Map<String, Object> queryMap, boolean isTenantAdmin); |
29 | 31 | |
30 | - List<TkDeviceScriptDTO> findDeviceScript(String tenantId); | |
32 | + List<TkDeviceScriptDTO> findDeviceScript(String tenantId,TkScriptFunctionType scriptType); | |
31 | 33 | |
32 | 34 | |
33 | 35 | /** |
... | ... | @@ -39,4 +41,12 @@ public interface TkDeviceScriptService extends BaseService<TkDeviceScriptEntity> |
39 | 41 | boolean validateFormdata(TkDeviceScriptDTO scriptDTO, boolean created); |
40 | 42 | |
41 | 43 | boolean updateScriptStatus(String tenantId,String id,Integer status); |
44 | + | |
45 | + | |
46 | + /** | |
47 | + * 生成Modebus协议指令 | |
48 | + * @param params 指令配置对象 | |
49 | + * @return | |
50 | + */ | |
51 | + String modbus(TkDeviceRpcDTO params); | |
42 | 52 | } | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | |
3 | 3 | import com.fasterxml.jackson.databind.JsonNode; |
4 | -import org.thingsboard.server.common.data.DeviceTransportType; | |
4 | +import com.google.common.util.concurrent.ListenableFuture;import org.thingsboard.server.common.data.DeviceTransportType; | |
5 | 5 | import org.thingsboard.server.common.data.id.EntityId; |
6 | 6 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
7 | 7 | import org.thingsboard.server.common.data.yunteng.dto.RelationDeviceDTO; |
... | ... | @@ -202,4 +202,6 @@ public interface TkDeviceService extends BaseService<TkDeviceEntity> { |
202 | 202 | * @return 需要接收RPC控制的网关设备或直连设备的ID |
203 | 203 | */ |
204 | 204 | List<String> rpcDevices(String tenantId,String organizationId,String projectId); |
205 | + | |
206 | + ListenableFuture<List<DeviceDTO>> findDeviceListByDeviceProfileId(String deviceProfileId,String tenantId); | |
205 | 207 | } | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | +import org.thingsboard.server.common.data.yunteng.enums.ShareViewType; | |
4 | + | |
5 | +public interface TkShareViewService { | |
6 | + | |
7 | + Object viewShareDataById(ShareViewType shareViewType,String id, String accessCredentials, String tenantId); | |
8 | + | |
9 | + boolean checkPublicViewNeedCredentials(ShareViewType type, String viewId, String tenantId); | |
10 | +} | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | + | |
3 | +import com.google.common.util.concurrent.ListenableFuture; | |
2 | 4 | import org.quartz.SchedulerException; |
3 | 5 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
4 | 6 | import org.thingsboard.server.common.data.yunteng.dto.SysJobDTO; |
5 | 7 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
8 | +import java.util.List; | |
6 | 9 | import java.util.Map; |
7 | 10 | |
8 | -/** | |
9 | - * 定时任务调度信息信息 服务层 | |
10 | - */ | |
11 | -public interface TkSysJobService | |
12 | -{ | |
13 | - /** | |
14 | - * 获取quartz调度器的计划任务 | |
15 | - * | |
16 | - * @param queryMap 查询参数 | |
17 | - * @return 分页数据 | |
18 | - */ | |
19 | - TkPageData<SysJobDTO> sysJobPage(Map<String, Object> queryMap); | |
20 | - | |
21 | - /** | |
22 | - * 通过调度任务ID查询调度信息 | |
23 | - * | |
24 | - * @param id 调度任务ID | |
25 | - * @return 调度任务对象信息 | |
26 | - */ | |
27 | - SysJobDTO selectJobById(String id); | |
11 | +/** 定时任务调度信息信息 服务层 */ | |
12 | +public interface TkSysJobService { | |
13 | + /** | |
14 | + * 获取quartz调度器的计划任务 | |
15 | + * | |
16 | + * @param queryMap 查询参数 | |
17 | + * @return 分页数据 | |
18 | + */ | |
19 | + TkPageData<SysJobDTO> sysJobPage(Map<String, Object> queryMap); | |
28 | 20 | |
29 | - /** | |
30 | - * 暂停任务 | |
31 | - * | |
32 | - * @param job 调度信息 | |
33 | - * @return 结果 | |
34 | - */ | |
35 | - SysJobDTO pauseJob(SysJobDTO job) throws SchedulerException; | |
21 | + /** | |
22 | + * 通过调度任务ID查询调度信息 | |
23 | + * | |
24 | + * @param id 调度任务ID | |
25 | + * @return 调度任务对象信息 | |
26 | + */ | |
27 | + SysJobDTO selectJobById(String id); | |
28 | + /** | |
29 | + * 通过调度任务ID查询调度信息 | |
30 | + * | |
31 | + * @param id 调度任务ID | |
32 | + * @return 调度任务对象信息 | |
33 | + */ | |
34 | + ListenableFuture<SysJobDTO> selectJobInfoById(String id); | |
35 | + /** | |
36 | + * 暂停任务 | |
37 | + * | |
38 | + * @param job 调度信息 | |
39 | + * @return 结果 | |
40 | + */ | |
41 | + SysJobDTO pauseJob(SysJobDTO job) throws SchedulerException; | |
36 | 42 | |
37 | - /** | |
38 | - * 恢复任务 | |
39 | - * | |
40 | - * @param job 调度信息 | |
41 | - * @return 结果 | |
42 | - */ | |
43 | - SysJobDTO resumeJob(SysJobDTO job) throws SchedulerException; | |
43 | + /** | |
44 | + * 恢复任务 | |
45 | + * | |
46 | + * @param job 调度信息 | |
47 | + * @return 结果 | |
48 | + */ | |
49 | + SysJobDTO resumeJob(SysJobDTO job) throws SchedulerException; | |
44 | 50 | |
45 | - /** | |
46 | - * 删除任务后,所对应的trigger也将被删除 | |
47 | - * | |
48 | - * @param job 调度信息 | |
49 | - * @return 结果 | |
50 | - */ | |
51 | - boolean deleteJob(SysJobDTO job) throws SchedulerException; | |
51 | + /** | |
52 | + * 删除任务后,所对应的trigger也将被删除 | |
53 | + * | |
54 | + * @param job 调度信息 | |
55 | + * @return 结果 | |
56 | + */ | |
57 | + boolean deleteJob(SysJobDTO job) throws SchedulerException; | |
52 | 58 | |
53 | - /** | |
54 | - * 批量删除调度信息 | |
55 | - * | |
56 | - * @param deleteDTO 需要删除的数据ID | |
57 | - * @return 结果 true删除成功 false删除失败 | |
58 | - */ | |
59 | - boolean deleteJobByIds(DeleteDTO deleteDTO) throws SchedulerException; | |
59 | + /** | |
60 | + * 批量删除定时任务 | |
61 | + * | |
62 | + * @param sourceIds 来源ID即业务ID | |
63 | + * @param jobGroup 定时任务分组 | |
64 | + * @param tenantId 租户ID | |
65 | + * @return true成功 false失败 | |
66 | + */ | |
67 | + boolean deleteJobs(List<String> sourceIds, String jobGroup, String tenantId) | |
68 | + throws SchedulerException; | |
60 | 69 | |
61 | - /** | |
62 | - * 任务调度状态修改 | |
63 | - * | |
64 | - * @param job 调度信息 | |
65 | - * @return 结果 | |
66 | - */ | |
67 | - SysJobDTO updateSysJobStatus(SysJobDTO job) throws SchedulerException; | |
70 | + /** | |
71 | + * 批量删除调度信息 | |
72 | + * | |
73 | + * @param deleteDTO 需要删除的数据ID | |
74 | + * @return 结果 true删除成功 false删除失败 | |
75 | + */ | |
76 | + boolean deleteJobByIds(DeleteDTO deleteDTO) throws SchedulerException; | |
68 | 77 | |
69 | - /** | |
70 | - * 立即运行任务 | |
71 | - * | |
72 | - * @param job 调度信息 | |
73 | - * @return 结果 | |
74 | - */ | |
75 | - boolean run(SysJobDTO job) throws SchedulerException; | |
78 | + /** | |
79 | + * 任务调度状态修改 | |
80 | + * | |
81 | + * @param job 调度信息 | |
82 | + * @return 结果 | |
83 | + */ | |
84 | + SysJobDTO updateSysJobStatus(SysJobDTO job) throws SchedulerException; | |
76 | 85 | |
77 | - /** | |
78 | - * 新增或编辑任务 | |
79 | - * | |
80 | - * @param job 调度信息 | |
81 | - * @return 结果 | |
82 | - */ | |
83 | - SysJobDTO saveOrUpdateJob(SysJobDTO job) throws SchedulerException; | |
86 | + /** | |
87 | + * 立即运行任务 | |
88 | + * | |
89 | + * @param job 调度信息 | |
90 | + * @return 结果 | |
91 | + */ | |
92 | + boolean run(SysJobDTO job) throws SchedulerException; | |
84 | 93 | |
94 | + /** | |
95 | + * 新增或编辑任务 | |
96 | + * | |
97 | + * @param job 调度信息 | |
98 | + * @return 结果 | |
99 | + */ | |
100 | + SysJobDTO saveOrUpdateJob(SysJobDTO job) throws SchedulerException; | |
85 | 101 | |
86 | - /** | |
87 | - * 校验cron表达式是否有效 | |
88 | - * | |
89 | - * @param cronExpression 表达式 | |
90 | - * @return 结果 | |
91 | - */ | |
92 | - boolean checkCronExpressionIsValid(String cronExpression); | |
102 | + /** | |
103 | + * 校验cron表达式是否有效 | |
104 | + * | |
105 | + * @param cronExpression 表达式 | |
106 | + * @return 结果 | |
107 | + */ | |
108 | + boolean checkCronExpressionIsValid(String cronExpression); | |
93 | 109 | |
94 | - /** | |
95 | - * 通过源ID找到定时任务信息 | |
96 | - * @param sourceId 源ID | |
97 | - * @return 定时任务信息 | |
98 | - */ | |
99 | - SysJobDTO findSysJobBySourceId(String sourceId); | |
100 | -} | |
\ No newline at end of file | ||
110 | + /** | |
111 | + * 通过源ID找到定时任务信息 | |
112 | + * | |
113 | + * @param sourceId 源ID | |
114 | + * @return 定时任务信息 | |
115 | + */ | |
116 | + SysJobDTO findSysJobBySourceId(String sourceId); | |
117 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | +import com.google.common.util.concurrent.ListenableFuture;import org.quartz.SchedulerException; | |
4 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; | |
7 | +import java.util.Map; | |
8 | + | |
9 | +public interface TkTaskCenterService { | |
10 | + /** | |
11 | + * 任务中心分页 | |
12 | + * | |
13 | + * @param queryMap 分页查询条件 | |
14 | + * @param tenantId 租户ID | |
15 | + * @return 分页数据 | |
16 | + */ | |
17 | + TkPageData<TkTaskCenterDTO> taskCenterPage(Map<String, Object> queryMap, String tenantId); | |
18 | + | |
19 | + /** | |
20 | + * 修改或保存任务中心 | |
21 | + * | |
22 | + * @param tkTaskCenterDTO 任务中心信息 | |
23 | + */ | |
24 | + TkTaskCenterDTO saveOrUpdateTaskCenter(TkTaskCenterDTO tkTaskCenterDTO) throws SchedulerException; | |
25 | + | |
26 | + /** | |
27 | + * 删除任务中心 | |
28 | + * | |
29 | + * @param deleteDTO 删除IDS | |
30 | + */ | |
31 | + boolean deleteTaskCenter(DeleteDTO deleteDTO)throws SchedulerException; | |
32 | + | |
33 | + /** | |
34 | + * 根据任务中心ID,查询任务信息 | |
35 | + * @param id 任务中心ID | |
36 | + * @param tenantId 租户ID | |
37 | + * @return 任务信息 | |
38 | + */ | |
39 | + TkTaskCenterDTO findTaskCenterInfoById(String id,String tenantId); | |
40 | + | |
41 | + /** | |
42 | + * 根据任务中心ID,异步查询任务信息 | |
43 | + * @param id 任务中心ID | |
44 | + * @return 任务信息 | |
45 | + */ | |
46 | + ListenableFuture<TkTaskCenterDTO> getTaskCenterInfoById(String id); | |
47 | + | |
48 | + /** | |
49 | + * 启用禁用任务中心 | |
50 | + * @param id 任务中心ID | |
51 | + * @param state 1启用 0禁用 | |
52 | + * @param tenantId 租户ID | |
53 | + * @return true成功 false失败 | |
54 | + */ | |
55 | + boolean updateState(String id,Integer state,String tenantId)throws SchedulerException; | |
56 | + | |
57 | + /** | |
58 | + * 设备取消任务执行 | |
59 | + * @param id 任务ID | |
60 | + * @param tbDeviceId 设备ID | |
61 | + * @param tenantId 租户ID | |
62 | + * @return true成功 false失败 | |
63 | + */ | |
64 | + boolean cancelExecute(String id,String tbDeviceId,String tenantId); | |
65 | +} | ... | ... |
... | ... | @@ -14,6 +14,8 @@ |
14 | 14 | <result property="tenantId" column="tenant_id"/> |
15 | 15 | <result property="updater" column="updater"/> |
16 | 16 | <result property="thumbnail" column="thumbnail"/> |
17 | + <result property="viewType" column="view_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> | |
18 | + <result property="accessCredentials" column="access_credentials"/> | |
17 | 19 | <association property="organizationDTO" |
18 | 20 | javaType="org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO"> |
19 | 21 | <result property="name" column="organization_name"/> |
... | ... | @@ -30,7 +32,8 @@ |
30 | 32 | </resultMap> |
31 | 33 | |
32 | 34 | <sql id="columns"> |
33 | - a.id,a.name,a.platform,a.organization_id,a.thumbnail, a.remark,a.update_time,a.create_time,a.creator,a.tenant_id,a.updater,io.name AS organization_name | |
35 | + a.id,a.name,a.platform,a.organization_id,a.thumbnail, a.remark,a.update_time,a.create_time,a.creator,a.tenant_id, | |
36 | + a.updater,io.name AS organization_name,a.view_type,a.access_credentials | |
34 | 37 | </sql> |
35 | 38 | <select id="getConfigurationCenterPage" resultMap="configurationCenterMap"> |
36 | 39 | SELECT | ... | ... |
... | ... | @@ -35,7 +35,9 @@ |
35 | 35 | <result property="updater" column="updater"/> |
36 | 36 | <result property="description" column="description"/> |
37 | 37 | <result property="customerId" column="customer_id"/> |
38 | - <result property="customerName" column="cusotomer_name"/> | |
38 | + <result property="customerName" column="customer_name"/> | |
39 | + <result property="customerAdditionalInfo" column="customer_additional_info" | |
40 | + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> | |
39 | 41 | <result property="organizationId" column="organization_id"/> |
40 | 42 | <result property="gatewayId" column="gateway_id"/> |
41 | 43 | <result property="gatewayName" column="gateway_name"/> |
... | ... | @@ -83,7 +85,7 @@ |
83 | 85 | </sql> |
84 | 86 | <select id="getDevicePage" resultMap="deviceMap"> |
85 | 87 | SELECT |
86 | - <include refid="pageColumns"/>,d.customer_id::TEXT AS customer_id,cus.title AS cusotomer_name | |
88 | + <include refid="pageColumns"/>,d.customer_id::TEXT AS customer_id,cus.title AS customer_name,cus.additional_info AS customer_additional_info | |
87 | 89 | FROM tk_device ifd |
88 | 90 | LEFT JOIN device_profile ifdp ON ifd.profile_id = ifdp.id::TEXT |
89 | 91 | LEFT JOIN tk_organization io ON io.id = ifd.organization_id | ... | ... |
... | ... | @@ -14,6 +14,8 @@ |
14 | 14 | <result property="tenantId" column="tenant_id"/> |
15 | 15 | <result property="updater" column="updater"/> |
16 | 16 | <result property="thumbnail" column="thumbnail"/> |
17 | + <result property="accessCredentials" column="access_credentials"/> | |
18 | + <result property="viewType" column="view_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> | |
17 | 19 | <association property="organizationDTO" |
18 | 20 | javaType="org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO"> |
19 | 21 | <result property="name" column="organization_name"/> |
... | ... | @@ -34,7 +36,8 @@ |
34 | 36 | </resultMap> |
35 | 37 | |
36 | 38 | <sql id="columns"> |
37 | - a.id,a.name, a.remark,a.state,a.tenant_id,a.organization_id,a.thumbnail,a.updater,a.update_time,a.create_time,a.creator,io.name AS organization_name | |
39 | + a.id,a.name, a.remark,a.state,a.tenant_id,a.organization_id,a.thumbnail,a.updater,a.update_time,a.create_time, | |
40 | + a.creator,io.name AS organization_name,a.access_credentials,a.view_type | |
38 | 41 | </sql> |
39 | 42 | <select id="getDataViewPage" resultMap="dataViewMap"> |
40 | 43 | SELECT | ... | ... |