Commit 9ae508be86efd0a46a43822ebae1b961a76e66c5

Authored by xp.Huang
2 parents e73eb81b e703ceed

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 *
... ...
  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 +}
... ...
  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;
... ...
... ... @@ -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;
... ...
  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 }
... ...
  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 +}
... ...
  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 +}
... ...
  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 +}
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum ExecuteTypeEnum {
  4 + CUSTOM,
  5 + POLL
  6 +}
... ...
... ... @@ -3,5 +3,6 @@ package org.thingsboard.server.common.data.yunteng.enums;
3 3 public enum JobGroupEnum {
4 4 DEFAULT,
5 5 SYSTEM,
6   - REPORT
  6 + REPORT,
  7 + TASK_CENTER
7 8 }
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum ShareViewType {
  4 + DATA_BOARD,
  5 + SCADA,
  6 + LARGE_SCREEN
  7 +}
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum TargetTypeEnum {
  4 + PRODUCTS,
  5 + DEVICES
  6 +}
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum TaskTypeEnum {
  4 + CUSTOM,
  5 + MODBUS_RTU
  6 +}
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/**
  4 + * 编码类型
  5 + */
  6 +public enum TcpDataTypeEnum {
  7 + HEX,
  8 + JSON,
  9 + ASCII
  10 +}
... ...
  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 }
... ...
... ... @@ -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 }
... ...
... ... @@ -25,5 +25,6 @@ public class TkDataViewEntity extends TenantBaseEntity {
25 25 @TableField(typeHandler = EnumTypeHandler.class)
26 26 private ViewType viewType;
27 27
  28 + @TableField(updateStrategy = FieldStrategy.IGNORED)
28 29 private String accessCredentials;
29 30 }
... ...
  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
... ...