Commit e73eb81b0f7dfe83c06a4fd0fc4e46d48fed8fa4
Merge branch 'TCP脚本转换' into 'master_dev'
refactor: TCP协议脚本转换实现方式调整 See merge request yunteng/thingskit!170
Showing
46 changed files
with
1063 additions
and
1207 deletions
... | ... | @@ -59,6 +59,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; |
59 | 59 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
60 | 60 | import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; |
61 | 61 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
62 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
62 | 63 | import org.thingsboard.server.dao.asset.AssetService; |
63 | 64 | import org.thingsboard.server.dao.attributes.AttributesService; |
64 | 65 | import org.thingsboard.server.dao.audit.AuditLogService; |
... | ... | @@ -887,9 +888,9 @@ public abstract class BaseController { |
887 | 888 | * 构建设备配置的配置数据 |
888 | 889 | * @param transportType 产品的通信协议 |
889 | 890 | * @param deviceProfileData 空的设备配置数据 |
890 | - * @param scriptText 自定义数据协议的解析脚本 | |
891 | + * @return | |
891 | 892 | */ |
892 | - protected DeviceProfileData buildDeviceProfileData(String transportType,DeviceProfileData deviceProfileData,String scriptText) { | |
893 | + protected DeviceProfileData buildDeviceProfileData(String transportType,DeviceProfileData deviceProfileData) { | |
893 | 894 | if(null == deviceProfileData){ |
894 | 895 | deviceProfileData = new DeviceProfileData(); |
895 | 896 | } |
... | ... | @@ -899,10 +900,6 @@ public abstract class BaseController { |
899 | 900 | // 传输类型默认都是Default |
900 | 901 | if(transportType ==null || DeviceTransportType.DEFAULT.name().equals(transportType)){ |
901 | 902 | deviceProfileData.setTransportConfiguration(new DefaultDeviceProfileTransportConfiguration()); |
902 | - }else if(DeviceTransportType.TCP.name().equals(transportType)){ | |
903 | - TkTcpDeviceProfileTransportConfiguration tcpDeviceProfileTransportConfiguration = (TkTcpDeviceProfileTransportConfiguration) deviceProfileData.getTransportConfiguration(); | |
904 | - tcpDeviceProfileTransportConfiguration.setScriptText(scriptText); | |
905 | - deviceProfileData.setTransportConfiguration(tcpDeviceProfileTransportConfiguration); | |
906 | 903 | }else{ |
907 | 904 | deviceProfileData.setTransportConfiguration(deviceProfileData.getTransportConfiguration()); |
908 | 905 | } |
... | ... | @@ -938,14 +935,16 @@ public abstract class BaseController { |
938 | 935 | DeviceProfile savedDeviceProfile = |
939 | 936 | checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); |
940 | 937 | |
938 | + /**通知设备接入服务设备配置更新*/ | |
941 | 939 | tbClusterService.onDeviceProfileChange(savedDeviceProfile, null); |
940 | + /**通知核心服务或规则引擎设备配置更新*/ | |
942 | 941 | tbClusterService.broadcastEntityStateChangeEvent( |
943 | 942 | deviceProfile.getTenantId(), savedDeviceProfile.getId(), ComponentLifecycleEvent.UPDATED); |
944 | 943 | |
945 | 944 | logEntityAction(savedDeviceProfile.getId(), savedDeviceProfile, null, ActionType.UPDATED, null); |
946 | 945 | |
947 | 946 | otaPackageStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged); |
948 | - | |
947 | + /**通知边缘服务设备配置更新*/ | |
949 | 948 | sendEntityNotificationMsg( |
950 | 949 | getTenantId(), savedDeviceProfile.getId(), EdgeEventActionType.UPDATED); |
951 | 950 | return savedDeviceProfile; | ... | ... |
... | ... | @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; |
32 | 32 | import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; |
33 | 33 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
34 | 34 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
35 | -import org.thingsboard.server.common.yunteng.script.TkScriptFactory; | |
35 | +import org.thingsboard.server.transport.tcp.script.TkScriptFactory; | |
36 | 36 | import org.thingsboard.server.controller.BaseController; |
37 | 37 | import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; |
38 | 38 | import org.thingsboard.server.dao.yunteng.service.TkDeviceProfileService; |
... | ... | @@ -293,17 +293,8 @@ public class TkDeviceProfileController extends BaseController { |
293 | 293 | tbDeviceProfile.setTransportType(DeviceTransportType.valueOf(transportType)); |
294 | 294 | } |
295 | 295 | |
296 | - if (DeviceTransportType.TCP.name().equals(transportType)) { | |
297 | - TkTcpDeviceProfileTransportConfiguration tcpDeviceProfileTransportConfiguration = | |
298 | - (TkTcpDeviceProfileTransportConfiguration) | |
299 | - deviceProfileDTO.getProfileData().getTransportConfiguration(); | |
300 | - String scriptId = tcpDeviceProfileTransportConfiguration.getScriptId(); | |
301 | - scriptText = javaScriptService.getScriptText(deviceProfileDTO.getTenantId(), scriptId); | |
302 | - deviceProfileDTO.setScriptId(scriptId); | |
303 | - } | |
304 | - | |
305 | 296 | tbDeviceProfile.setProfileData( |
306 | - buildDeviceProfileData(transportType, deviceProfileDTO.getProfileData(), scriptText == null? TkScriptFactory.INCLUD_ORIGINAL_DATA:scriptText)); | |
297 | + buildDeviceProfileData(transportType, deviceProfileDTO.getProfileData())); | |
307 | 298 | return tbDeviceProfile; |
308 | 299 | } |
309 | 300 | } | ... | ... |
... | ... | @@ -21,34 +21,32 @@ import org.thingsboard.server.common.data.DeviceProfile; |
21 | 21 | import org.thingsboard.server.common.data.DeviceProfileProvisionType; |
22 | 22 | import org.thingsboard.server.common.data.DeviceProfileType; |
23 | 23 | import org.thingsboard.server.common.data.DeviceTransportType; |
24 | -import org.thingsboard.server.common.data.audit.ActionType; | |
25 | -import org.thingsboard.server.common.data.edge.EdgeEventActionType; | |
26 | 24 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
27 | 25 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
28 | 26 | import org.thingsboard.server.common.data.id.RuleChainId; |
29 | 27 | import org.thingsboard.server.common.data.id.TenantId; |
30 | -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | |
31 | 28 | import org.thingsboard.server.common.data.yunteng.common.DeleteGroup; |
32 | -import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
33 | 29 | import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; |
34 | 30 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
35 | 31 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
36 | 32 | import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; |
37 | 33 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
38 | 34 | import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; |
35 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
39 | 36 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
40 | 37 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
41 | -import org.thingsboard.server.common.yunteng.script.TkScriptFactory; | |
42 | -import org.thingsboard.server.common.yunteng.script.TkScriptInvokeService; | |
43 | -import org.thingsboard.server.common.yunteng.script.TkScriptType; | |
44 | 38 | import org.thingsboard.server.controller.BaseController; |
45 | 39 | import org.thingsboard.server.dao.yunteng.service.TkDeviceProfileService; |
46 | 40 | import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; |
41 | +import org.thingsboard.server.transport.tcp.script.TkScriptInvokeService; | |
47 | 42 | |
48 | 43 | import java.sql.Timestamp; |
49 | 44 | import java.time.LocalDateTime; |
50 | 45 | import java.time.ZoneOffset; |
51 | -import java.util.*; | |
46 | +import java.util.HashMap; | |
47 | +import java.util.List; | |
48 | +import java.util.Map; | |
49 | +import java.util.UUID; | |
52 | 50 | import java.util.concurrent.TimeUnit; |
53 | 51 | |
54 | 52 | import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*; |
... | ... | @@ -58,210 +56,208 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant. |
58 | 56 | @RequestMapping("api/yt/js") |
59 | 57 | @Api(tags = {"设备数据解析脚本管理"}) |
60 | 58 | public class TkDeviceScriptController extends BaseController { |
61 | - private static final JsonParser parser = new JsonParser(); | |
62 | - private static final ObjectMapper objectMapper = new ObjectMapper(); | |
63 | - private final TkDeviceScriptService scriptService; | |
64 | - private final TkDeviceProfileService ytDeviceProfileService; | |
65 | - private final TkScriptInvokeService jsEngine; | |
59 | + private static final JsonParser parser = new JsonParser(); | |
60 | + private static final ObjectMapper objectMapper = new ObjectMapper(); | |
61 | + private final TkDeviceScriptService scriptService; | |
62 | + private final TkDeviceProfileService ytDeviceProfileService; | |
63 | + private final TkScriptInvokeService jsEngine; | |
66 | 64 | |
67 | - @PostMapping() | |
68 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:post','api:yt:js:update'})") | |
69 | - @ApiOperation("创建 | 编辑") | |
70 | - public ResponseEntity<TkDeviceScriptDTO> saveJavaScript(@RequestBody TkDeviceScriptDTO scriptDTO) | |
71 | - throws ThingsboardException { | |
72 | - String id = scriptDTO.getId(); | |
73 | - boolean created = StringUtils.isBlank(id); | |
74 | - String tenantId = getCurrentUser().getCurrentTenantId(); | |
75 | - scriptDTO.setTenantId(tenantId); | |
76 | - scriptService.validateFormdata(scriptDTO, created); | |
65 | + @PostMapping() | |
66 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:post','api:yt:js:update'})") | |
67 | + @ApiOperation("创建 | 编辑") | |
68 | + public ResponseEntity<TkDeviceScriptDTO> saveJavaScript(@RequestBody TkDeviceScriptDTO scriptDTO) | |
69 | + throws ThingsboardException { | |
70 | + String id = scriptDTO.getId(); | |
71 | + boolean created = StringUtils.isBlank(id); | |
72 | + String tenantId = getCurrentUser().getCurrentTenantId(); | |
73 | + scriptDTO.setTenantId(tenantId); | |
74 | + scriptService.validateFormdata(scriptDTO, created); | |
77 | 75 | |
78 | 76 | |
79 | - String creator = getCurrentUser().getCurrentUserId(); | |
80 | - scriptDTO.setCreator(creator); | |
81 | - scriptDTO.setUpdater(creator); | |
82 | - return ResponseEntity.ok(scriptService.insertOrUpdate(scriptDTO)); | |
83 | - } | |
84 | - | |
85 | - @PostMapping("/{id}/{status}") | |
86 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:post','api:yt:js:update:status'})") | |
87 | - @ApiOperation("修改脚本状态") | |
88 | - public ResponseEntity<Boolean> updateScriptStatus( | |
89 | - @PathVariable("id") String id, @PathVariable("status") Integer status) | |
90 | - throws ThingsboardException { | |
91 | - /** 业务流程 1/3.编辑时同步刷新相关的设备配置 2/3.处理TB业务逻辑 3/3.处理业务平台的业务逻辑 */ | |
92 | - String tenantId = getCurrentUser().getCurrentTenantId(); | |
93 | - TkDeviceScriptDTO scriptDTO = scriptService.getDeviceScript(tenantId,id).get(); | |
94 | - if(scriptDTO ==null || scriptDTO.getStatus().equals(status)){ | |
95 | - return ResponseEntity.ok(false); | |
77 | + String creator = getCurrentUser().getCurrentUserId(); | |
78 | + scriptDTO.setCreator(creator); | |
79 | + scriptDTO.setUpdater(creator); | |
80 | + return ResponseEntity.ok(scriptService.insertOrUpdate(scriptDTO)); | |
96 | 81 | } |
97 | - String convertJs = TkScriptFactory.INCLUD_ORIGINAL_DATA; | |
98 | 82 | |
99 | - if(1 == status){ | |
100 | - if(scriptDTO.isSaveOriginalData()){ | |
101 | - convertJs += scriptDTO.getConvertJs(); | |
102 | - }else{ | |
103 | - convertJs = scriptDTO.getConvertJs(); | |
104 | - } | |
105 | - } | |
106 | - List<DeviceProfileDTO> usedProfiles = ytDeviceProfileService.findDeviceProfile(tenantId, id,null); | |
107 | - for (DeviceProfileDTO profile : usedProfiles) { | |
108 | - DeviceProfile tbDeviceProfile = | |
109 | - buildTbDeviceProfileFromDeviceProfileDTO( | |
110 | - profile, tenantId, convertJs); | |
111 | - updateTbDeviceProfile(tbDeviceProfile); | |
83 | + @PostMapping("/{id}/{status}") | |
84 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:post','api:yt:js:update:status'})") | |
85 | + @ApiOperation("修改脚本状态") | |
86 | + public ResponseEntity<Boolean> updateScriptStatus( | |
87 | + @PathVariable("id") String id, @PathVariable("status") Integer status) | |
88 | + throws ThingsboardException { | |
89 | + /** 业务流程 1/3.编辑时同步刷新相关的设备配置 2/3.处理TB业务逻辑 3/3.处理业务平台的业务逻辑 */ | |
90 | + String tenantId = getCurrentUser().getCurrentTenantId(); | |
91 | + TkDeviceScriptDTO scriptDTO = scriptService.getDeviceScript(tenantId, id).get(); | |
92 | + if (scriptDTO == null || scriptDTO.getStatus().equals(status)) { | |
93 | + return ResponseEntity.ok(false); | |
94 | + } | |
95 | + | |
96 | + /**脚本引擎启用/禁用时,刷新规则引擎中缓存的脚本ID对应的脚本内容,禁用时为默认脚本*/ | |
97 | +// List<DeviceProfileDTO> usedProfiles = ytDeviceProfileService.findDeviceProfile(tenantId, id,null); | |
98 | +// for (DeviceProfileDTO profile : usedProfiles) { | |
99 | +// DeviceProfile tbDeviceProfile = | |
100 | +// buildTbDeviceProfileFromDeviceProfileDTO( | |
101 | +// profile, id,scriptDTO.getScriptType()); | |
102 | +// updateTbDeviceProfile(tbDeviceProfile); | |
103 | +// } | |
104 | + | |
105 | + scriptService.updateScriptStatus(tenantId, id, status); | |
106 | + return ResponseEntity.ok(true); | |
112 | 107 | } |
113 | - scriptService.updateScriptStatus(tenantId, id, status); | |
114 | - return ResponseEntity.ok(true); | |
115 | - } | |
116 | 108 | |
117 | 109 | |
118 | - @GetMapping("{id}") | |
119 | - @ApiOperation("详情") | |
120 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:js:get'})") | |
121 | - public ResponseEntity<TkDeviceScriptDTO> getDevice(@PathVariable("id") String id) | |
122 | - throws ThingsboardException { | |
123 | - return ResponseEntity.of( | |
124 | - scriptService.getDeviceScript(getCurrentUser().getCurrentTenantId(), id)); | |
125 | - } | |
110 | + @GetMapping("{id}") | |
111 | + @ApiOperation("详情") | |
112 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:js:get'})") | |
113 | + public ResponseEntity<TkDeviceScriptDTO> getDevice(@PathVariable("id") String id) | |
114 | + throws ThingsboardException { | |
115 | + return ResponseEntity.of( | |
116 | + scriptService.getDeviceScript(getCurrentUser().getCurrentTenantId(), id)); | |
117 | + } | |
118 | + | |
119 | + @GetMapping(params = {PAGE_SIZE, PAGE}) | |
120 | + @ApiOperation("分页查询") | |
121 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") | |
122 | + public TkPageData<TkDeviceScriptDTO> pageDeviceScript( | |
123 | + @RequestParam(PAGE_SIZE) int pageSize, | |
124 | + @RequestParam(PAGE) int page, | |
125 | + @RequestParam(value = ORDER_FILED, required = false) String orderFiled, | |
126 | + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType, | |
127 | + @RequestParam(value = "name", required = false) String name, | |
128 | + @RequestParam(value = "startTime", required = false) Long startTime, | |
129 | + @RequestParam(value = "endTime", required = false) Long endTime) | |
130 | + throws ThingsboardException { | |
131 | + Map<String, Object> queryMap = new HashMap<>(); | |
132 | + queryMap.put(PAGE_SIZE, pageSize); | |
133 | + queryMap.put(PAGE, page); | |
134 | + queryMap.put(ORDER_FILED, orderFiled); | |
135 | + queryMap.put(ORDER_TYPE, orderType); | |
136 | + queryMap.put(CUSTOMER_ID, getCurrentUser().getCustomerId().toString()); | |
137 | + queryMap.put(TENANT_ID, getCurrentUser().getCurrentTenantId()); | |
126 | 138 | |
127 | - @GetMapping(params = {PAGE_SIZE, PAGE}) | |
128 | - @ApiOperation("分页查询") | |
129 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") | |
130 | - public TkPageData<TkDeviceScriptDTO> pageDeviceScript( | |
131 | - @RequestParam(PAGE_SIZE) int pageSize, | |
132 | - @RequestParam(PAGE) int page, | |
133 | - @RequestParam(value = ORDER_FILED, required = false) String orderFiled, | |
134 | - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType, | |
135 | - @RequestParam(value = "name", required = false) String name, | |
136 | - @RequestParam(value = "startTime", required = false) Long startTime, | |
137 | - @RequestParam(value = "endTime", required = false) Long endTime) | |
138 | - throws ThingsboardException { | |
139 | - Map<String, Object> queryMap = new HashMap<>(); | |
140 | - queryMap.put(PAGE_SIZE, pageSize); | |
141 | - queryMap.put(PAGE, page); | |
142 | - queryMap.put(ORDER_FILED, orderFiled); | |
143 | - queryMap.put(ORDER_TYPE, orderType); | |
144 | - queryMap.put(CUSTOMER_ID, getCurrentUser().getCustomerId().toString()); | |
145 | - queryMap.put(TENANT_ID, getCurrentUser().getCurrentTenantId()); | |
139 | + if (!StringUtils.isEmpty(name)) { | |
140 | + queryMap.put("name", name); | |
141 | + } | |
142 | + if (null != startTime && null != endTime) { | |
143 | + if (startTime > endTime) { | |
144 | + throw new TkDataValidationException( | |
145 | + ErrorMessage.START_TIME_NOT_MORE_THAN_END_TIME.getMessage()); | |
146 | + } | |
147 | + queryMap.put("startTime", new Timestamp(startTime).toLocalDateTime()); | |
148 | + queryMap.put("endTime", new Timestamp(endTime).toLocalDateTime()); | |
149 | + } | |
146 | 150 | |
147 | - if(!StringUtils.isEmpty(name)){ | |
148 | - queryMap.put("name", name); | |
151 | + return scriptService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
149 | 152 | } |
150 | - if(null != startTime && null!=endTime){ | |
151 | - if (startTime > endTime) { | |
152 | - throw new TkDataValidationException( | |
153 | - ErrorMessage.START_TIME_NOT_MORE_THAN_END_TIME.getMessage()); | |
154 | - } | |
155 | - queryMap.put("startTime", new Timestamp(startTime).toLocalDateTime()); | |
156 | - queryMap.put("endTime", new Timestamp(endTime).toLocalDateTime()); | |
153 | + | |
154 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | |
155 | + @GetMapping("/me/list") | |
156 | + @ApiOperation("选项列表") | |
157 | + public ResponseEntity listDeviceScript() throws ThingsboardException { | |
158 | + List<TkDeviceScriptDTO> results = | |
159 | + scriptService.findDeviceScript(getCurrentUser().getCurrentTenantId()); | |
160 | + return ResponseEntity.ok(results); | |
157 | 161 | } |
158 | 162 | |
159 | - return scriptService.page(queryMap, getCurrentUser().isTenantAdmin()); | |
160 | - } | |
163 | + @DeleteMapping | |
164 | + @ApiOperation("删除") | |
165 | + @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:delete'})") | |
166 | + public void deleteDevices(@Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) | |
167 | + throws ThingsboardException { | |
168 | + scriptService.deleteScriptes(getCurrentUser().getCurrentTenantId(), deleteDTO.getIds()); | |
169 | + } | |
161 | 170 | |
162 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | |
163 | - @GetMapping("/me/list") | |
164 | - @ApiOperation("选项列表") | |
165 | - public ResponseEntity listDeviceScript() throws ThingsboardException { | |
166 | - List<TkDeviceScriptDTO> results = | |
167 | - scriptService.findDeviceScript(getCurrentUser().getCurrentTenantId()); | |
168 | - return ResponseEntity.ok(results); | |
169 | - } | |
171 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | |
172 | + @PostMapping("/test") | |
173 | + @ApiOperation("测试脚本执行结果") | |
174 | + public ResponseEntity<JsonNode> test(@RequestBody JsonNode inputParams) | |
175 | + throws ThingsboardException { | |
176 | + try { | |
177 | + String script = inputParams.get("script").asText(); | |
178 | + String scriptType = inputParams.get("scriptType").asText(); | |
179 | + String jsParam = inputParams.get("params").asText(); | |
170 | 180 | |
171 | - @DeleteMapping | |
172 | - @ApiOperation("删除") | |
173 | - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN'},{'api:yt:js:delete'})") | |
174 | - public void deleteDevices(@Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) | |
175 | - throws ThingsboardException { | |
176 | - scriptService.deleteScriptes(getCurrentUser().getCurrentTenantId(), deleteDTO.getIds()); | |
177 | - } | |
181 | + String output = ""; | |
182 | + String errorText = ""; | |
183 | + ScriptEngine engine = null; | |
184 | + try { | |
185 | + TkScriptFunctionType functionType = TkScriptFunctionType.valueOf(scriptType); | |
186 | + UUID scriptId = jsEngine.eval(null, functionType, script).get(); | |
178 | 187 | |
179 | - @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") | |
180 | - @PostMapping("/test") | |
181 | - @ApiOperation("测试脚本执行结果") | |
182 | - public ResponseEntity<JsonNode> test(@RequestBody JsonNode inputParams) | |
183 | - throws ThingsboardException { | |
184 | - try { | |
185 | - String script = inputParams.get("script").asText(); | |
186 | - String jsParam = inputParams.get("params").asText(); | |
187 | 188 | |
188 | - String output = ""; | |
189 | - String errorText = ""; | |
190 | - ScriptEngine engine = null; | |
191 | - try { | |
192 | - UUID scriptId = jsEngine.eval(TkScriptType.TCP_TRANSPORT_SCRIPT, script).get(); | |
193 | - ListenableFuture<String> result = | |
194 | - Futures.transformAsync( | |
195 | - jsEngine.invokeFunction(scriptId, jsParam), | |
196 | - o -> { | |
197 | - try { | |
198 | - JsonElement json = parser.parse(o.toString()); | |
199 | - return Futures.immediateFuture(json.toString()); | |
200 | - } catch (Exception e) { | |
201 | - return Futures.immediateFailedFuture(e); | |
202 | - } | |
203 | - }, | |
204 | - MoreExecutors.directExecutor()); | |
189 | + ListenableFuture<String> result = | |
190 | + Futures.transformAsync( | |
191 | + jsEngine.invokeFunction(scriptId, jsParam), | |
192 | + o -> { | |
193 | + try { | |
194 | + JsonElement json = parser.parse(o.toString()); | |
195 | + return Futures.immediateFuture(json.toString()); | |
196 | + } catch (Exception e) { | |
197 | + return Futures.immediateFailedFuture(e); | |
198 | + } | |
199 | + }, | |
200 | + MoreExecutors.directExecutor()); | |
205 | 201 | |
206 | - output = result.get(20, TimeUnit.SECONDS); | |
207 | - } catch (Exception e) { | |
208 | - errorText = e.getMessage(); | |
209 | - } finally { | |
210 | - if (engine != null) { | |
211 | - engine.destroy(); | |
202 | + output = result.get(20, TimeUnit.SECONDS); | |
203 | + jsEngine.release(scriptId); | |
204 | + } catch (Exception e) { | |
205 | + errorText = e.getMessage(); | |
206 | + } finally { | |
207 | + if (engine != null) { | |
208 | + engine.destroy(); | |
209 | + } | |
210 | + } | |
211 | + ObjectNode result = objectMapper.createObjectNode(); | |
212 | + result.put("output", output); | |
213 | + result.put("error", errorText); | |
214 | + return ResponseEntity.ok(result); | |
215 | + } catch (Exception e) { | |
216 | + throw handleException(e); | |
212 | 217 | } |
213 | - } | |
214 | - ObjectNode result = objectMapper.createObjectNode(); | |
215 | - result.put("output", output); | |
216 | - result.put("error", errorText); | |
217 | - return ResponseEntity.ok(result); | |
218 | - } catch (Exception e) { | |
219 | - throw handleException(e); | |
220 | 218 | } |
221 | - } | |
222 | 219 | |
223 | - /** | |
224 | - * 构造调用TBDeviceProfile需要的参数 | |
225 | - * | |
226 | - * @param deviceProfileDTO 页面接收的参数 | |
227 | - * @return 封装好的TBDeviceProfile | |
228 | - */ | |
229 | - private DeviceProfile buildTbDeviceProfileFromDeviceProfileDTO( | |
230 | - DeviceProfileDTO deviceProfileDTO, String scriptId, String scriptText) { | |
231 | - DeviceProfile tbDeviceProfile = new DeviceProfile(); | |
232 | - if (StringUtils.isNotBlank(deviceProfileDTO.getId())) { | |
233 | - UUID profileId = UUID.fromString(deviceProfileDTO.getTbProfileId()); | |
234 | - tbDeviceProfile.setId(new DeviceProfileId(profileId)); | |
235 | - tbDeviceProfile.setCreatedTime( | |
236 | - deviceProfileDTO.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
237 | - } else { | |
238 | - tbDeviceProfile.setCreatedTime( | |
239 | - LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
240 | - } | |
241 | - tbDeviceProfile.setName(deviceProfileDTO.getName()); | |
242 | - tbDeviceProfile.setImage(deviceProfileDTO.getImage()); | |
243 | - tbDeviceProfile.setDescription(deviceProfileDTO.getDescription()); | |
244 | - tbDeviceProfile.setType(DeviceProfileType.DEFAULT); | |
245 | - UUID tenantId = UUID.fromString(deviceProfileDTO.getTenantId()); | |
246 | - tbDeviceProfile.setTenantId(TenantId.fromUUID(tenantId)); | |
247 | - tbDeviceProfile.setDefault(deviceProfileDTO.isDefault()); | |
220 | + /** | |
221 | + * 构造调用TBDeviceProfile需要的参数 | |
222 | + * | |
223 | + * @param deviceProfileDTO 页面接收的参数 | |
224 | + * @return 封装好的TBDeviceProfile | |
225 | + */ | |
226 | + private DeviceProfile buildTbDeviceProfileFromDeviceProfileDTO( | |
227 | + DeviceProfileDTO deviceProfileDTO, String scriptId, TkScriptFunctionType scriptType) { | |
228 | + DeviceProfile tbDeviceProfile = new DeviceProfile(); | |
229 | + if (StringUtils.isNotBlank(deviceProfileDTO.getId())) { | |
230 | + UUID profileId = UUID.fromString(deviceProfileDTO.getTbProfileId()); | |
231 | + tbDeviceProfile.setId(new DeviceProfileId(profileId)); | |
232 | + tbDeviceProfile.setCreatedTime( | |
233 | + deviceProfileDTO.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
234 | + } else { | |
235 | + tbDeviceProfile.setCreatedTime( | |
236 | + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
237 | + } | |
238 | + tbDeviceProfile.setName(deviceProfileDTO.getName()); | |
239 | + tbDeviceProfile.setImage(deviceProfileDTO.getImage()); | |
240 | + tbDeviceProfile.setDescription(deviceProfileDTO.getDescription()); | |
241 | + tbDeviceProfile.setType(DeviceProfileType.DEFAULT); | |
242 | + UUID tenantId = UUID.fromString(deviceProfileDTO.getTenantId()); | |
243 | + tbDeviceProfile.setTenantId(TenantId.fromUUID(tenantId)); | |
244 | + tbDeviceProfile.setDefault(deviceProfileDTO.isDefault()); | |
248 | 245 | |
249 | - // 获取当前租户的默认规则链 | |
250 | - if (StringUtils.isNotBlank(deviceProfileDTO.getDefaultRuleChainId())) { | |
251 | - UUID chainId = UUID.fromString(deviceProfileDTO.getDefaultRuleChainId()); | |
252 | - tbDeviceProfile.setDefaultRuleChainId(new RuleChainId(chainId)); | |
253 | - } | |
246 | + // 获取当前租户的默认规则链 | |
247 | + if (StringUtils.isNotBlank(deviceProfileDTO.getDefaultRuleChainId())) { | |
248 | + UUID chainId = UUID.fromString(deviceProfileDTO.getDefaultRuleChainId()); | |
249 | + tbDeviceProfile.setDefaultRuleChainId(new RuleChainId(chainId)); | |
250 | + } | |
254 | 251 | |
255 | - tbDeviceProfile.setDefaultQueueName(ServiceQueue.MAIN); | |
256 | - tbDeviceProfile.setProvisionType(DeviceProfileProvisionType.DISABLED); | |
252 | + tbDeviceProfile.setDefaultQueueName(ServiceQueue.MAIN); | |
253 | + tbDeviceProfile.setProvisionType(DeviceProfileProvisionType.DISABLED); | |
257 | 254 | |
258 | - // 传输类型默认都是Default | |
259 | - String transportType = deviceProfileDTO.getTransportType(); | |
260 | - tbDeviceProfile.setTransportType(DeviceTransportType.valueOf(transportType)); | |
255 | + // 传输类型默认都是Default | |
256 | + String transportType = deviceProfileDTO.getTransportType(); | |
257 | + tbDeviceProfile.setTransportType(DeviceTransportType.valueOf(transportType)); | |
261 | 258 | |
262 | - deviceProfileDTO.setScriptId(scriptId); | |
263 | - tbDeviceProfile.setProfileData( | |
264 | - buildDeviceProfileData(transportType, deviceProfileDTO.getProfileData(), scriptText)); | |
265 | - return tbDeviceProfile; | |
266 | - } | |
259 | + tbDeviceProfile.setProfileData( | |
260 | + buildDeviceProfileData(transportType, deviceProfileDTO.getProfileData())); | |
261 | + return tbDeviceProfile; | |
262 | + } | |
267 | 263 | } | ... | ... |
... | ... | @@ -61,6 +61,8 @@ import org.thingsboard.server.common.data.relation.EntityRelation; |
61 | 61 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
62 | 62 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
63 | 63 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
64 | +import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; | |
65 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
64 | 66 | import org.thingsboard.server.common.msg.EncryptionUtil; |
65 | 67 | import org.thingsboard.server.common.msg.TbMsg; |
66 | 68 | import org.thingsboard.server.common.msg.TbMsgDataType; |
... | ... | @@ -75,6 +77,7 @@ import org.thingsboard.server.dao.device.provision.ProvisionResponse; |
75 | 77 | import org.thingsboard.server.dao.ota.OtaPackageService; |
76 | 78 | import org.thingsboard.server.dao.relation.RelationService; |
77 | 79 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
80 | +import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; | |
78 | 81 | import org.thingsboard.server.dao.yunteng.service.TkDeviceService; |
79 | 82 | import org.thingsboard.server.gen.transport.TransportProtos; |
80 | 83 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
... | ... | @@ -102,6 +105,8 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService; |
102 | 105 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
103 | 106 | import org.thingsboard.server.service.resource.TbResourceService; |
104 | 107 | |
108 | +import java.util.Arrays; | |
109 | +import java.util.List; | |
105 | 110 | import java.util.Optional; |
106 | 111 | import java.util.UUID; |
107 | 112 | import java.util.concurrent.ConcurrentHashMap; |
... | ... | @@ -129,6 +134,7 @@ public class DefaultTransportApiService implements TransportApiService { |
129 | 134 | private final TbApiUsageStateService apiUsageStateService; |
130 | 135 | private final DeviceService deviceService; |
131 | 136 | private final TkDeviceService ytDeviceService; |
137 | + private final TkDeviceScriptService scriptService; | |
132 | 138 | private final RelationService relationService; |
133 | 139 | private final DeviceCredentialsService deviceCredentialsService; |
134 | 140 | private final DbCallbackExecutorService dbCallbackExecutorService; |
... | ... | @@ -182,6 +188,12 @@ public class DefaultTransportApiService implements TransportApiService { |
182 | 188 | result = handle(transportApiRequestMsg.getOtaPackageRequestMsg()); |
183 | 189 | } |
184 | 190 | |
191 | + //Thingskit function | |
192 | + else if (transportApiRequestMsg.hasScript()) { | |
193 | + result = handle(transportApiRequestMsg.getScript()); | |
194 | + } | |
195 | + | |
196 | + | |
185 | 197 | return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture), |
186 | 198 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), |
187 | 199 | MoreExecutors.directExecutor()); |
... | ... | @@ -279,25 +291,21 @@ public class DefaultTransportApiService implements TransportApiService { |
279 | 291 | Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(requestMsg.getDeviceName(), id -> new ReentrantLock()); |
280 | 292 | deviceCreationLock.lock(); |
281 | 293 | try { |
294 | + Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), requestMsg.getDeviceName()); | |
295 | + | |
296 | + if (device == null) { | |
297 | + | |
282 | 298 | |
283 | - //Thingskit function | |
284 | - String slaveName = requestMsg.getDeviceName(); | |
285 | - if(gateway.getDeviceData().getTransportConfiguration().getType() == DeviceTransportType.TCP) { | |
286 | - DeviceDTO iotDev = ytDeviceService.findSlaveDevice(gateway.getTenantId().getId().toString() | |
287 | - , gateway.getId().getId().toString() | |
288 | - ,requestMsg.getDeviceName()); | |
289 | - if(iotDev == null ){ | |
299 | + | |
300 | + //Thingskit function | |
301 | + if(gateway.getDeviceData().getTransportConfiguration().getType() == DeviceTransportType.TCP) { | |
290 | 302 | GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = GetOrCreateDeviceFromGatewayResponseMsg.newBuilder(); |
291 | 303 | return TransportApiResponseMsg.newBuilder() |
292 | 304 | .setGetOrCreateDeviceResponseMsg(builder.build()) |
293 | 305 | .build(); |
294 | 306 | } |
295 | - slaveName = iotDev.getName(); | |
296 | - } | |
297 | 307 | |
298 | - Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), slaveName); | |
299 | 308 | |
300 | - if (device == null) { | |
301 | 309 | TenantId tenantId = gateway.getTenantId(); |
302 | 310 | device = new Device(); |
303 | 311 | device.setTenantId(tenantId); |
... | ... | @@ -666,4 +674,35 @@ public class DefaultTransportApiService implements TransportApiService { |
666 | 674 | private Long checkLong(Long l) { |
667 | 675 | return l != null ? l : 0; |
668 | 676 | } |
677 | + | |
678 | + | |
679 | + | |
680 | + //Thingskit function | |
681 | + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) { | |
682 | + | |
683 | + int type = requestMsg.getFunctionType(); | |
684 | + UUID scriptId = getUUID(requestMsg.getScriptIdLSB(),requestMsg.getScriptIdMSB()); | |
685 | + | |
686 | + List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes(Arrays.stream(TkScriptFunctionType.values()).filter(f->f.ordinal()==type).findFirst().get(),null,null,scriptId); | |
687 | + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder(); | |
688 | + allScriptes.forEach(item->{ | |
689 | + UUID tenantId = UUID.fromString(item.getTenantId()); | |
690 | + UUID id = UUID.fromString(item.getId()); | |
691 | + responseBuilder.addScriptsResponseMsg(TransportProtos.ScriptProto.newBuilder() | |
692 | + .setConvertJs(item.getConvertJs()) | |
693 | + .setTenantIdLSB(tenantId.getLeastSignificantBits()) | |
694 | + .setTenantIdMSB(tenantId.getMostSignificantBits()) | |
695 | + .setScriptIdLSB(id.getLeastSignificantBits()) | |
696 | + .setScriptIdMSB(id.getMostSignificantBits()) | |
697 | + .setFunctionType(item.getScriptType().ordinal()) | |
698 | + ); | |
699 | + }); | |
700 | + return Futures.immediateFuture(responseBuilder.build()); | |
701 | + } | |
702 | + private UUID getUUID(long lsb,long msb){ | |
703 | + if(lsb==0 && msb==0){ | |
704 | + return null; | |
705 | + } | |
706 | + return new UUID(msb,lsb); | |
707 | + } | |
669 | 708 | } | ... | ... |
... | ... | @@ -679,6 +679,9 @@ message TransportApiRequestMsg { |
679 | 679 | GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 11; |
680 | 680 | GetDeviceRequestMsg deviceRequestMsg = 12; |
681 | 681 | GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 13; |
682 | + | |
683 | + //Thingskit function | |
684 | + ScriptProto script = 14; | |
682 | 685 | } |
683 | 686 | |
684 | 687 | /* Response from ThingsBoard Core Service to Transport Service */ |
... | ... | @@ -693,6 +696,9 @@ message TransportApiResponseMsg { |
693 | 696 | GetOtaPackageResponseMsg otaPackageResponseMsg = 8; |
694 | 697 | GetDeviceResponseMsg deviceResponseMsg = 9; |
695 | 698 | GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10; |
699 | + | |
700 | + //Thingskit function | |
701 | + repeated ScriptProto scriptsResponseMsg = 11; | |
696 | 702 | } |
697 | 703 | |
698 | 704 | /* Messages that are handled by ThingsBoard Core Service */ |
... | ... | @@ -769,3 +775,22 @@ message ToOtaPackageStateServiceMsg { |
769 | 775 | int64 otaPackageIdLSB = 7; |
770 | 776 | string type = 8; |
771 | 777 | } |
778 | + | |
779 | + | |
780 | + | |
781 | + | |
782 | + | |
783 | + | |
784 | + | |
785 | + | |
786 | +//Thingskit function 请求:functionType、;响应:tenantId、projectId、scriptId、convertJs | |
787 | +message ScriptProto{ | |
788 | + int64 tenantIdMSB = 1; | |
789 | + int64 tenantIdLSB = 2; | |
790 | +// int64 projectIdMSB = 3; | |
791 | +// int64 projectIdLSB = 4; | |
792 | + int64 scriptIdMSB = 5; | |
793 | + int64 scriptIdLSB = 6; | |
794 | + int32 functionType = 7; | |
795 | + string convertJs = 8; | |
796 | +} | ... | ... |
1 | -/** | |
2 | - * Copyright © 2016-2022 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | 1 | package org.thingsboard.server.common.data.device.profile; |
17 | 2 | |
18 | 3 | import lombok.Data; |
19 | 4 | import org.thingsboard.server.common.data.DeviceTransportType; |
20 | 5 | import org.thingsboard.server.common.data.validation.NoXss; |
21 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
22 | 6 | |
23 | 7 | @Data |
24 | 8 | public class TkTcpDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration { |
25 | - | |
26 | - @NoXss | |
27 | - private TcpDataTypeEnum dataFormat = TcpDataTypeEnum.HEX; | |
28 | - private String scriptId; | |
29 | - private String scriptText; | |
30 | -// private String pingText; | |
9 | + /** | |
10 | + * 鉴权脚本ID:解析脚本鉴权信息,正确解析结果如下: | |
11 | + * clientId: 设备鉴权客户端ID | |
12 | + * userName: 设备鉴权用户名 | |
13 | + * password: 设备鉴权密码 | |
14 | + * success :鉴权成功返回内容 | |
15 | + */ | |
31 | 16 | @NoXss |
32 | - private String telemetryTopic = "03"; | |
17 | + private String authScriptId; | |
18 | + /** | |
19 | + * 上行脚本ID:设备推送给平台 | |
20 | + */ | |
33 | 21 | @NoXss |
34 | - private String attributesTopic = "01"; | |
22 | + private String upScriptId; | |
23 | + /** | |
24 | + * 下行脚本ID:平台推送给设备 | |
25 | + */ | |
35 | 26 | @NoXss |
36 | - private String rpcTopic = "05"; | |
27 | + private String downScriptId; | |
28 | + | |
37 | 29 | @Override |
38 | 30 | public DeviceTransportType getType() { |
39 | 31 | return DeviceTransportType.TCP; |
40 | 32 | } |
41 | 33 | |
42 | 34 | |
43 | - | |
44 | - | |
45 | 35 | } | ... | ... |
... | ... | @@ -31,9 +31,7 @@ public class DeviceProfileDTO extends BaseDTO { |
31 | 31 | @ApiModelProperty(value = "描述") |
32 | 32 | private String description; |
33 | 33 | |
34 | - /** TCP协议的解析脚本ID,由后端自己回填 */ | |
35 | - @ApiModelProperty(value = "解析脚本ID") | |
36 | - private String scriptId; | |
34 | + | |
37 | 35 | |
38 | 36 | @ApiModelProperty(value = "租户ID") |
39 | 37 | private String tenantId; | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/TkDeviceRpcDTO.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.dto; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | + | |
6 | +import javax.validation.constraints.NotEmpty; | |
7 | +import java.io.Serializable; | |
8 | +import java.util.Map; | |
9 | + | |
10 | + | |
11 | +@Data | |
12 | +public class TkDeviceRpcDTO implements Serializable { | |
13 | + | |
14 | + @ApiModelProperty(value = "命令下发方法名、功能名") | |
15 | + @NotEmpty(message = "功能名不能为空或者空字符串") | |
16 | + private String method; | |
17 | + | |
18 | + @ApiModelProperty(value = "设备名称。添加设备时,设备名称的内容必须与脚本用到的设备标识一致。") | |
19 | + @NotEmpty(message = "设备名称不能为空或者空字符串") | |
20 | + private String deviceCode; | |
21 | + | |
22 | + @ApiModelProperty(value = "数据校验算法") | |
23 | + private String check; | |
24 | + | |
25 | + @ApiModelProperty(value = "数据相关信息,例如:寄存器地址和寄存器数") | |
26 | + @NotEmpty(message = "数据相关信息不能为空或者空字符串") | |
27 | + private Map<String, Object> params; | |
28 | +} | ... | ... |
... | ... | @@ -5,7 +5,7 @@ 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.common.UpdateGroup; |
8 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
8 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
9 | 9 | |
10 | 10 | import javax.validation.constraints.NotEmpty; |
11 | 11 | import javax.validation.constraints.NotNull; |
... | ... | @@ -14,36 +14,37 @@ import javax.validation.constraints.NotNull; |
14 | 14 | @Data |
15 | 15 | public class TkDeviceScriptDTO extends BaseDTO { |
16 | 16 | |
17 | - @ApiModelProperty(value = "解析脚本名称") | |
18 | - @NotEmpty( | |
19 | - message = "解析脚本名称不能为空或者空字符串", | |
20 | - groups = {AddGroup.class, UpdateGroup.class}) | |
21 | - private String name; | |
17 | + @ApiModelProperty(value = "解析脚本名称") | |
18 | + @NotEmpty( | |
19 | + message = "解析脚本名称不能为空或者空字符串", | |
20 | + groups = {AddGroup.class, UpdateGroup.class}) | |
21 | + private String name; | |
22 | 22 | |
23 | - @ApiModelProperty(value = "租户ID") | |
24 | - private String tenantId; | |
23 | + @ApiModelProperty(value = "租户ID") | |
24 | + private String tenantId; | |
25 | 25 | |
26 | - @ApiModelProperty(value = "脚本描述") | |
27 | - private String description; | |
26 | + @ApiModelProperty(value = "脚本描述") | |
27 | + private String description; | |
28 | 28 | |
29 | - @ApiModelProperty(value = "解析脚本方法体内容") | |
30 | - @NotEmpty( | |
31 | - message = "解析脚本内容不能为空或者空字符串", | |
32 | - groups = {AddGroup.class, UpdateGroup.class}) | |
33 | - private String convertJs; | |
29 | + @ApiModelProperty(value = "解析脚本方法体内容") | |
30 | + @NotEmpty( | |
31 | + message = "解析脚本内容不能为空或者空字符串", | |
32 | + groups = {AddGroup.class, UpdateGroup.class}) | |
33 | + private String convertJs; | |
34 | 34 | |
35 | - @ApiModelProperty(value = "状态:0禁用 1启用") | |
36 | - @NotNull(message = "状态不能为空", groups = UpdateGroup.class) | |
37 | - private Integer status; | |
35 | + @ApiModelProperty(value = "状态:0禁用 1启用") | |
36 | + @NotNull(message = "状态不能为空", groups = UpdateGroup.class) | |
37 | + private Integer status; | |
38 | 38 | |
39 | - @ApiModelProperty(value = "脚本编数据编码类型:HEX ASCII") | |
40 | - private TcpDataTypeEnum dataType; | |
39 | + @ApiModelProperty(value = "脚本类型:AUTHENTICATION、SERVER_TO_DEVICE、DEVICE_TO_SERVER") | |
40 | + private TkScriptFunctionType scriptType; | |
41 | 41 | |
42 | - @ApiModelProperty(value = "保存原始数据:默认false") | |
43 | - @NotNull( | |
44 | - message = "保存原始数据不能为空", | |
45 | - groups = {AddGroup.class}) | |
46 | - private boolean saveOriginalData; | |
42 | + @ApiModelProperty(value = "保存原始数据:默认false") | |
43 | + @NotNull( | |
44 | + message = "保存原始数据不能为空", | |
45 | + groups = {AddGroup.class}) | |
46 | + private boolean saveOriginalData; | |
47 | 47 | |
48 | - public TkDeviceScriptDTO() {} | |
48 | + public TkDeviceScriptDTO() { | |
49 | + } | |
49 | 50 | } | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/enums/TkScriptFunctionType.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.enums; | |
2 | + | |
3 | +public enum TkScriptFunctionType { | |
4 | + TRANSPORT_TCP_AUTH, | |
5 | + //var attrData = {};attrData.source= params;out.attributes = attrData;var teleData = {};teleData.source= params;out.telemetries = teleData;out.ackMsg = params;out.deviceName = params;out.ts = Date.now(); | |
6 | + TRANSPORT_TCP_UP, | |
7 | + TRANSPORT_TCP_DOWN, | |
8 | + RULE_ENGINE_TRANSFORM | |
9 | +} | ... | ... |
... | ... | @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
25 | 25 | import org.springframework.stereotype.Component; |
26 | 26 | import org.thingsboard.server.common.transport.TransportContext; |
27 | 27 | import org.thingsboard.server.transport.tcp.adaptors.JsonTcpAdaptor; |
28 | +import org.thingsboard.server.transport.tcp.script.TkScriptInvokeService; | |
28 | 29 | |
29 | 30 | import javax.annotation.PostConstruct; |
30 | 31 | import java.net.InetSocketAddress; |
... | ... | @@ -47,6 +48,9 @@ public class TcpTransportContext extends TransportContext { |
47 | 48 | @Autowired |
48 | 49 | private JsonTcpAdaptor jsonTcpAdaptor; |
49 | 50 | |
51 | + @Getter | |
52 | + @Autowired | |
53 | + private TkScriptInvokeService jsEngine; | |
50 | 54 | |
51 | 55 | @Getter |
52 | 56 | @Value("${transport.tcp.netty.max_payload_size}") | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
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 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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. |
... | ... | @@ -16,6 +16,10 @@ |
16 | 16 | package org.thingsboard.server.transport.tcp; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import com.google.common.util.concurrent.FutureCallback; | |
20 | +import com.google.common.util.concurrent.Futures; | |
21 | +import com.google.common.util.concurrent.ListenableFuture; | |
22 | +import com.google.common.util.concurrent.MoreExecutors; | |
19 | 23 | import io.netty.buffer.ByteBuf; |
20 | 24 | import io.netty.buffer.Unpooled; |
21 | 25 | import io.netty.channel.ChannelFuture; |
... | ... | @@ -28,16 +32,16 @@ import io.netty.util.concurrent.Future; |
28 | 32 | import io.netty.util.concurrent.GenericFutureListener; |
29 | 33 | import lombok.extern.slf4j.Slf4j; |
30 | 34 | import org.apache.commons.lang3.StringUtils; |
35 | +import org.checkerframework.checker.nullness.qual.Nullable; | |
36 | +import org.thingsboard.common.util.JacksonUtil; | |
31 | 37 | import org.thingsboard.server.common.data.DataConstants; |
32 | 38 | import org.thingsboard.server.common.data.Device; |
33 | 39 | import org.thingsboard.server.common.data.DeviceProfile; |
34 | 40 | import org.thingsboard.server.common.data.DeviceTransportType; |
41 | +import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration; | |
35 | 42 | import org.thingsboard.server.common.data.id.DeviceId; |
36 | -import org.thingsboard.server.common.data.id.OtaPackageId; | |
37 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | |
38 | 43 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
39 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
40 | -import org.thingsboard.server.common.msg.EncryptionUtil; | |
44 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
41 | 45 | import org.thingsboard.server.common.msg.tools.TbRateLimitsException; |
42 | 46 | import org.thingsboard.server.common.transport.SessionMsgListener; |
43 | 47 | import org.thingsboard.server.common.transport.TransportService; |
... | ... | @@ -48,31 +52,28 @@ import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; |
48 | 52 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
49 | 53 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
50 | 54 | import org.thingsboard.server.common.transport.service.SessionMetaData; |
51 | -import org.thingsboard.server.common.transport.util.SslUtil; | |
52 | 55 | import org.thingsboard.server.gen.transport.TransportProtos; |
53 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; | |
56 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
57 | +import org.thingsboard.server.transport.tcp.adaptors.TcpAuthEntry; | |
54 | 58 | import org.thingsboard.server.transport.tcp.adaptors.TcpTransportAdaptor; |
59 | +import org.thingsboard.server.transport.tcp.adaptors.TcpUpEntry; | |
60 | +import org.thingsboard.server.transport.tcp.script.TkScriptFactory; | |
55 | 61 | import org.thingsboard.server.transport.tcp.session.TcpDeviceSessionCtx; |
56 | -import org.thingsboard.server.transport.tcp.session.TCPMessage; | |
57 | 62 | import org.thingsboard.server.transport.tcp.session.TcpGatewaySessionHandler; |
58 | 63 | import org.thingsboard.server.transport.tcp.util.ByteUtils; |
59 | 64 | |
60 | -import javax.net.ssl.SSLPeerUnverifiedException; | |
61 | 65 | import java.io.IOException; |
62 | 66 | import java.io.UnsupportedEncodingException; |
63 | 67 | import java.net.InetSocketAddress; |
64 | -import java.security.cert.Certificate; | |
65 | -import java.security.cert.X509Certificate; | |
66 | 68 | import java.util.List; |
69 | +import java.util.Map; | |
67 | 70 | import java.util.Optional; |
68 | 71 | import java.util.UUID; |
69 | 72 | import java.util.concurrent.ConcurrentHashMap; |
70 | 73 | import java.util.concurrent.ConcurrentMap; |
71 | -import java.util.regex.Matcher; | |
74 | +import java.util.concurrent.atomic.AtomicInteger; | |
72 | 75 | |
73 | -import static com.amazonaws.util.StringUtils.UTF8; | |
74 | 76 | import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED; |
75 | -import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; | |
76 | 77 | import static io.netty.handler.codec.mqtt.MqttMessageType.PUBACK; |
77 | 78 | import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK; |
78 | 79 | import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE; |
... | ... | @@ -92,7 +93,9 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
92 | 93 | private final SslHandler sslHandler; |
93 | 94 | |
94 | 95 | |
95 | - /**需要处理的消息队列,例如:需要下发给设备的,设备上传的。*/ | |
96 | + /** | |
97 | + * 需要处理的消息队列,例如:需要下发给设备的,设备上传的。 | |
98 | + */ | |
96 | 99 | final TcpDeviceSessionCtx deviceSessionCtx; |
97 | 100 | volatile InetSocketAddress address; |
98 | 101 | |
... | ... | @@ -100,7 +103,8 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
100 | 103 | private final ConcurrentHashMap<String, String> otaPackSessions; |
101 | 104 | private final ConcurrentHashMap<String, Integer> chunkSizes; |
102 | 105 | private final ConcurrentMap<Integer, TransportProtos.ToDeviceRpcRequestMsg> rpcAwaitingAck; |
103 | - | |
106 | + private final ConcurrentMap<UUID, String> authScripts; | |
107 | + private final AtomicInteger authedCounter = new AtomicInteger(); | |
104 | 108 | |
105 | 109 | |
106 | 110 | TcpTransportHandler(TcpTransportContext context, SslHandler sslHandler) { |
... | ... | @@ -112,6 +116,22 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
112 | 116 | this.otaPackSessions = new ConcurrentHashMap<>(); |
113 | 117 | this.chunkSizes = new ConcurrentHashMap<>(); |
114 | 118 | this.rpcAwaitingAck = new ConcurrentHashMap<>(); |
119 | + this.authScripts = new ConcurrentHashMap<>(); | |
120 | + List<ScriptProto> authScripts = this.transportService.getScripts(ScriptProto.newBuilder().setFunctionType(TkScriptFunctionType.TRANSPORT_TCP_AUTH.ordinal()).build()); | |
121 | + authScripts.stream().forEach(i -> { | |
122 | + UUID scriptId = new UUID(i.getScriptIdMSB(), i.getScriptIdLSB()); | |
123 | + deviceSessionCtx.cacheScript(scriptId, TkScriptFunctionType.TRANSPORT_TCP_AUTH, i.getConvertJs(), new FutureCallback<UUID>() { | |
124 | + @Override | |
125 | + public void onSuccess(@Nullable UUID result) { | |
126 | + TcpTransportHandler.this.authScripts.put(scriptId, result.toString()); | |
127 | + } | |
128 | + | |
129 | + @Override | |
130 | + public void onFailure(Throwable t) { | |
131 | + } | |
132 | + }); | |
133 | + | |
134 | + }); | |
115 | 135 | } |
116 | 136 | |
117 | 137 | @Override |
... | ... | @@ -136,12 +156,13 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
136 | 156 | if (msg instanceof ByteBuf) { |
137 | 157 | ByteBuf message = (ByteBuf) msg; |
138 | 158 | byte[] byteMsg = ByteUtils.buf2Bytes(message); |
139 | - | |
159 | + String msgStr = ByteUtils.getString(byteMsg, ByteUtils.UTF_8); | |
160 | + log.error("会话【{}】收到设备【{}】来自【{}】数据【{}】", sessionId, deviceSessionCtx.getDeviceId(), address, msgStr); | |
140 | 161 | deviceSessionCtx.setChannel(ctx); |
141 | - if (deviceSessionCtx.getDeviceInfo() == null || deviceSessionCtx.getDeviceProfile() == null) { | |
142 | - processConnect(ctx, ByteUtils.getString(byteMsg, ByteUtils.UTF_8)); | |
162 | + if (deviceSessionCtx.getDeviceInfo() == null || deviceSessionCtx.getDeviceProfile() == null) { | |
163 | + processConnect(ctx, msgStr); | |
143 | 164 | } else { |
144 | - enqueueRegularSessionMsg(ctx,message); | |
165 | + enqueueRegularSessionMsg(ctx, msgStr); | |
145 | 166 | } |
146 | 167 | |
147 | 168 | } else { |
... | ... | @@ -167,9 +188,7 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
167 | 188 | } |
168 | 189 | |
169 | 190 | |
170 | - | |
171 | - | |
172 | - void enqueueRegularSessionMsg(ChannelHandlerContext ctx, ByteBuf msg) { | |
191 | + void enqueueRegularSessionMsg(ChannelHandlerContext ctx, String msg) { | |
173 | 192 | final int queueSize = deviceSessionCtx.getMsgQueueSize(); |
174 | 193 | if (queueSize >= context.getMessageQueueSizePerDeviceLimit()) { |
175 | 194 | log.info("Closing current session because msq queue size for device {} exceed limit {} with msgQueueSize counter {} and actual queue size {}", |
... | ... | @@ -178,14 +197,12 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
178 | 197 | return; |
179 | 198 | } |
180 | 199 | |
181 | - TCPMessage message =deviceSessionCtx.getPayloadAdaptor().createTcpMessage(deviceSessionCtx,msg); | |
182 | - deviceSessionCtx.addToQueue(message); | |
200 | + deviceSessionCtx.addToQueue(msg); | |
183 | 201 | processQueueMessage(ctx); //Under the normal conditions the msg queue will contain 0 messages. Many messages will be processed on device connect event in separate thread pool |
184 | 202 | |
185 | 203 | } |
186 | 204 | |
187 | 205 | |
188 | - | |
189 | 206 | void processQueueMessage(ChannelHandlerContext ctx) { |
190 | 207 | if (!deviceSessionCtx.isConnected()) { |
191 | 208 | log.trace("[{}][{}] Postpone processing msg due to device is not connected. Msg queue size is {}", sessionId, deviceSessionCtx.getDeviceId(), deviceSessionCtx.getMsgQueueSize()); |
... | ... | @@ -195,128 +212,81 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
195 | 212 | } |
196 | 213 | |
197 | 214 | |
215 | + private void processDeviceSessionMsg(ChannelHandlerContext ctx, String tcpMessage) { | |
216 | + if (!checkConnected(ctx, tcpMessage)) { | |
217 | + return; | |
218 | + } | |
219 | + deviceSessionCtx.doUpScript(tcpMessage, r -> { | |
220 | + if (gatewaySessionHandler != null) { | |
221 | + processGatewayDeviceMsg(ctx, r); | |
198 | 222 | |
223 | + if (!hasDatas(r.getDatas(), true)) { | |
224 | + transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | |
225 | + return; | |
226 | + } | |
227 | + } | |
199 | 228 | |
200 | 229 | |
230 | + processDirectDeviceMsg(ctx, r); | |
231 | + }); | |
201 | 232 | |
202 | - private void processDeviceSessionMsg(ChannelHandlerContext ctx, TCPMessage tcpMessage) { | |
203 | - if (!checkConnected(ctx, tcpMessage)) { | |
204 | - return; | |
233 | + } | |
234 | + | |
235 | + | |
236 | + private boolean hasDatas(Map<String, Object> datas, boolean includeSource) { | |
237 | + if (datas == null || datas.isEmpty()) { | |
238 | + return false; | |
205 | 239 | } |
206 | - log.error("【{}】设备【{}】收到数据【{}】", sessionId,deviceSessionCtx.getDeviceId(), tcpMessage.getMessage()); | |
207 | - if (!deviceSessionCtx.getDeviceCode().equals(tcpMessage.getMessage()) && gatewaySessionHandler != null) { | |
208 | - processGatewayDeviceMsg(ctx, tcpMessage); | |
209 | - transportService.reportActivity(deviceSessionCtx.getSessionInfo()); | |
210 | - } else { | |
211 | - processDirectDeviceMsg(ctx,tcpMessage); | |
240 | + if (includeSource && !datas.containsKey(TkScriptFactory.ORIGINAL_DATA_FILED)) { | |
241 | + return false; | |
212 | 242 | } |
243 | + return true; | |
213 | 244 | } |
214 | 245 | |
215 | 246 | |
216 | - private void processGatewayDeviceMsg(ChannelHandlerContext ctx, TCPMessage tcpMessage) { | |
217 | - log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage.getMessage()); | |
247 | + private void processGatewayDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | |
248 | + log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage); | |
218 | 249 | try { |
219 | - String topicName = tcpMessage.getTopic(); | |
220 | - if (deviceSessionCtx.isDeviceAttributesTopic(topicName)) { | |
221 | - gatewaySessionHandler.onDeviceAttributes(tcpMessage); | |
222 | - } else if (deviceSessionCtx.isDeviceTelemetryTopic(topicName)) { | |
223 | - gatewaySessionHandler.onDeviceTelemetry(tcpMessage); | |
224 | - | |
225 | - } else if (deviceSessionCtx.isToDeviceRpcResponseTopic(topicName)) { | |
250 | + Map<String, Object> datas = tcpMessage.getDatas(); | |
251 | + if (hasDatas(datas, false)) { | |
252 | + datas.forEach((devName, param) -> { | |
253 | + if (TkScriptFactory.ORIGINAL_DATA_FILED.equals(devName)) { | |
254 | + return; | |
255 | + } | |
256 | + if (tcpMessage.getTelemetry()) { | |
257 | + gatewaySessionHandler.onDeviceTelemetry(devName, tcpMessage.getRequestId(), param.toString()); | |
258 | + } else { | |
259 | + gatewaySessionHandler.onDeviceAttributes(devName, tcpMessage.getRequestId(), param.toString()); | |
260 | + } | |
226 | 261 | |
262 | + }); | |
227 | 263 | } else { |
228 | 264 | transportService.reportActivity(deviceSessionCtx.getSessionInfo()); |
229 | - pushDeviceMsg(ctx,tcpMessage); | |
265 | + pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | |
230 | 266 | } |
231 | - } catch (AdaptorException e) { | |
267 | + } catch (Exception e) { | |
232 | 268 | log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); |
233 | 269 | ctx.close(); |
234 | 270 | } |
235 | 271 | } |
236 | 272 | |
237 | - private void processDirectDeviceMsg(ChannelHandlerContext ctx, TCPMessage tcpMessage) { | |
238 | - log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage.getMessage()); | |
273 | + private void processDirectDeviceMsg(ChannelHandlerContext ctx, TcpUpEntry tcpMessage) { | |
274 | + log.trace("[{}][{}] Processing publish msg [{}]!", sessionId, deviceSessionCtx.getDeviceId(), tcpMessage); | |
239 | 275 | try { |
240 | - String topicName = tcpMessage.getTopic(); | |
241 | 276 | TcpTransportAdaptor payloadAdaptor = deviceSessionCtx.getPayloadAdaptor(); |
242 | - if (deviceSessionCtx.isDeviceAttributesTopic(topicName)) { | |
243 | -// TransportProtos.PostAttributeMsg postAttributeMsg = payloadAdaptor.convertToPostAttributes(deviceSessionCtx, tcpMessage.getMessage()); | |
244 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, tcpMessage.getRequestId(), postAttributeMsg)); | |
245 | - } else if (deviceSessionCtx.isDeviceTelemetryTopic(topicName)) { | |
246 | - TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, tcpMessage.getMessage()); | |
247 | - transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, null); | |
248 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX)) { | |
249 | -// TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_TOPIC_PREFIX); | |
250 | -// transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg)); | |
251 | -// attrReqTopicType = TopicType.V1; | |
252 | - } else if (deviceSessionCtx.isToDeviceRpcResponseTopic(topicName)) { | |
253 | -// TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, tcpMessage.getMessage(), MqttTopics.DEVICE_RPC_RESPONSE_TOPIC); | |
254 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg)); | |
255 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)) { | |
256 | -// TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC); | |
257 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); | |
258 | -// toServerRpcSubTopicType = TopicType.V1; | |
259 | -// } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) { | |
260 | -// TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg); | |
261 | -// transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg)); | |
262 | -// } else if ((fwMatcher = FW_REQUEST_PATTERN.matcher(topicName)).find()) { | |
263 | -// getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.FIRMWARE); | |
264 | -// } else if ((fwMatcher = SW_REQUEST_PATTERN.matcher(topicName)).find()) { | |
265 | -// getOtaPackageCallback(ctx, mqttMsg, msgId, fwMatcher, OtaPackageType.SOFTWARE); | |
266 | -// } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_TOPIC)) { | |
267 | -// TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, mqttMsg); | |
268 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg)); | |
269 | -// } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_JSON_TOPIC)) { | |
270 | -// TransportProtos.PostTelemetryMsg postTelemetryMsg = context.getJsonMqttAdaptor().convertToPostTelemetry(deviceSessionCtx, mqttMsg); | |
271 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg)); | |
272 | -// } else if (topicName.equals(MqttTopics.DEVICE_TELEMETRY_SHORT_PROTO_TOPIC)) { | |
273 | -// TransportProtos.PostTelemetryMsg postTelemetryMsg = context.getAscallAdaptor().convertToPostTelemetry(deviceSessionCtx, mqttMsg); | |
274 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, msgId, postTelemetryMsg)); | |
275 | -// } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_TOPIC)) { | |
276 | -// TransportProtos.PostAttributeMsg postAttributeMsg = payloadAdaptor.convertToPostAttributes(deviceSessionCtx, mqttMsg); | |
277 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg)); | |
278 | -// } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_JSON_TOPIC)) { | |
279 | -// TransportProtos.PostAttributeMsg postAttributeMsg = context.getJsonMqttAdaptor().convertToPostAttributes(deviceSessionCtx, mqttMsg); | |
280 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg)); | |
281 | -// } else if (topicName.equals(MqttTopics.DEVICE_ATTRIBUTES_SHORT_PROTO_TOPIC)) { | |
282 | -// TransportProtos.PostAttributeMsg postAttributeMsg = context.getAscallAdaptor().convertToPostAttributes(deviceSessionCtx, mqttMsg); | |
283 | -// transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, msgId, postAttributeMsg)); | |
284 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC)) { | |
285 | -// TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = context.getJsonMqttAdaptor().convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_JSON_TOPIC); | |
286 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg)); | |
287 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC)) { | |
288 | -// TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = context.getAscallAdaptor().convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_PROTO_TOPIC); | |
289 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg)); | |
290 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_RESPONSE_SHORT_TOPIC)) { | |
291 | -// TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg = payloadAdaptor.convertToDeviceRpcResponse(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_RESPONSE_SHORT_TOPIC); | |
292 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg)); | |
293 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC)) { | |
294 | -// TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = context.getJsonMqttAdaptor().convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_JSON_TOPIC); | |
295 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); | |
296 | -// toServerRpcSubTopicType = TopicType.V2_JSON; | |
297 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC)) { | |
298 | -// TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = context.getAscallAdaptor().convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_PROTO_TOPIC); | |
299 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); | |
300 | -// toServerRpcSubTopicType = TopicType.V2_PROTO; | |
301 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_SHORT_TOPIC)) { | |
302 | -// TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_SHORT_TOPIC); | |
303 | -// transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); | |
304 | -// toServerRpcSubTopicType = TopicType.V2; | |
305 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX)) { | |
306 | -// TransportProtos.GetAttributeRequestMsg getAttributeMsg = context.getJsonMqttAdaptor().convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_JSON_TOPIC_PREFIX); | |
307 | -// transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg)); | |
308 | -// attrReqTopicType = TopicType.V2_JSON; | |
309 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX)) { | |
310 | -// TransportProtos.GetAttributeRequestMsg getAttributeMsg = context.getAscallAdaptor().convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_PROTO_TOPIC_PREFIX); | |
311 | -// transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg)); | |
312 | -// attrReqTopicType = TopicType.V2_PROTO; | |
313 | -// } else if (topicName.startsWith(MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX)) { | |
314 | -// TransportProtos.GetAttributeRequestMsg getAttributeMsg = payloadAdaptor.convertToGetAttributes(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_ATTRIBUTES_REQUEST_SHORT_TOPIC_PREFIX); | |
315 | -// transportService.process(deviceSessionCtx.getSessionInfo(), getAttributeMsg, getPubAckCallback(ctx, msgId, getAttributeMsg)); | |
316 | -// attrReqTopicType = TopicType.V2; | |
277 | + Map<String, Object> datas = tcpMessage.getDatas(); | |
278 | + if (hasDatas(datas, false)) { | |
279 | + String dataStr = JacksonUtil.toString(datas); | |
280 | + if (tcpMessage.getTelemetry()) { | |
281 | + TransportProtos.PostTelemetryMsg postTelemetryMsg = payloadAdaptor.convertToPostTelemetry(deviceSessionCtx, dataStr); | |
282 | + transportService.process(deviceSessionCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(ctx, tcpMessage)); | |
283 | + } else { | |
284 | + TransportProtos.PostAttributeMsg postAttributeMsg = payloadAdaptor.convertToPostAttributes(deviceSessionCtx, dataStr); | |
285 | + transportService.process(deviceSessionCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(ctx, tcpMessage)); | |
286 | + } | |
317 | 287 | } else { |
318 | 288 | transportService.reportActivity(deviceSessionCtx.getSessionInfo()); |
319 | - pushDeviceMsg(ctx,tcpMessage); | |
289 | + pushDeviceMsg(ctx, tcpMessage.getAckMsg()); | |
320 | 290 | } |
321 | 291 | } catch (AdaptorException e) { |
322 | 292 | log.debug("[{}] Failed to process publish msg [{}][{}]", sessionId, tcpMessage, e); |
... | ... | @@ -324,50 +294,14 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
324 | 294 | } |
325 | 295 | } |
326 | 296 | |
327 | - private void getOtaPackageCallback(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, OtaPackageType type) { | |
328 | - String payload = mqttMsg.content().toString(UTF8); | |
329 | - int chunkSize = StringUtils.isNotEmpty(payload) ? Integer.parseInt(payload) : 0; | |
330 | - String requestId = fwMatcher.group("requestId"); | |
331 | - int chunk = Integer.parseInt(fwMatcher.group("chunk")); | |
332 | - | |
333 | - if (chunkSize > 0) { | |
334 | - this.chunkSizes.put(requestId, chunkSize); | |
335 | - } else { | |
336 | - chunkSize = chunkSizes.getOrDefault(requestId, 0); | |
337 | - } | |
338 | - | |
339 | - if (chunkSize > context.getMaxPayloadSize()) { | |
340 | -// sendOtaPackageError(ctx, PAYLOAD_TOO_LARGE); | |
341 | - return; | |
342 | - } | |
343 | - | |
344 | - String otaPackageId = otaPackSessions.get(requestId); | |
345 | - | |
346 | - if (otaPackageId != null) { | |
347 | - sendOtaPackage(ctx, mqttMsg.variableHeader().packetId(), otaPackageId, requestId, chunkSize, chunk, type); | |
348 | - } else { | |
349 | - TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo(); | |
350 | - TransportProtos.GetOtaPackageRequestMsg getOtaPackageRequestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder() | |
351 | - .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) | |
352 | - .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) | |
353 | - .setTenantIdMSB(sessionInfo.getTenantIdMSB()) | |
354 | - .setTenantIdLSB(sessionInfo.getTenantIdLSB()) | |
355 | - .setType(type.name()) | |
356 | - .build(); | |
357 | - transportService.process(deviceSessionCtx.getSessionInfo(), getOtaPackageRequestMsg, | |
358 | - new OtaPackageCallback(ctx, msgId, getOtaPackageRequestMsg, requestId, chunkSize, chunk)); | |
359 | - } | |
360 | - } | |
361 | - | |
362 | - | |
363 | 297 | |
364 | - private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final String msgId, final TCPMessage msg) { | |
298 | + private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final TcpUpEntry msg) { | |
365 | 299 | return new TransportServiceCallback<>() { |
366 | 300 | @Override |
367 | 301 | public void onSuccess(Void dummy) { |
368 | 302 | log.trace("[{}] Published msg: {}", sessionId, msg); |
369 | - if(StringUtils.isNotEmpty(msgId)){ | |
370 | - pushDeviceMsg(ctx,msg); | |
303 | + if (StringUtils.isNotEmpty(msg.getAckMsg())) { | |
304 | + pushDeviceMsg(ctx, msg.getAckMsg()); | |
371 | 305 | } |
372 | 306 | } |
373 | 307 | |
... | ... | @@ -380,138 +314,63 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
380 | 314 | } |
381 | 315 | |
382 | 316 | |
383 | - private class OtaPackageCallback implements TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> { | |
384 | - private final ChannelHandlerContext ctx; | |
385 | - private final int msgId; | |
386 | - private final TransportProtos.GetOtaPackageRequestMsg msg; | |
387 | - private final String requestId; | |
388 | - private final int chunkSize; | |
389 | - private final int chunk; | |
390 | - | |
391 | - OtaPackageCallback(ChannelHandlerContext ctx, int msgId, TransportProtos.GetOtaPackageRequestMsg msg, String requestId, int chunkSize, int chunk) { | |
392 | - this.ctx = ctx; | |
393 | - this.msgId = msgId; | |
394 | - this.msg = msg; | |
395 | - this.requestId = requestId; | |
396 | - this.chunkSize = chunkSize; | |
397 | - this.chunk = chunk; | |
398 | - } | |
399 | - | |
400 | - @Override | |
401 | - public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) { | |
402 | - if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) { | |
403 | - OtaPackageId firmwareId = new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())); | |
404 | - otaPackSessions.put(requestId, firmwareId.toString()); | |
405 | - sendOtaPackage(ctx, msgId, firmwareId.toString(), requestId, chunkSize, chunk, OtaPackageType.valueOf(response.getType())); | |
406 | - } else { | |
407 | -// sendOtaPackageError(ctx, response.getResponseStatus().toString()); | |
408 | - } | |
409 | - } | |
410 | - | |
411 | - @Override | |
412 | - public void onError(Throwable e) { | |
413 | - log.trace("[{}] Failed to get firmware: {}", sessionId, msg, e); | |
414 | - ctx.close(); | |
415 | - } | |
416 | - } | |
417 | - | |
418 | - private void sendOtaPackage(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, OtaPackageType type) { | |
419 | - log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId); | |
420 | - pushDeviceMsg(ctx,new TCPMessage(requestId)); | |
421 | - try { | |
422 | - byte[] firmwareChunk = context.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk); | |
423 | - deviceSessionCtx.getPayloadAdaptor() | |
424 | - .convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type) | |
425 | - .ifPresent(deviceSessionCtx.getChannel()::writeAndFlush); | |
426 | - } catch (Exception e) { | |
427 | - log.trace("[{}] Failed to send firmware response!", sessionId, e); | |
428 | - } | |
429 | - } | |
430 | - | |
431 | - | |
432 | - | |
433 | 317 | void processConnect(ChannelHandlerContext ctx, String accessToken) { |
434 | 318 | log.debug("[{}][{}] Processing connect msg for client: {}!", address, sessionId, accessToken); |
435 | 319 | |
436 | 320 | if (DataConstants.PROVISION.equals(accessToken) || DataConstants.PROVISION.equals(accessToken)) { |
437 | 321 | deviceSessionCtx.setProvisionOnly(true); |
438 | - ctx.writeAndFlush(createTcpConnAckMsg(CONNECTION_ACCEPTED)); | |
322 | + ctx.writeAndFlush(createTcpConnAckMsg(CONNECTION_ACCEPTED.name())); | |
439 | 323 | } else { |
440 | - X509Certificate cert; | |
441 | - if (sslHandler != null && (cert = getX509Certificate()) != null) { | |
442 | -// processX509CertConnect(ctx, cert, msg); | |
443 | - } else { | |
444 | - processAuthTokenConnect(ctx, accessToken); | |
445 | - } | |
324 | + authScripts.forEach((id, idStr) -> { | |
325 | + ListenableFuture item = context.getJsEngine().invokeFunction(id, accessToken); | |
326 | + Futures.addCallback(item, new FutureCallback<String>() { | |
327 | + @Override | |
328 | + public void onSuccess(@Nullable String result) { | |
329 | + processAuthTokenConnect(ctx, id, JacksonUtil.fromString(result, TcpAuthEntry.class)); | |
330 | + } | |
331 | + | |
332 | + @Override | |
333 | + public void onFailure(Throwable t) { | |
334 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | |
335 | + } | |
336 | + }, MoreExecutors.directExecutor()); | |
337 | + | |
338 | + }); | |
446 | 339 | } |
447 | 340 | } |
448 | 341 | |
449 | - private void processAuthTokenConnect(ChannelHandlerContext ctx, String accessToken) { | |
342 | + private void processAuthTokenConnect(ChannelHandlerContext ctx, UUID scriptId, TcpAuthEntry accessToken) { | |
450 | 343 | |
451 | 344 | log.debug("[{}][{}] Processing connect msg for client with user name: {}!", address, sessionId, accessToken); |
452 | - TransportProtos.ValidateDeviceTokenRequestMsg.Builder request = TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder() | |
453 | - .setToken(accessToken); | |
345 | + TransportProtos.ValidateDeviceTokenRequestMsg.Builder request = TransportProtos.ValidateDeviceTokenRequestMsg.newBuilder(); | |
346 | + if (null != accessToken.getClientId()) { | |
347 | + } | |
348 | + if (null != accessToken.getUserName()) { | |
349 | + } | |
350 | + if (null == accessToken.getPassword()) { | |
351 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_PAYLOAD_FORMAT_INVALID); | |
352 | + return; | |
353 | + } | |
354 | + request.setToken(accessToken.getPassword()); | |
454 | 355 | |
455 | 356 | transportService.process(DeviceTransportType.TCP, request.build(), |
456 | 357 | new TransportServiceCallback<>() { |
457 | 358 | @Override |
458 | 359 | public void onSuccess(ValidateDeviceCredentialsResponse msg) { |
459 | - onValidateDeviceResponse(msg, ctx); | |
360 | + onValidateDeviceResponse(msg, ctx, accessToken, scriptId); | |
460 | 361 | } |
461 | 362 | |
462 | 363 | @Override |
463 | 364 | public void onError(Throwable e) { |
464 | 365 | log.trace("[{}] Failed to process credentials: {}", address, accessToken, e); |
465 | - ctx.writeAndFlush(createTcpConnAckMsg(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE)); | |
466 | - ctx.close(); | |
366 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | |
467 | 367 | } |
468 | 368 | }); |
469 | 369 | } |
470 | 370 | |
471 | - private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert, MqttConnectMessage connectMessage) { | |
472 | - try { | |
473 | - if (!context.isSkipValidityCheckForClientCert()) { | |
474 | - cert.checkValidity(); | |
475 | - } | |
476 | - String strCert = SslUtil.getCertificateString(cert); | |
477 | - String sha3Hash = EncryptionUtil.getSha3Hash(strCert); | |
478 | - transportService.process(DeviceTransportType.MQTT, ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(), | |
479 | - new TransportServiceCallback<>() { | |
480 | - @Override | |
481 | - public void onSuccess(ValidateDeviceCredentialsResponse msg) { | |
482 | - onValidateDeviceResponse(msg, ctx); | |
483 | - } | |
484 | - | |
485 | - @Override | |
486 | - public void onError(Throwable e) { | |
487 | - log.trace("[{}] Failed to process credentials: {}", address, sha3Hash, e); | |
488 | - ctx.writeAndFlush(createTcpConnAckMsg(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE)); | |
489 | - ctx.close(); | |
490 | - } | |
491 | - }); | |
492 | - } catch (Exception e) { | |
493 | - context.onAuthFailure(address); | |
494 | - ctx.writeAndFlush(createTcpConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); | |
495 | - log.trace("[{}] X509 auth failure: {}", sessionId, address, e); | |
496 | - ctx.close(); | |
497 | - } | |
498 | - } | |
499 | - | |
500 | - private X509Certificate getX509Certificate() { | |
501 | - try { | |
502 | - Certificate[] certChain = sslHandler.engine().getSession().getPeerCertificates(); | |
503 | - if (certChain.length > 0) { | |
504 | - return (X509Certificate) certChain[0]; | |
505 | - } | |
506 | - } catch (SSLPeerUnverifiedException e) { | |
507 | - log.warn(e.getMessage()); | |
508 | - return null; | |
509 | - } | |
510 | - return null; | |
511 | - } | |
512 | 371 | |
513 | - private ByteBuf createTcpConnAckMsg(MqttConnectReturnCode msg) { | |
514 | - return Unpooled.copiedBuffer(ByteUtils.hexStr2Bytes(msg.name())); | |
372 | + private ByteBuf createTcpConnAckMsg(String msg) { | |
373 | + return Unpooled.copiedBuffer(ByteUtils.getBytes(msg, ByteUtils.UTF_8)); | |
515 | 374 | } |
516 | 375 | |
517 | 376 | @Override |
... | ... | @@ -538,7 +397,6 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
538 | 397 | } |
539 | 398 | |
540 | 399 | |
541 | - | |
542 | 400 | public static MqttPubAckMessage createMqttPubAckMsg(int requestId) { |
543 | 401 | MqttFixedHeader mqttFixedHeader = |
544 | 402 | new MqttFixedHeader(PUBACK, false, AT_MOST_ONCE, false, 0); |
... | ... | @@ -547,7 +405,7 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
547 | 405 | return new MqttPubAckMessage(mqttFixedHeader, mqttMsgIdVariableHeader); |
548 | 406 | } |
549 | 407 | |
550 | - private boolean checkConnected(ChannelHandlerContext ctx, TCPMessage msg) { | |
408 | + private boolean checkConnected(ChannelHandlerContext ctx, String msg) { | |
551 | 409 | if (deviceSessionCtx.isConnected()) { |
552 | 410 | return true; |
553 | 411 | } else { |
... | ... | @@ -594,22 +452,28 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
594 | 452 | } |
595 | 453 | |
596 | 454 | |
597 | - private void onValidateDeviceResponse(ValidateDeviceCredentialsResponse msg, ChannelHandlerContext ctx) { | |
455 | + private void onValidateDeviceResponse(ValidateDeviceCredentialsResponse msg, ChannelHandlerContext ctx, TcpAuthEntry authEntry, UUID scriptId) { | |
598 | 456 | if (!msg.hasDeviceInfo()) { |
599 | 457 | context.onAuthFailure(address); |
600 | - ctx.writeAndFlush(createTcpConnAckMsg(CONNECTION_REFUSED_NOT_AUTHORIZED)); | |
601 | - ctx.close(); | |
458 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED); | |
602 | 459 | } else { |
460 | + DeviceProfile profile = msg.getDeviceProfile(); | |
461 | + TkTcpDeviceProfileTransportConfiguration tcpConfig = (TkTcpDeviceProfileTransportConfiguration) profile.getProfileData().getTransportConfiguration(); | |
462 | + if (scriptId != null && !tcpConfig.getAuthScriptId().equals(scriptId.toString())) { | |
463 | + authedCounter.incrementAndGet(); | |
464 | + return; | |
465 | + } | |
603 | 466 | context.onAuthSuccess(address); |
604 | 467 | deviceSessionCtx.setDeviceInfo(msg.getDeviceInfo()); |
605 | - deviceSessionCtx.setDeviceProfile(msg.getDeviceProfile()); | |
468 | + deviceSessionCtx.setDeviceProfile(profile); | |
606 | 469 | deviceSessionCtx.setSessionInfo(SessionInfoCreator.create(msg, context, sessionId)); |
607 | 470 | transportService.process(deviceSessionCtx.getSessionInfo(), SESSION_EVENT_MSG_OPEN, new TransportServiceCallback<Void>() { |
608 | 471 | @Override |
609 | 472 | public void onSuccess(Void msg) { |
473 | + authedCounter.incrementAndGet(); | |
610 | 474 | SessionMetaData sessionMetaData = transportService.registerAsyncSession(deviceSessionCtx.getSessionInfo(), TcpTransportHandler.this); |
611 | 475 | checkGatewaySession(sessionMetaData); |
612 | - ctx.writeAndFlush(createTcpConnAckMsg(CONNECTION_ACCEPTED)); | |
476 | + ctx.writeAndFlush(createTcpConnAckMsg(authEntry.getSuccess())); | |
613 | 477 | deviceSessionCtx.setConnected(true); |
614 | 478 | log.debug("[{}] Client connected!", sessionId); |
615 | 479 | |
... | ... | @@ -624,13 +488,20 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
624 | 488 | } else { |
625 | 489 | log.warn("[{}] Failed to submit session event", sessionId, e); |
626 | 490 | } |
627 | - ctx.writeAndFlush(createTcpConnAckMsg(MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE)); | |
628 | - ctx.close(); | |
491 | + onValidateFailed(ctx, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE); | |
629 | 492 | } |
630 | 493 | }); |
631 | 494 | } |
632 | 495 | } |
633 | 496 | |
497 | + private void onValidateFailed(ChannelHandlerContext ctx, MqttConnectReturnCode msg) { | |
498 | + authedCounter.incrementAndGet(); | |
499 | + if (authScripts.size() == authedCounter.incrementAndGet()) { | |
500 | + ctx.writeAndFlush(createTcpConnAckMsg(msg.name())); | |
501 | + ctx.close(); | |
502 | + } | |
503 | + } | |
504 | + | |
634 | 505 | @Override |
635 | 506 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) { |
636 | 507 | // log.trace("[{}] Received get attributes response", sessionId); |
... | ... | @@ -663,7 +534,7 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
663 | 534 | |
664 | 535 | @Override |
665 | 536 | public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { |
666 | - log.error("【{}】下发RPC命令【{}】给设备【{}】", sessionId,rpcRequest.getParams(),deviceSessionCtx.getDeviceInfo().getDeviceName()); | |
537 | + log.error("【{}】下发RPC命令【{}】给设备【{}】", sessionId, rpcRequest.getParams(), deviceSessionCtx.getDeviceInfo().getDeviceName()); | |
667 | 538 | TcpTransportAdaptor adaptor = deviceSessionCtx.getPayloadAdaptor(); |
668 | 539 | try { |
669 | 540 | adaptor.convertToPublish(deviceSessionCtx, rpcRequest).ifPresent(payload -> { |
... | ... | @@ -677,7 +548,7 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
677 | 548 | // } |
678 | 549 | // }, Math.max(0, Math.min(deviceSessionCtx.getContext().getTimeout(), rpcRequest.getExpirationTime() - System.currentTimeMillis())), TimeUnit.MILLISECONDS); |
679 | 550 | // } |
680 | - var cf = pushDeviceMsg(deviceSessionCtx.getChannel(), payload); | |
551 | + var cf = pushDeviceMsg(deviceSessionCtx.getChannel(), payload.getDatas()); | |
681 | 552 | cf.addListener(result -> { |
682 | 553 | if (result.cause() == null) { |
683 | 554 | // if (!isAckExpected(payload)) { |
... | ... | @@ -713,33 +584,22 @@ public class TcpTransportHandler extends ChannelInboundHandlerAdapter implements |
713 | 584 | |
714 | 585 | /** |
715 | 586 | * 往设备推送消息 |
716 | - * @param tcp | |
587 | + * | |
588 | + * @param message | |
717 | 589 | * @return |
718 | 590 | */ |
719 | - private ChannelFuture pushDeviceMsg(ChannelHandlerContext ctx,TCPMessage tcp) { | |
591 | + private ChannelFuture pushDeviceMsg(ChannelHandlerContext ctx, String message) { | |
720 | 592 | try { |
721 | - String message = tcp.getMessage(); | |
722 | - byte[] payloadInBytes ; | |
723 | - if(deviceSessionCtx.getPayloadType().equals(TcpDataTypeEnum.HEX)){ | |
724 | - payloadInBytes = ByteUtils.hexStr2Bytes(message); | |
725 | - }else{ | |
726 | - payloadInBytes = message.getBytes(ByteUtils.UTF_8); | |
727 | - } | |
728 | -// ByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false); | |
729 | -// ByteBuf payload = ALLOCATOR.buffer(); | |
730 | -// payload.writeBytes(payloadInBytes); | |
593 | + byte[] payloadInBytes = message.getBytes(ByteUtils.UTF_8); | |
731 | 594 | ByteBuf payload = Unpooled.copiedBuffer(payloadInBytes); |
732 | 595 | |
733 | 596 | return ctx.writeAndFlush(payload); |
734 | 597 | } catch (UnsupportedEncodingException e) { |
735 | - log.error(e.getMessage(),e); | |
598 | + log.error(e.getMessage(), e); | |
736 | 599 | throw new RuntimeException(e); |
737 | 600 | } |
738 | 601 | } |
739 | 602 | |
740 | - private boolean isAckExpected(MqttMessage message) { | |
741 | - return message.fixedHeader().qosLevel().value() > 0; | |
742 | - } | |
743 | 603 | |
744 | 604 | @Override |
745 | 605 | public void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile) { | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/adaptors/JsonTcpAdaptor.java
... | ... | @@ -25,19 +25,15 @@ import com.google.gson.JsonSyntaxException; |
25 | 25 | import io.netty.buffer.ByteBuf; |
26 | 26 | import io.netty.handler.codec.mqtt.MqttPublishMessage; |
27 | 27 | import lombok.extern.slf4j.Slf4j; |
28 | -import org.springframework.beans.factory.annotation.Autowired; | |
29 | 28 | import org.springframework.stereotype.Component; |
30 | 29 | import org.springframework.util.StringUtils; |
30 | +import org.thingsboard.common.util.JacksonUtil; | |
31 | 31 | import org.thingsboard.server.common.data.ota.OtaPackageType; |
32 | 32 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
33 | 33 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
34 | -import org.thingsboard.server.common.yunteng.script.TkScriptInvokeService; | |
35 | -import org.thingsboard.server.common.yunteng.script.TkScriptType; | |
36 | 34 | import org.thingsboard.server.gen.transport.TransportProtos; |
37 | -import org.thingsboard.server.transport.tcp.session.TCPMessage; | |
38 | 35 | import org.thingsboard.server.transport.tcp.session.TcpDeviceWareSessionContext; |
39 | 36 | |
40 | -import java.io.UnsupportedEncodingException; | |
41 | 37 | import java.nio.charset.Charset; |
42 | 38 | import java.nio.charset.StandardCharsets; |
43 | 39 | import java.util.*; |
... | ... | @@ -52,33 +48,22 @@ import java.util.concurrent.ExecutionException; |
52 | 48 | public class JsonTcpAdaptor implements TcpTransportAdaptor { |
53 | 49 | |
54 | 50 | protected static final Charset UTF8 = StandardCharsets.UTF_8; |
55 | - @Autowired | |
56 | - private TkScriptInvokeService jsEngine; | |
57 | 51 | private static final JsonParser parser = new JsonParser(); |
58 | 52 | |
53 | + | |
59 | 54 | @Override |
60 | - public TransportProtos.PostTelemetryMsg convertToPostTelemetry(TcpDeviceWareSessionContext ctx, String inbound) throws AdaptorException { | |
55 | + public TransportProtos.PostTelemetryMsg convertToPostTelemetry(TcpDeviceWareSessionContext ctx, String payload) throws AdaptorException { | |
61 | 56 | try { |
62 | - JsonElement payload = validatePayload(ctx, inbound, false); | |
63 | - return JsonConverter.convertToTelemetryProto(payload); | |
57 | + return JsonConverter.convertToTelemetryProto(new JsonParser().parse(payload)); | |
64 | 58 | } catch (IllegalStateException | JsonSyntaxException ex) { |
65 | 59 | log.debug("Failed to decode post telemetry request", ex); |
66 | 60 | throw new AdaptorException(ex); |
67 | - } catch (ExecutionException e) { | |
68 | - throw new RuntimeException(e); | |
69 | - } catch (InterruptedException e) { | |
70 | - throw new RuntimeException(e); | |
71 | 61 | } |
72 | 62 | } |
73 | 63 | |
74 | - @Override | |
75 | - public UUID getJsScriptEngineFunctionId(String scriptBody, String... argNames) throws ExecutionException, InterruptedException { | |
76 | - return jsEngine.eval(TkScriptType.TCP_TRANSPORT_SCRIPT, scriptBody, argNames).get(); | |
77 | - } | |
78 | 64 | |
79 | 65 | @Override |
80 | - public TransportProtos.PostAttributeMsg convertToPostAttributes(TcpDeviceWareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException { | |
81 | - String payload = validatePayload(ctx.getSessionId(), inbound.payload(), false); | |
66 | + public TransportProtos.PostAttributeMsg convertToPostAttributes(TcpDeviceWareSessionContext ctx, String payload) throws AdaptorException { | |
82 | 67 | try { |
83 | 68 | return JsonConverter.convertToAttributesProto(new JsonParser().parse(payload)); |
84 | 69 | } catch (IllegalStateException | JsonSyntaxException ex) { |
... | ... | @@ -124,57 +109,44 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
124 | 109 | } |
125 | 110 | |
126 | 111 | @Override |
127 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | |
112 | + public Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | |
128 | 113 | return processConvertFromAttributeResponseMsg(ctx, responseMsg, topicBase); |
129 | 114 | } |
130 | 115 | |
131 | 116 | @Override |
132 | - public Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { | |
117 | + public Optional<TcpUpEntry> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { | |
133 | 118 | return processConvertFromGatewayAttributeResponseMsg(ctx, deviceName, responseMsg); |
134 | 119 | } |
135 | 120 | |
136 | 121 | @Override |
137 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg, String topic) { | |
122 | + public Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg, String topic) { | |
138 | 123 | return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(notificationMsg))); |
139 | 124 | } |
140 | 125 | |
141 | - @Override | |
142 | - public Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.AttributeUpdateNotificationMsg notificationMsg) { | |
143 | - JsonObject result = JsonConverter.getJsonObjectForGateway(deviceName, notificationMsg); | |
144 | - return Optional.of(createTcpMessage(ctx, result)); | |
145 | - } | |
146 | 126 | |
147 | 127 | @Override |
148 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws UnsupportedEncodingException { | |
149 | - byte[] result = null; | |
150 | - String payload = rpcRequest.getParams();//methodThingskit | |
151 | -// if(ctx.getPayloadType().equals(TcpDataTypeEnum.ASCII)){ | |
152 | -// }else{ | |
153 | -// result= ByteUtils.hexToBytes(payload); | |
154 | -// } | |
155 | - if (!payload.startsWith("{") && !payload.endsWith("}")) { | |
156 | - payload = payload.replace("\"","");; | |
157 | - } | |
158 | - return Optional.of(createTcpMessage(ctx, payload)); | |
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()); | |
159 | 131 | } |
160 | 132 | |
161 | 133 | @Override |
162 | - public Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { | |
134 | + public Optional<TcpUpEntry> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) { | |
163 | 135 | return Optional.of(createTcpMessage(ctx, JsonConverter.toGatewayJson(deviceName, rpcRequest))); |
164 | 136 | } |
165 | 137 | |
166 | 138 | @Override |
167 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse, String topicBase) { | |
139 | + public Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse, String topicBase) { | |
168 | 140 | return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(rpcResponse))); |
169 | 141 | } |
170 | 142 | |
171 | 143 | @Override |
172 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ProvisionDeviceResponseMsg provisionResponse) { | |
144 | + public Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, TransportProtos.ProvisionDeviceResponseMsg provisionResponse) { | |
173 | 145 | return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(provisionResponse))); |
174 | 146 | } |
175 | 147 | |
176 | 148 | @Override |
177 | - public Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) { | |
149 | + public Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) { | |
178 | 150 | return Optional.of(null); |
179 | 151 | } |
180 | 152 | |
... | ... | @@ -235,7 +207,7 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
235 | 207 | } |
236 | 208 | } |
237 | 209 | |
238 | - private Optional<TCPMessage> processConvertFromAttributeResponseMsg(TcpDeviceWareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | |
210 | + private Optional<TcpUpEntry> processConvertFromAttributeResponseMsg(TcpDeviceWareSessionContext ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | |
239 | 211 | if (!StringUtils.isEmpty(responseMsg.getError())) { |
240 | 212 | throw new AdaptorException(responseMsg.getError()); |
241 | 213 | } else { |
... | ... | @@ -248,7 +220,7 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
248 | 220 | } |
249 | 221 | } |
250 | 222 | |
251 | - private Optional<TCPMessage> processConvertFromGatewayAttributeResponseMsg(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { | |
223 | + private Optional<TcpUpEntry> processConvertFromGatewayAttributeResponseMsg(TcpDeviceWareSessionContext ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { | |
252 | 224 | if (!StringUtils.isEmpty(responseMsg.getError())) { |
253 | 225 | throw new AdaptorException(responseMsg.getError()); |
254 | 226 | } else { |
... | ... | @@ -278,34 +250,13 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
278 | 250 | return payload; |
279 | 251 | } |
280 | 252 | |
281 | - private JsonElement validatePayload(TcpDeviceWareSessionContext session, String payload, boolean isEmptyPayloadAllowed) throws AdaptorException, ExecutionException, InterruptedException { | |
282 | - if (payload == null) { | |
283 | - log.debug("[{}] Payload is empty!", session.getSessionId()); | |
284 | - if (!isEmptyPayloadAllowed) { | |
285 | - throw new AdaptorException(new IllegalArgumentException("Payload is empty!")); | |
286 | - } | |
287 | - } | |
288 | -// jsEngine.invokeFunction(); | |
289 | -// new JsonParser().parse(payload) | |
290 | -// return payload; | |
291 | - ListenableFuture<JsonElement> result = Futures.transformAsync(jsEngine.invokeFunction(session.getScriptId(), payload), | |
292 | - o -> { | |
293 | - try { | |
294 | - return Futures.immediateFuture(parser.parse(o.toString())); | |
295 | - } catch (Exception e) { | |
296 | - return Futures.immediateFailedFuture(e); | |
297 | - } | |
298 | - }, MoreExecutors.directExecutor()); | |
299 | - | |
300 | - return result.get(); | |
301 | - } | |
302 | 253 | |
303 | 254 | private int getRequestId(String topicName, String topic) { |
304 | 255 | return Integer.parseInt(topicName.substring(topic.length())); |
305 | 256 | } |
306 | 257 | |
307 | 258 | |
308 | - protected TCPMessage createTcpMessage(TcpDeviceWareSessionContext ctx, JsonElement json) { | |
259 | + protected TcpUpEntry createTcpMessage(TcpDeviceWareSessionContext ctx, JsonElement json) { | |
309 | 260 | // TCPMessage msg = new TCPMessage(MqttMessageType.PUBLISH,); |
310 | 261 | //// new MqttFixedHeader(MqttMessageType.PUBLISH, false, ctx.getQoSForTopic(topic), false, 0); |
311 | 262 | // MqttPublishVariableHeader header = new MqttPublishVariableHeader(topic, ctx.nextMsgId()); |
... | ... | @@ -315,12 +266,5 @@ public class JsonTcpAdaptor implements TcpTransportAdaptor { |
315 | 266 | return null; |
316 | 267 | } |
317 | 268 | |
318 | - protected TCPMessage createTcpMessage(TcpDeviceWareSessionContext ctx, String payload) { | |
319 | - TCPMessage message = new TCPMessage(payload); | |
320 | - message.setRequestId(payload.substring(0, 4)); | |
321 | - message.setTopic(payload.substring(2, 4)); | |
322 | - message.setDeviceCode(payload.substring(0, 2)); | |
323 | - return message; | |
324 | - } | |
325 | 269 | |
326 | 270 | } | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/adaptors/TcpAuthEntry.java
0 → 100644
1 | +package org.thingsboard.server.transport.tcp.adaptors; | |
2 | + | |
3 | +import lombok.Data; | |
4 | + | |
5 | +import java.io.Serializable; | |
6 | + | |
7 | +@Data | |
8 | +public class TcpAuthEntry implements Serializable { | |
9 | + /** clientId: 设备鉴权客户端ID */ | |
10 | + private String clientId; | |
11 | + /** userName: 设备鉴权用户名 */ | |
12 | + private String userName; | |
13 | + /** password: 设备鉴权密码 */ | |
14 | + private String password; | |
15 | + /** success :鉴权成功返回内容 */ | |
16 | + private String success; | |
17 | + | |
18 | +} | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/adaptors/TcpDownEntry.java
0 → 100644
1 | +package org.thingsboard.server.transport.tcp.adaptors; | |
2 | + | |
3 | +import lombok.AllArgsConstructor; | |
4 | +import lombok.Data; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.util.UUID; | |
8 | + | |
9 | +/** | |
10 | + * 下行脚本 | |
11 | + */ | |
12 | +@Data | |
13 | +@AllArgsConstructor | |
14 | +public class TcpDownEntry implements Serializable { | |
15 | + | |
16 | + /** | |
17 | + * 消息ID,用于请求与响应的匹配,例如:modbus由地址码和功能码组成。 | |
18 | + */ | |
19 | + private UUID requestId; | |
20 | + /** | |
21 | + * 设备名称、设备标识 | |
22 | + */ | |
23 | + private String deviceName; | |
24 | + /** | |
25 | + * 下发给设备的最终内容 | |
26 | + */ | |
27 | + private String datas; | |
28 | +} | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
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 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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. |
... | ... | @@ -18,17 +18,13 @@ package org.thingsboard.server.transport.tcp.adaptors; |
18 | 18 | import io.netty.buffer.ByteBuf; |
19 | 19 | import io.netty.handler.codec.mqtt.MqttPublishMessage; |
20 | 20 | import org.thingsboard.server.common.data.ota.OtaPackageType; |
21 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
22 | 21 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
23 | 22 | import org.thingsboard.server.gen.transport.TransportProtos.*; |
24 | 23 | import org.thingsboard.server.transport.tcp.session.TcpDeviceWareSessionContext; |
25 | -import org.thingsboard.server.transport.tcp.session.TCPMessage; | |
26 | 24 | |
27 | -import java.io.UnsupportedEncodingException; | |
28 | 25 | import java.nio.charset.Charset; |
29 | 26 | import java.nio.charset.StandardCharsets; |
30 | 27 | import java.util.Optional; |
31 | -import java.util.UUID; | |
32 | 28 | import java.util.concurrent.ExecutionException; |
33 | 29 | |
34 | 30 | /** |
... | ... | @@ -40,10 +36,20 @@ public interface TcpTransportAdaptor { |
40 | 36 | static char[] HEX_VOCABLE = {'0', '1', '2', '3', '4', '5', '6', '7', |
41 | 37 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; |
42 | 38 | static final Charset UTF8 = StandardCharsets.UTF_8; |
39 | + | |
40 | + | |
41 | + /** | |
42 | + * 设备数据转遥测数据 | |
43 | + * | |
44 | + * @param ctx | |
45 | + * @param inbound 设备上报的数据字符串 | |
46 | + * @return 平台需要的遥测数据 | |
47 | + * @throws AdaptorException | |
48 | + */ | |
43 | 49 | PostTelemetryMsg convertToPostTelemetry(TcpDeviceWareSessionContext ctx, String inbound) throws AdaptorException; |
44 | 50 | |
45 | - UUID getJsScriptEngineFunctionId(String scriptBody, String... argNames) throws ExecutionException, InterruptedException; | |
46 | - PostAttributeMsg convertToPostAttributes(TcpDeviceWareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException; | |
51 | + | |
52 | + PostAttributeMsg convertToPostAttributes(TcpDeviceWareSessionContext ctx, String inbound) throws AdaptorException; | |
47 | 53 | |
48 | 54 | GetAttributeRequestMsg convertToGetAttributes(TcpDeviceWareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException; |
49 | 55 | |
... | ... | @@ -53,31 +59,32 @@ public interface TcpTransportAdaptor { |
53 | 59 | |
54 | 60 | ClaimDeviceMsg convertToClaimDevice(TcpDeviceWareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException; |
55 | 61 | |
56 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException; | |
62 | + Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException; | |
57 | 63 | |
58 | - Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, GetAttributeResponseMsg responseMsg) throws AdaptorException; | |
64 | + Optional<TcpUpEntry> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, GetAttributeResponseMsg responseMsg) throws AdaptorException; | |
59 | 65 | |
60 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg, String topic) throws AdaptorException; | |
66 | + Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg, String topic) throws AdaptorException; | |
61 | 67 | |
62 | - Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException; | |
63 | 68 | |
64 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException, UnsupportedEncodingException; | |
69 | + Optional<TcpDownEntry> convertToPublish(TcpDeviceWareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest) throws ExecutionException, InterruptedException; | |
65 | 70 | |
66 | - Optional<TCPMessage> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; | |
71 | + Optional<TcpUpEntry> convertToGatewayPublish(TcpDeviceWareSessionContext ctx, String deviceName, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException; | |
67 | 72 | |
68 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, ToServerRpcResponseMsg rpcResponse, String topicBase) throws AdaptorException; | |
73 | + Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, ToServerRpcResponseMsg rpcResponse, String topicBase) throws AdaptorException; | |
69 | 74 | |
70 | 75 | ProvisionDeviceRequestMsg convertToProvisionRequestMsg(TcpDeviceWareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException; |
71 | 76 | |
72 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException; | |
77 | + Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException; | |
78 | + | |
79 | + Optional<TcpUpEntry> convertToPublish(TcpDeviceWareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException; | |
73 | 80 | |
74 | - Optional<TCPMessage> convertToPublish(TcpDeviceWareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException; | |
75 | 81 | public static byte[] toBytes(ByteBuf inbound) { |
76 | 82 | byte[] bytes = new byte[inbound.readableBytes()]; |
77 | 83 | int readerIndex = inbound.readerIndex(); |
78 | 84 | inbound.getBytes(readerIndex, bytes); |
79 | 85 | return bytes; |
80 | 86 | } |
87 | + | |
81 | 88 | public static String bytesToHex(byte[] bs) { |
82 | 89 | StringBuilder sb = new StringBuilder(); |
83 | 90 | for (byte b : bs) { |
... | ... | @@ -88,18 +95,4 @@ public interface TcpTransportAdaptor { |
88 | 95 | } |
89 | 96 | return sb.toString(); |
90 | 97 | } |
91 | - default TCPMessage createTcpMessage(TcpDeviceWareSessionContext ctx, ByteBuf payload) { | |
92 | - String payloadStr; | |
93 | - if(ctx.getPayloadType().equals(TcpDataTypeEnum.HEX)){ | |
94 | - byte[] payloadBytes = toBytes(payload); | |
95 | - payloadStr = bytesToHex(payloadBytes); | |
96 | - }else{ | |
97 | - payloadStr = payload.toString(UTF8); | |
98 | - } | |
99 | - TCPMessage message = new TCPMessage(payloadStr); | |
100 | - message.setRequestId(payloadStr.substring(0,4)); | |
101 | - message.setTopic(payloadStr.substring(2,4)); | |
102 | - message.setDeviceCode(payloadStr.substring(0,2)); | |
103 | - return message; | |
104 | - } | |
105 | 98 | } | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/adaptors/TcpUpEntry.java
0 → 100644
1 | +package org.thingsboard.server.transport.tcp.adaptors; | |
2 | + | |
3 | +import lombok.AllArgsConstructor; | |
4 | +import lombok.Data; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.util.Map; | |
8 | +import java.util.UUID; | |
9 | + | |
10 | +/** | |
11 | + * 上行脚本解析对象 | |
12 | + * 字符串解析为JSON对象 | |
13 | + */ | |
14 | +@Data | |
15 | +@AllArgsConstructor | |
16 | +public class TcpUpEntry implements Serializable { | |
17 | + | |
18 | + /** | |
19 | + * 消息ID,用于请求与响应的匹配,例如:modbus由地址码和功能码组成。 | |
20 | + */ | |
21 | + private UUID requestId; | |
22 | + | |
23 | + /** | |
24 | + * 设备上报的设备端数据,格式:网关设备多个子设备,直连设备多个指标 | |
25 | + */ | |
26 | + private Map<String, Object> datas; | |
27 | + /** | |
28 | + * datas存放的是遥测数据还是设备端属性 | |
29 | + */ | |
30 | + private Boolean telemetry; | |
31 | + /** | |
32 | + * 数据成功处理后的响应内容 | |
33 | + */ | |
34 | + private String ackMsg; | |
35 | + /** | |
36 | + * 设备名称、设备标识 | |
37 | + */ | |
38 | + private String deviceName; | |
39 | + /** | |
40 | + * 指标采集时间 | |
41 | + */ | |
42 | + private Long ts; | |
43 | + | |
44 | + public TcpUpEntry(UUID requestId) { | |
45 | + this.requestId = requestId; | |
46 | + } | |
47 | +} | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/AbstractNashornTkScriptInvokeService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/AbstractNashornTkScriptInvokeService.java
1 | -/** | |
2 | - * Copyright © 2016-2022 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.common.yunteng.script; | |
1 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 2 | |
18 | 3 | import com.google.common.util.concurrent.FutureCallback; |
19 | 4 | import com.google.common.util.concurrent.Futures; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/AbstractTkScriptInvokeService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/AbstractTkScriptInvokeService.java
... | ... | @@ -13,12 +13,13 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.Futures; |
19 | 19 | import com.google.common.util.concurrent.ListenableFuture; |
20 | 20 | import lombok.extern.slf4j.Slf4j; |
21 | 21 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
22 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
22 | 23 | |
23 | 24 | import java.util.Map; |
24 | 25 | import java.util.UUID; |
... | ... | @@ -54,10 +55,10 @@ public abstract class AbstractTkScriptInvokeService implements TkScriptInvokeSer |
54 | 55 | } |
55 | 56 | |
56 | 57 | @Override |
57 | - public ListenableFuture<UUID> eval(TkScriptType scriptType, String scriptBody, String... argNames) { | |
58 | - UUID scriptId = UUID.randomUUID(); | |
58 | + public ListenableFuture<UUID> eval(UUID id,TkScriptFunctionType scriptType, String scriptBody) { | |
59 | + UUID scriptId = id == null?UUID.randomUUID():id; | |
59 | 60 | String functionName = "invokeInternal_" + scriptId.toString().replace('-', '_'); |
60 | - String jsScript = generateJsScript(scriptType, functionName, scriptBody, argNames); | |
61 | + String jsScript = generateJsScript(scriptType, functionName, scriptBody); | |
61 | 62 | return doEval(scriptId, functionName, jsScript); |
62 | 63 | } |
63 | 64 | |
... | ... | @@ -109,10 +110,9 @@ public abstract class AbstractTkScriptInvokeService implements TkScriptInvokeSer |
109 | 110 | disableListInfo.incrementAndGet(); |
110 | 111 | } |
111 | 112 | |
112 | - private String generateJsScript(TkScriptType scriptType, String functionName, String scriptBody, String... argNames) { | |
113 | - if (scriptType == TkScriptType.TCP_TRANSPORT_SCRIPT) { | |
114 | - return TkScriptFactory.generateRuleNodeScript(functionName, scriptBody, argNames); | |
115 | - | |
113 | + private String generateJsScript(TkScriptFunctionType scriptType, String functionName, String scriptBody) { | |
114 | + if (TkScriptFunctionType.valueOf(scriptType.name()) != null) { | |
115 | + return TkScriptFactory.generateTcpScript(scriptType,functionName, scriptBody); | |
116 | 116 | } |
117 | 117 | throw new RuntimeException("No script factory implemented for scriptType: " + scriptType); |
118 | 118 | } | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/NashornTkScriptInvokeService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/NashornTkScriptInvokeService.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.springframework.beans.factory.annotation.Value; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/RemoteJsRequestEncoder.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/RemoteJsRequestEncoder.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.InvalidProtocolBufferException; |
19 | 19 | import com.google.protobuf.util.JsonFormat; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/RemoteJsResponseDecoder.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/RemoteJsResponseDecoder.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.protobuf.util.JsonFormat; |
19 | 19 | import org.thingsboard.server.gen.js.JsInvokeProtos; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkRemoteJsInvokeService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkRemoteJsInvokeService.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.FutureCallback; |
19 | 19 | import com.google.common.util.concurrent.Futures; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptExecutorService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptExecutorService.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import org.springframework.beans.factory.annotation.Value; |
19 | 19 | import org.springframework.stereotype.Component; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptFactory.java
0 → 100644
1 | +package org.thingsboard.server.transport.tcp.script; | |
2 | + | |
3 | +import org.apache.commons.lang3.StringUtils; | |
4 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
5 | + | |
6 | +public class TkScriptFactory { | |
7 | + | |
8 | + /** | |
9 | + * 脚本函数入参:数据配置 | |
10 | + */ | |
11 | + public static final String MSG = "params"; | |
12 | + /** | |
13 | + * 脚本函数入参:RPC功能名 | |
14 | + */ | |
15 | + public static final String METHODNAME = "thingsKit"; | |
16 | + public static final String SCRIPT_FUNCTION_NAME = "tcpTransportFunc"; | |
17 | + public static final String ORIGINAL_DATA_FILED = "source"; | |
18 | + public static final String INCLUD_ORIGINAL_DATA = "out." + ORIGINAL_DATA_FILED + "=params;"; | |
19 | + | |
20 | + private static final String JS_WRAPPER_PREFIX_TEMPLATE = "function %s(params) { " + | |
21 | + " var out = new Object(); " + | |
22 | + " return JSON.stringify(%s(params));" + | |
23 | + " function %s(%s) {"; | |
24 | + private static final String JS_DOWN_WRAPPER_PREFIX_TEMPLATE = "function %s(params) { " +//"function %s(method,params) { " | |
25 | + " var out = new Object(); " + | |
26 | + " return JSON.stringify(%s(params));" + //" return JSON.stringify(%s(method,params));" | |
27 | + " function %s(%s) {";//" function %s(%s,%s) {" | |
28 | + private static final String JS_UP_WRAPPER_PREFIX_TEMPLATE = "function %s(params) { " + | |
29 | + " var out = new Object(); " + | |
30 | + " return JSON.stringify(%s(params));" + | |
31 | + " function %s(%s) {"; | |
32 | + private static final String JS_WRAPPER_SUFFIX = "return out; \n }" + | |
33 | + "\n}"; | |
34 | + | |
35 | + | |
36 | + /** | |
37 | + * 构建完整的脚本函数 | |
38 | + * | |
39 | + * @param scriptType 脚本类型 | |
40 | + * @param functionName 脚本函数名 | |
41 | + * @param scriptBody 自定义的脚本函数体 | |
42 | + * @param argNames 脚本函数入参 | |
43 | + * @return | |
44 | + */ | |
45 | + public static String generateTcpScript(TkScriptFunctionType scriptType, String functionName, String scriptBody, String... argNames) { | |
46 | + String jsWrapperPrefix; | |
47 | + String msgArg = argNames.length >= 1 ? argNames[0] : MSG; | |
48 | +// String methodName = argNames.length >= 2 ? argNames[0] : METHODNAME; | |
49 | + switch (scriptType) { | |
50 | + case TRANSPORT_TCP_UP: | |
51 | + jsWrapperPrefix = String.format(JS_UP_WRAPPER_PREFIX_TEMPLATE | |
52 | + , functionName | |
53 | + , SCRIPT_FUNCTION_NAME | |
54 | + , SCRIPT_FUNCTION_NAME, msgArg); | |
55 | + break; | |
56 | + case TRANSPORT_TCP_DOWN: | |
57 | + jsWrapperPrefix = String.format(JS_DOWN_WRAPPER_PREFIX_TEMPLATE | |
58 | + , functionName | |
59 | + , SCRIPT_FUNCTION_NAME | |
60 | + , SCRIPT_FUNCTION_NAME, msgArg); | |
61 | + break; | |
62 | + default: | |
63 | + jsWrapperPrefix = String.format(JS_WRAPPER_PREFIX_TEMPLATE | |
64 | + , functionName | |
65 | + , SCRIPT_FUNCTION_NAME | |
66 | + , SCRIPT_FUNCTION_NAME, msgArg); | |
67 | + } | |
68 | + | |
69 | + | |
70 | + String result = jsWrapperPrefix + (StringUtils.isEmpty(scriptBody) ? INCLUD_ORIGINAL_DATA : scriptBody) + JS_WRAPPER_SUFFIX; | |
71 | + return result; | |
72 | + } | |
73 | + | |
74 | +} | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptInvokeRequest.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptInvokeRequest.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import java.util.List; |
19 | 19 | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptInvokeResponse.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptInvokeResponse.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import java.util.List; |
19 | 19 | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptInvokeService.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptInvokeService.java
... | ... | @@ -13,18 +13,37 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
19 | 20 | |
20 | 21 | import java.util.UUID; |
21 | 22 | |
22 | 23 | public interface TkScriptInvokeService { |
23 | 24 | |
24 | - ListenableFuture<UUID> eval(TkScriptType scriptType, String scriptBody, String... argNames); | |
25 | + /** | |
26 | + * 编译脚本函数 | |
27 | + * @param scriptId 脚本函数的唯一UUID,为空时随机生成 | |
28 | + * @param scriptType 脚本函数类型 | |
29 | + * @param scriptBody 脚本函数方法体 | |
30 | + * @return 返回脚本函数的UUID | |
31 | + */ | |
32 | + ListenableFuture<UUID> eval(UUID scriptId, TkScriptFunctionType scriptType, String scriptBody); | |
25 | 33 | |
34 | + /** | |
35 | + * 执行脚本函数 | |
36 | + * @param scriptId 脚本函数的唯一UUID | |
37 | + * @param args 脚本函数的实际参数 | |
38 | + * @return 脚本函数执行结果 | |
39 | + */ | |
26 | 40 | ListenableFuture<Object> invokeFunction(UUID scriptId, Object... args); |
27 | 41 | |
42 | + /** | |
43 | + * 释放缓存的脚本函数内容。临时测试脚本函数后需要释放缓存的相关内容 | |
44 | + * @param scriptId 脚本函数的唯一UUID | |
45 | + * @return | |
46 | + */ | |
28 | 47 | ListenableFuture<Void> release(UUID scriptId); |
29 | 48 | |
30 | 49 | } | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/script/TkScriptStatCallback.java
renamed from
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptStatCallback.java
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | -package org.thingsboard.server.common.yunteng.script; | |
16 | +package org.thingsboard.server.transport.tcp.script; | |
17 | 17 | |
18 | 18 | import com.google.common.util.concurrent.FutureCallback; |
19 | 19 | import lombok.AllArgsConstructor; | ... | ... |
common/transport/tcp/src/main/java/org/thingsboard/server/transport/tcp/session/TCPMessage.java
deleted
100644 → 0
1 | -package org.thingsboard.server.transport.tcp.session; | |
2 | - | |
3 | -import io.netty.handler.codec.mqtt.MqttMessageType; | |
4 | -import lombok.Data; | |
5 | - | |
6 | -import java.io.Serializable; | |
7 | - | |
8 | -@Data | |
9 | -public class TCPMessage implements Serializable { | |
10 | - | |
11 | - /**消息ID,用于请求与响应的匹配,例如:modbus由地址码和功能码组成。*/ | |
12 | - private String requestId; | |
13 | - | |
14 | - | |
15 | - private String message; | |
16 | - | |
17 | - /**数据主题,例如:modbus的功能码等。*/ | |
18 | - private String topic; | |
19 | - | |
20 | - /**设备地址码,例如:modbus的地址吗*/ | |
21 | - private String deviceCode; | |
22 | - | |
23 | - | |
24 | - | |
25 | - public TCPMessage(String message){ | |
26 | - this.message = message; | |
27 | - } | |
28 | - | |
29 | -} |
... | ... | @@ -21,6 +21,7 @@ import lombok.Getter; |
21 | 21 | import lombok.Setter; |
22 | 22 | import lombok.extern.slf4j.Slf4j; |
23 | 23 | import org.thingsboard.server.transport.tcp.TcpTransportContext; |
24 | +import org.thingsboard.server.transport.tcp.adaptors.TcpUpEntry; | |
24 | 25 | |
25 | 26 | import java.util.UUID; |
26 | 27 | import java.util.concurrent.ConcurrentLinkedQueue; |
... | ... | @@ -42,7 +43,7 @@ public class TcpDeviceSessionCtx extends TcpDeviceWareSessionContext { |
42 | 43 | |
43 | 44 | private final AtomicInteger msgIdSeq = new AtomicInteger(0); |
44 | 45 | |
45 | - private final ConcurrentLinkedQueue<TCPMessage> msgQueue = new ConcurrentLinkedQueue<>(); | |
46 | + private final ConcurrentLinkedQueue<String> msgQueue = new ConcurrentLinkedQueue<>(); | |
46 | 47 | |
47 | 48 | @Getter |
48 | 49 | private final Lock msgQueueProcessorLock = new ReentrantLock(); |
... | ... | @@ -73,17 +74,17 @@ public class TcpDeviceSessionCtx extends TcpDeviceWareSessionContext { |
73 | 74 | |
74 | 75 | |
75 | 76 | |
76 | - public void addToQueue(TCPMessage msg) { | |
77 | + public void addToQueue(String msg) { | |
77 | 78 | msgQueueSize.incrementAndGet(); |
78 | 79 | ReferenceCountUtil.retain(msg); |
79 | 80 | msgQueue.add(msg); |
80 | 81 | } |
81 | 82 | |
82 | - public void tryProcessQueuedMsgs(Consumer<TCPMessage> msgProcessor) { | |
83 | + public void tryProcessQueuedMsgs(Consumer<String> msgProcessor) { | |
83 | 84 | while (!msgQueue.isEmpty()) { |
84 | 85 | if (msgQueueProcessorLock.tryLock()) { |
85 | 86 | try { |
86 | - TCPMessage msg; | |
87 | + String msg; | |
87 | 88 | while ((msg = msgQueue.poll()) != null) { |
88 | 89 | try { |
89 | 90 | msgQueueSize.decrementAndGet(); | ... | ... |
1 | -/** | |
2 | - * Copyright © 2016-2022 The Thingsboard Authors | |
3 | - * <p> | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * <p> | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * <p> | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | 1 | package org.thingsboard.server.transport.tcp.session; |
17 | 2 | |
18 | -import com.fasterxml.jackson.core.JsonProcessingException; | |
19 | -import com.fasterxml.jackson.databind.JsonNode; | |
3 | +import com.google.common.util.concurrent.FutureCallback; | |
4 | +import com.google.common.util.concurrent.Futures; | |
5 | +import com.google.common.util.concurrent.ListenableFuture; | |
6 | +import com.google.common.util.concurrent.MoreExecutors; | |
20 | 7 | import lombok.Getter; |
21 | 8 | import lombok.extern.slf4j.Slf4j; |
9 | +import org.jetbrains.annotations.Nullable; | |
10 | +import org.thingsboard.common.util.JacksonUtil; | |
22 | 11 | import org.thingsboard.server.common.data.DeviceProfile; |
23 | 12 | import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
24 | 13 | import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration; |
25 | -import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
26 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
14 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
27 | 15 | import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; |
28 | 16 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; |
29 | -import org.thingsboard.server.common.yunteng.script.TkScriptFactory; | |
30 | 17 | import org.thingsboard.server.gen.transport.TransportProtos; |
31 | 18 | import org.thingsboard.server.transport.tcp.TcpTransportContext; |
32 | 19 | import org.thingsboard.server.transport.tcp.adaptors.TcpTransportAdaptor; |
20 | +import org.thingsboard.server.transport.tcp.adaptors.TcpUpEntry; | |
33 | 21 | |
34 | 22 | import java.util.UUID; |
35 | -import java.util.concurrent.ExecutionException; | |
23 | +import java.util.function.Consumer; | |
36 | 24 | |
37 | 25 | /** |
38 | 26 | * @author Andrew Shvayka |
... | ... | @@ -42,22 +30,19 @@ public abstract class TcpDeviceWareSessionContext extends DeviceAwareSessionCont |
42 | 30 | |
43 | 31 | @Getter |
44 | 32 | private final TcpTransportContext context; |
45 | - | |
46 | - private volatile String telemetryTopicFilter ; | |
47 | - private volatile String attributesTopicFilter; | |
48 | - private volatile String toDeviceRpcResponseTopicFilter; | |
49 | 33 | @Getter |
50 | - private volatile TcpDataTypeEnum payloadType = TcpDataTypeEnum.HEX; | |
51 | - | |
52 | - private volatile TcpTransportAdaptor adaptor; | |
53 | - | |
54 | - /**设备唯一标识符,例如:设备SN、设备地址码等。数据内携带标识符*/ | |
34 | + private volatile UUID authScriptId; | |
55 | 35 | @Getter |
56 | - private volatile String deviceCode = "55"; | |
57 | - | |
36 | + private volatile UUID telemetryScriptId; | |
37 | + @Getter | |
38 | + private volatile UUID rpcScriptId; | |
58 | 39 | |
40 | + /** | |
41 | + * 设备唯一标识符,例如:设备SN、设备地址码等。数据内携带标识符 | |
42 | + */ | |
59 | 43 | @Getter |
60 | - private UUID scriptId; | |
44 | + private volatile String deviceName; | |
45 | + private volatile TcpTransportAdaptor adaptor; | |
61 | 46 | |
62 | 47 | public TcpDeviceWareSessionContext(UUID sessionId, TcpTransportContext context) { |
63 | 48 | super(sessionId); |
... | ... | @@ -66,17 +51,6 @@ public abstract class TcpDeviceWareSessionContext extends DeviceAwareSessionCont |
66 | 51 | } |
67 | 52 | |
68 | 53 | |
69 | - public boolean isDeviceTelemetryTopic(String topicName) { | |
70 | - return telemetryTopicFilter.equals(topicName); | |
71 | - } | |
72 | - | |
73 | - public boolean isDeviceAttributesTopic(String topicName) { | |
74 | - return attributesTopicFilter.equals(topicName); | |
75 | - } | |
76 | - public boolean isToDeviceRpcResponseTopic(String topicName) { | |
77 | - return toDeviceRpcResponseTopicFilter.equals(topicName); | |
78 | - } | |
79 | - | |
80 | 54 | public TcpTransportAdaptor getPayloadAdaptor() { |
81 | 55 | return this.adaptor; |
82 | 56 | } |
... | ... | @@ -85,15 +59,7 @@ public abstract class TcpDeviceWareSessionContext extends DeviceAwareSessionCont |
85 | 59 | @Override |
86 | 60 | public void setDeviceInfo(TransportDeviceInfo deviceInfo) { |
87 | 61 | super.setDeviceInfo(deviceInfo); |
88 | - try { | |
89 | - JsonNode additionalInfo = context.getMapper().readTree(deviceInfo.getAdditionalInfo()); | |
90 | - if(additionalInfo !=null && additionalInfo.has(FastIotConstants.TCP_DEVICE_IDENTIFY_FILED)){ | |
91 | - deviceCode = additionalInfo.get(FastIotConstants.TCP_DEVICE_IDENTIFY_FILED).asText(); | |
92 | - } | |
93 | - } catch (JsonProcessingException e) { | |
94 | - log.trace("[{}][{}] Failed to fetch device additional info", sessionId, deviceInfo.getDeviceName(), e); | |
95 | - } | |
96 | - | |
62 | + deviceName = deviceInfo.getDeviceName(); | |
97 | 63 | } |
98 | 64 | |
99 | 65 | @Override |
... | ... | @@ -108,28 +74,71 @@ public abstract class TcpDeviceWareSessionContext extends DeviceAwareSessionCont |
108 | 74 | updateDeviceSessionConfiguration(deviceProfile); |
109 | 75 | } |
110 | 76 | |
111 | - private void updateDeviceSessionConfiguration(DeviceProfile deviceProfile){ | |
77 | + private void updateDeviceSessionConfiguration(DeviceProfile deviceProfile) { | |
112 | 78 | DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration(); |
113 | 79 | |
114 | 80 | TkTcpDeviceProfileTransportConfiguration tcpConfiguration = (TkTcpDeviceProfileTransportConfiguration) transportConfiguration; |
115 | - payloadType = tcpConfiguration.getDataFormat(); | |
116 | - if (TcpDataTypeEnum.ASCII.equals(payloadType)) { | |
117 | - payloadType = TcpDataTypeEnum.ASCII; | |
118 | - } else { | |
119 | - payloadType = TcpDataTypeEnum.HEX; | |
120 | - } | |
121 | - this.attributesTopicFilter = tcpConfiguration.getAttributesTopic(); | |
122 | - this.telemetryTopicFilter = tcpConfiguration.getTelemetryTopic(); | |
123 | - this.toDeviceRpcResponseTopicFilter = tcpConfiguration.getRpcTopic(); | |
124 | - String scriptBody = tcpConfiguration.getScriptText(); | |
125 | - try { | |
126 | - this.scriptId = this.adaptor.getJsScriptEngineFunctionId(scriptBody==null? TkScriptFactory.INCLUD_ORIGINAL_DATA:scriptBody); | |
127 | - } catch (ExecutionException e) { | |
128 | - log.warn("设备配置【{}】的脚本【{}】解析异常",deviceProfile.getSearchText(),scriptBody); | |
129 | - throw new RuntimeException(e); | |
130 | - } catch (InterruptedException e) { | |
131 | - throw new RuntimeException(e); | |
81 | + this.authScriptId = UUID.fromString(tcpConfiguration.getAuthScriptId()); | |
82 | + | |
83 | + this.telemetryScriptId = UUID.fromString(tcpConfiguration.getUpScriptId()); | |
84 | + TransportProtos.ScriptProto upScript = context.getTransportService().getScripts(TransportProtos.ScriptProto.newBuilder().setScriptIdLSB(telemetryScriptId.getLeastSignificantBits()).setScriptIdMSB(telemetryScriptId.getMostSignificantBits()).build()).get(0); | |
85 | + cacheScript(telemetryScriptId, TkScriptFunctionType.TRANSPORT_TCP_UP, upScript.getConvertJs(), null); | |
86 | + | |
87 | + this.rpcScriptId = UUID.fromString(tcpConfiguration.getDownScriptId()); | |
88 | + TransportProtos.ScriptProto downScript = context.getTransportService().getScripts(TransportProtos.ScriptProto.newBuilder().setScriptIdLSB(rpcScriptId.getLeastSignificantBits()).setScriptIdMSB(rpcScriptId.getMostSignificantBits()).build()).get(0); | |
89 | + cacheScript(rpcScriptId, TkScriptFunctionType.TRANSPORT_TCP_DOWN, downScript.getConvertJs(), null); | |
90 | + } | |
91 | + | |
92 | + /** | |
93 | + * 编译并缓存脚本引擎 | |
94 | + * | |
95 | + * @param scriptId 脚本引擎ID | |
96 | + * @param scriptType 脚本类型 | |
97 | + * @param convertStr 脚本内容 | |
98 | + * @param callback 脚本引擎执行成功的回调函数 | |
99 | + */ | |
100 | + public void cacheScript(UUID scriptId, TkScriptFunctionType scriptType, String convertStr, FutureCallback callback) { | |
101 | + ListenableFuture<UUID> result = context.getJsEngine().eval(scriptId, scriptType, convertStr); | |
102 | + if (callback == null) { | |
103 | + callback = new FutureCallback() { | |
104 | + @Override | |
105 | + public void onSuccess(@Nullable Object result) { | |
106 | + | |
107 | + } | |
108 | + | |
109 | + @Override | |
110 | + public void onFailure(Throwable t) { | |
111 | + log.error(String.format("脚本【%s】解析时出现异常:【%s】", convertStr, t)); | |
112 | + } | |
113 | + }; | |
132 | 114 | } |
115 | + Futures.addCallback(result, callback, MoreExecutors.directExecutor()); | |
116 | + } | |
117 | + | |
118 | + /** | |
119 | + * 执行上行数据的解析脚本 | |
120 | + * | |
121 | + * @param scriptParam 脚本函数入参 | |
122 | + * @param onSuccess 脚本执行成功后的业务逻辑 | |
123 | + */ | |
124 | + public void doUpScript(String scriptParam, Consumer<TcpUpEntry> onSuccess) { | |
125 | + ListenableFuture future = context.getJsEngine().invokeFunction(this.telemetryScriptId, scriptParam); | |
126 | + Futures.addCallback(future, new FutureCallback<String>() { | |
127 | + | |
128 | + @Override | |
129 | + public void onSuccess(@org.checkerframework.checker.nullness.qual.Nullable String str) { | |
130 | + TcpUpEntry result = JacksonUtil.fromString(str, TcpUpEntry.class); | |
131 | + if (result == null) { | |
132 | + return; | |
133 | + } | |
134 | + onSuccess.accept(result); | |
135 | + } | |
136 | + | |
137 | + @Override | |
138 | + public void onFailure(Throwable t) { | |
139 | + log.error(t.getMessage()); | |
140 | + } | |
141 | + }, MoreExecutors.directExecutor()); | |
133 | 142 | } |
134 | 143 | |
135 | 144 | } | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
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 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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. |
... | ... | @@ -25,7 +25,6 @@ import org.thingsboard.server.common.transport.SessionMsgListener; |
25 | 25 | import org.thingsboard.server.common.transport.TransportService; |
26 | 26 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
27 | 27 | import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; |
28 | -import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; | |
29 | 28 | import org.thingsboard.server.gen.transport.TransportProtos; |
30 | 29 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
31 | 30 | import org.thingsboard.server.transport.tcp.TcpTransportContext; |
... | ... | @@ -43,7 +42,7 @@ public class TcpGatewayDeviceSessionCtx extends TcpDeviceWareSessionContext impl |
43 | 42 | |
44 | 43 | public TcpGatewayDeviceSessionCtx(TcpTransportContext context, TcpGatewaySessionHandler parent, TransportDeviceInfo deviceInfo, |
45 | 44 | DeviceProfile deviceProfile, TransportService transportService) { |
46 | - super(UUID.randomUUID(),context); | |
45 | + super(UUID.randomUUID(), context); | |
47 | 46 | this.parent = parent; |
48 | 47 | setSessionInfo(SessionInfoProto.newBuilder() |
49 | 48 | .setNodeId(parent.getNodeId()) |
... | ... | @@ -80,30 +79,21 @@ public class TcpGatewayDeviceSessionCtx extends TcpDeviceWareSessionContext impl |
80 | 79 | |
81 | 80 | @Override |
82 | 81 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg response) { |
83 | - try { | |
84 | - parent.getPayloadAdaptor().convertToGatewayPublish(this, getDeviceInfo().getDeviceName(), response).ifPresent(parent::pushDeviceMsg); | |
85 | - } catch (Exception e) { | |
86 | - log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e); | |
87 | - } | |
82 | + log.trace("[{}] convert device attributes response to TCP msg", sessionId, response); | |
88 | 83 | } |
89 | 84 | |
90 | 85 | @Override |
91 | 86 | public void onAttributeUpdate(UUID sessionId, TransportProtos.AttributeUpdateNotificationMsg notification) { |
92 | 87 | log.trace("[{}] Received attributes update notification to device", sessionId); |
93 | - try { | |
94 | - parent.getPayloadAdaptor().convertToGatewayPublish(this, getDeviceInfo().getDeviceName(), notification).ifPresent(parent::pushDeviceMsg); | |
95 | - } catch (Exception e) { | |
96 | - log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e); | |
97 | - } | |
98 | 88 | } |
99 | 89 | |
100 | 90 | @Override |
101 | 91 | public void onToDeviceRpcRequest(UUID sessionId, TransportProtos.ToDeviceRpcRequestMsg request) { |
102 | - log.error("【{}】下发RPC命令【{}】给网关子设备", sessionId,request.getParams()); | |
92 | + log.error("【{}】下发RPC命令【{}】给网关子设备", sessionId, request.getParams()); | |
103 | 93 | try { |
104 | 94 | parent.getPayloadAdaptor().convertToPublish(this, request).ifPresent( |
105 | 95 | payload -> { |
106 | - ChannelFuture channelFuture = parent.pushDeviceMsg(payload); | |
96 | + ChannelFuture channelFuture = parent.pushDeviceMsg(payload.getDatas()); | |
107 | 97 | if (request.getPersisted()) { |
108 | 98 | channelFuture.addListener(result -> { |
109 | 99 | if (result.cause() == null) { | ... | ... |
1 | 1 | /** |
2 | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | - * | |
3 | + * <p> | |
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 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
7 | + * <p> | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * <p> | |
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. |
... | ... | @@ -20,28 +20,23 @@ import com.google.common.util.concurrent.FutureCallback; |
20 | 20 | import com.google.common.util.concurrent.Futures; |
21 | 21 | import com.google.common.util.concurrent.ListenableFuture; |
22 | 22 | import com.google.common.util.concurrent.SettableFuture; |
23 | -import com.google.gson.*; | |
24 | -import com.google.protobuf.InvalidProtocolBufferException; | |
25 | -import com.google.protobuf.ProtocolStringList; | |
23 | +import com.google.gson.JsonElement; | |
24 | +import com.google.gson.JsonObject; | |
25 | +import com.google.gson.JsonSyntaxException; | |
26 | 26 | import io.netty.buffer.ByteBuf; |
27 | 27 | import io.netty.buffer.Unpooled; |
28 | 28 | import io.netty.channel.ChannelFuture; |
29 | 29 | import io.netty.channel.ChannelHandlerContext; |
30 | 30 | import io.netty.handler.codec.mqtt.MqttPublishMessage; |
31 | 31 | import lombok.extern.slf4j.Slf4j; |
32 | -import org.springframework.util.CollectionUtils; | |
33 | 32 | import org.springframework.util.ConcurrentReferenceHashMap; |
34 | 33 | import org.springframework.util.StringUtils; |
35 | -import org.thingsboard.server.common.data.id.DeviceId; | |
36 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
34 | +import org.thingsboard.common.util.JacksonUtil; | |
37 | 35 | import org.thingsboard.server.common.transport.TransportService; |
38 | 36 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
39 | 37 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
40 | -import org.thingsboard.server.common.transport.adaptor.JsonConverter; | |
41 | -import org.thingsboard.server.common.transport.adaptor.ProtoConverter; | |
42 | 38 | import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; |
43 | 39 | import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; |
44 | -import org.thingsboard.server.gen.transport.TransportApiProtos; | |
45 | 40 | import org.thingsboard.server.gen.transport.TransportProtos; |
46 | 41 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; |
47 | 42 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
... | ... | @@ -51,7 +46,7 @@ import org.thingsboard.server.transport.tcp.util.ByteUtils; |
51 | 46 | |
52 | 47 | import javax.annotation.Nullable; |
53 | 48 | import java.io.UnsupportedEncodingException; |
54 | -import java.util.*; | |
49 | +import java.util.UUID; | |
55 | 50 | import java.util.concurrent.ConcurrentHashMap; |
56 | 51 | import java.util.concurrent.ConcurrentMap; |
57 | 52 | import java.util.concurrent.locks.Lock; |
... | ... | @@ -97,37 +92,29 @@ public class TcpGatewaySessionHandler { |
97 | 92 | } |
98 | 93 | |
99 | 94 | |
100 | - | |
101 | - | |
102 | - | |
103 | - public void onDeviceTelemetry(TCPMessage tcpMessage) throws AdaptorException { | |
104 | - Futures.addCallback(checkDeviceConnected(tcpMessage.getDeviceCode()), | |
95 | + public void onDeviceTelemetry(String deviceName, UUID requestId, String deviceDataStr) { | |
96 | + Futures.addCallback(checkDeviceConnected(deviceName), | |
105 | 97 | new FutureCallback<>() { |
106 | 98 | @Override |
107 | 99 | public void onSuccess(@Nullable TcpGatewayDeviceSessionCtx deviceCtx) { |
108 | - String deviceName = deviceCtx.getDeviceInfo().getDeviceName(); | |
109 | - try { | |
110 | - TransportProtos.PostTelemetryMsg postTelemetryMsg = deviceCtx.getPayloadAdaptor().convertToPostTelemetry(deviceCtx,tcpMessage.getMessage()); | |
111 | - processPostTelemetryMsg(deviceCtx, postTelemetryMsg, deviceName, tcpMessage.getRequestId()); | |
112 | - } catch (Throwable e) { | |
113 | - log.warn("[{}][{}] Failed to convert telemetry: {}", gateway.getDeviceId(), deviceName, tcpMessage.getMessage(), e); | |
114 | - channel.close(); | |
115 | - } | |
100 | + deviceCtx.doUpScript(deviceDataStr, r -> { | |
101 | + try { | |
102 | + TransportProtos.PostTelemetryMsg postTelemetryMsg = deviceCtx.getPayloadAdaptor().convertToPostTelemetry(deviceCtx, JacksonUtil.toString(r.getDatas())); | |
103 | + processPostTelemetryMsg(deviceCtx, postTelemetryMsg, deviceName, requestId); | |
104 | + } catch (AdaptorException e) { | |
105 | + log.warn("[{}][{}] Failed to convert telemetry: {}", gateway.getDeviceId(), deviceName, deviceDataStr, e); | |
106 | + } | |
107 | + }); | |
116 | 108 | } |
117 | 109 | |
118 | 110 | @Override |
119 | 111 | public void onFailure(Throwable t) { |
120 | - log.debug("[{}] Failed to process device telemetry command: {}", sessionId, tcpMessage.getDeviceCode(), t); | |
112 | + log.debug("[{}] Failed to process device telemetry command: {}", sessionId, deviceName, t); | |
121 | 113 | } |
122 | 114 | }, context.getExecutor()); |
123 | 115 | } |
124 | 116 | |
125 | 117 | |
126 | - | |
127 | - | |
128 | - | |
129 | - | |
130 | - | |
131 | 118 | public void onGatewayDisconnect() { |
132 | 119 | devices.forEach(this::deregisterSession); |
133 | 120 | } |
... | ... | @@ -158,7 +145,6 @@ public class TcpGatewaySessionHandler { |
158 | 145 | } |
159 | 146 | |
160 | 147 | |
161 | - | |
162 | 148 | int nextMsgId() { |
163 | 149 | return deviceSessionCtx.nextMsgId(); |
164 | 150 | } |
... | ... | @@ -210,64 +196,49 @@ public class TcpGatewaySessionHandler { |
210 | 196 | if (future != null) { |
211 | 197 | return future; |
212 | 198 | } |
213 | - try { | |
214 | - transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder() | |
215 | - .setDeviceName(deviceName) | |
216 | - .setDeviceType(deviceType) | |
217 | - .setGatewayIdMSB(gateway.getDeviceId().getId().getMostSignificantBits()) | |
218 | - .setGatewayIdLSB(gateway.getDeviceId().getId().getLeastSignificantBits()).build(), | |
219 | - new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse>() { | |
220 | - @Override | |
221 | - public void onSuccess(GetOrCreateDeviceFromGatewayResponse msg) { | |
222 | - TcpGatewayDeviceSessionCtx deviceSessionCtx = new TcpGatewayDeviceSessionCtx(context,TcpGatewaySessionHandler.this, msg.getDeviceInfo(), msg.getDeviceProfile(), transportService); | |
223 | - if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { | |
224 | - log.trace("[{}] First got or created device [{}], type [{}] for the gateway session", sessionId, deviceName, deviceType); | |
225 | - SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); | |
226 | - transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx); | |
227 | - transportService.process(TransportProtos.TransportToDeviceActorMsg.newBuilder() | |
228 | - .setSessionInfo(deviceSessionInfo) | |
229 | - .setSessionEvent(SESSION_EVENT_MSG_OPEN) | |
230 | - .setSubscribeToAttributes(SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG) | |
231 | - .setSubscribeToRPC(SUBSCRIBE_TO_RPC_ASYNC_MSG) | |
232 | - .build(), null); | |
233 | - } | |
234 | - futureToSet.set(devices.get(deviceName)); | |
235 | - deviceFutures.remove(deviceName); | |
199 | + try { | |
200 | + transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder() | |
201 | + .setDeviceName(deviceName) | |
202 | + .setDeviceType(deviceType) | |
203 | + .setGatewayIdMSB(gateway.getDeviceId().getId().getMostSignificantBits()) | |
204 | + .setGatewayIdLSB(gateway.getDeviceId().getId().getLeastSignificantBits()).build(), | |
205 | + new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse>() { | |
206 | + @Override | |
207 | + public void onSuccess(GetOrCreateDeviceFromGatewayResponse msg) { | |
208 | + TcpGatewayDeviceSessionCtx deviceSessionCtx = new TcpGatewayDeviceSessionCtx(context, TcpGatewaySessionHandler.this, msg.getDeviceInfo(), msg.getDeviceProfile(), transportService); | |
209 | + if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { | |
210 | + log.trace("[{}] First got or created device [{}], type [{}] for the gateway session", sessionId, deviceName, deviceType); | |
211 | + SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); | |
212 | + transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx); | |
213 | + transportService.process(TransportProtos.TransportToDeviceActorMsg.newBuilder() | |
214 | + .setSessionInfo(deviceSessionInfo) | |
215 | + .setSessionEvent(SESSION_EVENT_MSG_OPEN) | |
216 | + .setSubscribeToAttributes(SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG) | |
217 | + .setSubscribeToRPC(SUBSCRIBE_TO_RPC_ASYNC_MSG) | |
218 | + .build(), null); | |
236 | 219 | } |
220 | + futureToSet.set(devices.get(deviceName)); | |
221 | + deviceFutures.remove(deviceName); | |
222 | + } | |
237 | 223 | |
238 | - @Override | |
239 | - public void onError(Throwable e) { | |
240 | - log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e); | |
241 | - futureToSet.setException(e); | |
242 | - deviceFutures.remove(deviceName); | |
243 | - } | |
244 | - }); | |
245 | - return futureToSet; | |
246 | - } catch (Throwable e) { | |
247 | - deviceFutures.remove(deviceName); | |
248 | - throw e; | |
249 | - } | |
224 | + @Override | |
225 | + public void onError(Throwable e) { | |
226 | + log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e); | |
227 | + futureToSet.setException(e); | |
228 | + deviceFutures.remove(deviceName); | |
229 | + } | |
230 | + }); | |
231 | + return futureToSet; | |
232 | + } catch (Throwable e) { | |
233 | + deviceFutures.remove(deviceName); | |
234 | + throw e; | |
235 | + } | |
250 | 236 | } |
251 | 237 | |
252 | 238 | private int getMsgId(MqttPublishMessage mqttMsg) { |
253 | 239 | return mqttMsg.variableHeader().packetId(); |
254 | 240 | } |
255 | 241 | |
256 | - public void onDeviceConnect(MqttPublishMessage mqttMsg) throws AdaptorException { | |
257 | - JsonElement json = getJson(mqttMsg); | |
258 | - String deviceName = checkDeviceName(getDeviceName(json)); | |
259 | - String deviceType = getDeviceType(json); | |
260 | - processOnConnect(mqttMsg, deviceName, deviceType); | |
261 | - } | |
262 | - | |
263 | - | |
264 | - | |
265 | - public void onDeviceDisconnect(MqttPublishMessage mqttMsg) throws AdaptorException { | |
266 | - String deviceName = checkDeviceName(getDeviceName(getJson(mqttMsg))); | |
267 | - processOnDisconnect(mqttMsg, deviceName); | |
268 | - } | |
269 | - | |
270 | - | |
271 | 242 | |
272 | 243 | private void processOnDisconnect(MqttPublishMessage msg, String deviceName) { |
273 | 244 | deregisterSession(deviceName); |
... | ... | @@ -275,113 +246,40 @@ public class TcpGatewaySessionHandler { |
275 | 246 | } |
276 | 247 | |
277 | 248 | |
278 | - | |
279 | - | |
280 | - private void processPostTelemetryMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.PostTelemetryMsg postTelemetryMsg, String deviceName, String msgId) { | |
249 | + private void processPostTelemetryMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.PostTelemetryMsg postTelemetryMsg, String deviceName, UUID msgId) { | |
281 | 250 | transportService.process(deviceCtx.getSessionInfo(), postTelemetryMsg, getPubAckCallback(channel, deviceName, msgId, postTelemetryMsg)); |
282 | 251 | } |
283 | - public void onDeviceClaim(MqttPublishMessage mqttMsg) throws AdaptorException { | |
284 | - int msgId = getMsgId(mqttMsg); | |
285 | - ByteBuf payload = mqttMsg.payload(); | |
286 | - JsonElement json = null;//JsonMqttAdaptor.validateJsonPayload(sessionId, payload); | |
287 | - if (json.isJsonObject()) { | |
288 | - JsonObject jsonObj = json.getAsJsonObject(); | |
289 | - for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) { | |
290 | - String deviceName = deviceEntry.getKey(); | |
291 | - Futures.addCallback(checkDeviceConnected(deviceName), | |
292 | - new FutureCallback<TcpGatewayDeviceSessionCtx>() { | |
293 | - @Override | |
294 | - public void onSuccess(@Nullable TcpGatewayDeviceSessionCtx deviceCtx) { | |
295 | - if (!deviceEntry.getValue().isJsonObject()) { | |
296 | - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); | |
297 | - } | |
298 | - try { | |
299 | - DeviceId deviceId = deviceCtx.getDeviceId(); | |
300 | - TransportProtos.ClaimDeviceMsg claimDeviceMsg = JsonConverter.convertToClaimDeviceProto(deviceId, deviceEntry.getValue()); | |
301 | - processClaimDeviceMsg(deviceCtx, claimDeviceMsg, deviceName, msgId); | |
302 | - } catch (Throwable e) { | |
303 | - log.warn("[{}][{}] Failed to convert claim message: {}", gateway.getDeviceId(), deviceName, deviceEntry.getValue(), e); | |
304 | - } | |
305 | - } | |
306 | - | |
307 | - @Override | |
308 | - public void onFailure(Throwable t) { | |
309 | - log.debug("[{}] Failed to process device claiming command: {}", sessionId, deviceName, t); | |
310 | - } | |
311 | - }, context.getExecutor()); | |
312 | - } | |
313 | - } else { | |
314 | - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); | |
315 | - } | |
316 | - } | |
317 | - | |
318 | - | |
319 | - private void processClaimDeviceMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.ClaimDeviceMsg claimDeviceMsg, String deviceName, int msgId) { | |
320 | - transportService.process(deviceCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(channel, deviceName, msgId+"", claimDeviceMsg)); | |
321 | - } | |
322 | 252 | |
323 | - public void onDeviceAttributes(TCPMessage mqttMsg) throws AdaptorException { | |
324 | - int msgId = 0;//getMsgId(mqttMsg); | |
325 | - ByteBuf payload = null;//mqttMsg.payload(); | |
326 | - JsonElement json = null;//JsonMqttAdaptor.validateJsonPayload(sessionId, payload); | |
327 | - if (json.isJsonObject()) { | |
328 | - JsonObject jsonObj = json.getAsJsonObject(); | |
329 | - for (Map.Entry<String, JsonElement> deviceEntry : jsonObj.entrySet()) { | |
330 | - String deviceName = deviceEntry.getKey(); | |
331 | - Futures.addCallback(checkDeviceConnected(deviceName), | |
332 | - new FutureCallback<TcpGatewayDeviceSessionCtx>() { | |
333 | - @Override | |
334 | - public void onSuccess(@Nullable TcpGatewayDeviceSessionCtx deviceCtx) { | |
335 | - if (!deviceEntry.getValue().isJsonObject()) { | |
336 | - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); | |
337 | - } | |
338 | - TransportProtos.PostAttributeMsg postAttributeMsg = JsonConverter.convertToAttributesProto(deviceEntry.getValue().getAsJsonObject()); | |
339 | - processPostAttributesMsg(deviceCtx, postAttributeMsg, deviceName, msgId); | |
253 | + public void onDeviceAttributes(String deviceName, UUID requestId, String deviceDataStr) { | |
254 | + Futures.addCallback(checkDeviceConnected(deviceName), | |
255 | + new FutureCallback<TcpGatewayDeviceSessionCtx>() { | |
256 | + @Override | |
257 | + public void onSuccess(@Nullable TcpGatewayDeviceSessionCtx deviceCtx) { | |
258 | + deviceCtx.doUpScript(deviceDataStr, r -> { | |
259 | + try { | |
260 | + TransportProtos.PostAttributeMsg postAttributeMsg = deviceCtx.getPayloadAdaptor().convertToPostAttributes(deviceCtx, JacksonUtil.toString(r.getDatas())); | |
261 | + processPostAttributesMsg(deviceCtx, postAttributeMsg, deviceName, requestId); | |
262 | + } catch (AdaptorException e) { | |
263 | + log.warn("[{}][{}] Failed to convert telemetry: {}", gateway.getDeviceId(), deviceName, deviceDataStr, e); | |
340 | 264 | } |
265 | + }); | |
266 | + } | |
341 | 267 | |
342 | - @Override | |
343 | - public void onFailure(Throwable t) { | |
344 | - log.debug("[{}] Failed to process device attributes command: {}", sessionId, deviceName, t); | |
345 | - } | |
346 | - }, context.getExecutor()); | |
347 | - } | |
348 | - } else { | |
349 | - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); | |
350 | - } | |
268 | + @Override | |
269 | + public void onFailure(Throwable t) { | |
270 | + log.debug("[{}] Failed to process device attributes command: {}", sessionId, deviceName, t); | |
271 | + } | |
272 | + }, context.getExecutor()); | |
351 | 273 | } |
352 | 274 | |
353 | 275 | |
354 | - private void processPostAttributesMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.PostAttributeMsg postAttributeMsg, String deviceName, int msgId) { | |
355 | - transportService.process(deviceCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(channel, deviceName, msgId+"", postAttributeMsg)); | |
356 | - } | |
357 | - | |
358 | - public void onDeviceAttributesRequest(MqttPublishMessage mqttMsg) throws AdaptorException { | |
359 | - JsonElement json = null;//JsonMqttAdaptor.validateJsonPayload(sessionId, msg.payload()); | |
360 | - if (json.isJsonObject()) { | |
361 | - JsonObject jsonObj = json.getAsJsonObject(); | |
362 | - int requestId = jsonObj.get("id").getAsInt(); | |
363 | - String deviceName = jsonObj.get(DEVICE_PROPERTY).getAsString(); | |
364 | - boolean clientScope = jsonObj.get("client").getAsBoolean(); | |
365 | - Set<String> keys; | |
366 | - if (jsonObj.has("key")) { | |
367 | - keys = Collections.singleton(jsonObj.get("key").getAsString()); | |
368 | - } else { | |
369 | - JsonArray keysArray = jsonObj.get("keys").getAsJsonArray(); | |
370 | - keys = new HashSet<>(); | |
371 | - for (JsonElement keyObj : keysArray) { | |
372 | - keys.add(keyObj.getAsString()); | |
373 | - } | |
374 | - } | |
375 | - TransportProtos.GetAttributeRequestMsg requestMsg = toGetAttributeRequestMsg(requestId, clientScope, keys); | |
376 | - processGetAttributeRequestMessage(mqttMsg, deviceName, requestMsg); | |
377 | - } else { | |
378 | - throw new JsonSyntaxException(CAN_T_PARSE_VALUE + json); | |
379 | - } | |
276 | + private void processPostAttributesMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.PostAttributeMsg postAttributeMsg, String deviceName, UUID msgId) { | |
277 | + transportService.process(deviceCtx.getSessionInfo(), postAttributeMsg, getPubAckCallback(channel, deviceName, msgId, postAttributeMsg)); | |
380 | 278 | } |
381 | 279 | |
382 | 280 | |
383 | 281 | public void onDeviceRpcResponse(MqttPublishMessage mqttMsg) throws AdaptorException { |
384 | - int msgId = getMsgId(mqttMsg); | |
282 | + UUID msgId = null; | |
385 | 283 | ByteBuf payload = mqttMsg.payload(); |
386 | 284 | JsonElement json = null;// JsonMqttAdaptor.validateJsonPayload(sessionId, payload); |
387 | 285 | if (json.isJsonObject()) { |
... | ... | @@ -409,38 +307,10 @@ public class TcpGatewaySessionHandler { |
409 | 307 | } |
410 | 308 | |
411 | 309 | |
412 | - private void processRpcResponseMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg, String deviceName, int msgId) { | |
413 | - transportService.process(deviceCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(channel, deviceName, msgId+"", rpcResponseMsg)); | |
414 | - } | |
415 | - | |
416 | - private void processGetAttributeRequestMessage(MqttPublishMessage mqttMsg, String deviceName, TransportProtos.GetAttributeRequestMsg requestMsg) { | |
417 | - int msgId = getMsgId(mqttMsg); | |
418 | - Futures.addCallback(checkDeviceConnected(deviceName), | |
419 | - new FutureCallback<TcpGatewayDeviceSessionCtx>() { | |
420 | - @Override | |
421 | - public void onSuccess(@Nullable TcpGatewayDeviceSessionCtx deviceCtx) { | |
422 | - transportService.process(deviceCtx.getSessionInfo(), requestMsg, getPubAckCallback(channel, deviceName, msgId+"", requestMsg)); | |
423 | - } | |
424 | - | |
425 | - @Override | |
426 | - public void onFailure(Throwable t) { | |
427 | - ack(mqttMsg); | |
428 | - log.debug("[{}] Failed to process device attributes request command: {}", sessionId, deviceName, t); | |
429 | - } | |
430 | - }, context.getExecutor()); | |
310 | + private void processRpcResponseMsg(TcpGatewayDeviceSessionCtx deviceCtx, TransportProtos.ToDeviceRpcResponseMsg rpcResponseMsg, String deviceName, UUID msgId) { | |
311 | + transportService.process(deviceCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(channel, deviceName, msgId, rpcResponseMsg)); | |
431 | 312 | } |
432 | 313 | |
433 | - private TransportProtos.GetAttributeRequestMsg toGetAttributeRequestMsg(int requestId, boolean clientScope, Set<String> keys) { | |
434 | - TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); | |
435 | - result.setRequestId(requestId); | |
436 | - | |
437 | - if (clientScope) { | |
438 | - result.addAllClientAttributeNames(keys); | |
439 | - } else { | |
440 | - result.addAllSharedAttributeNames(keys); | |
441 | - } | |
442 | - return result.build(); | |
443 | - } | |
444 | 314 | |
445 | 315 | private ListenableFuture<TcpGatewayDeviceSessionCtx> checkDeviceConnected(String deviceCode) { |
446 | 316 | TcpGatewayDeviceSessionCtx ctx = devices.get(deviceCode); |
... | ... | @@ -452,29 +322,6 @@ public class TcpGatewaySessionHandler { |
452 | 322 | } |
453 | 323 | } |
454 | 324 | |
455 | - private String checkDeviceName(String deviceName) { | |
456 | - if (StringUtils.isEmpty(deviceName)) { | |
457 | - throw new RuntimeException("Device name is empty!"); | |
458 | - } else { | |
459 | - return deviceName; | |
460 | - } | |
461 | - } | |
462 | - | |
463 | - private String getDeviceName(JsonElement json) { | |
464 | - return json.getAsJsonObject().get(DEVICE_PROPERTY).getAsString(); | |
465 | - } | |
466 | - | |
467 | - private String getDeviceType(JsonElement json) { | |
468 | - JsonElement type = json.getAsJsonObject().get("type"); | |
469 | - return type == null || type instanceof JsonNull ? DEFAULT_DEVICE_TYPE : type.getAsString(); | |
470 | - } | |
471 | - | |
472 | - private JsonElement getJson(MqttPublishMessage mqttMsg) throws AdaptorException { | |
473 | - return null;//JsonMqttAdaptor.validateJsonPayload(sessionId, mqttMsg.payload()); | |
474 | - } | |
475 | - | |
476 | - | |
477 | - | |
478 | 325 | |
479 | 326 | private void deregisterSession(String deviceName, TcpGatewayDeviceSessionCtx deviceSessionCtx) { |
480 | 327 | transportService.deregisterSession(deviceSessionCtx.getSessionInfo()); |
... | ... | @@ -482,13 +329,13 @@ public class TcpGatewaySessionHandler { |
482 | 329 | log.debug("[{}] Removed device [{}] from the gateway session", sessionId, deviceName); |
483 | 330 | } |
484 | 331 | |
485 | - private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final String deviceName, final String msgId, final T msg) { | |
332 | + private <T> TransportServiceCallback<Void> getPubAckCallback(final ChannelHandlerContext ctx, final String deviceName, final UUID msgId, final T msg) { | |
486 | 333 | return new TransportServiceCallback<Void>() { |
487 | 334 | @Override |
488 | 335 | public void onSuccess(Void dummy) { |
489 | 336 | log.trace("[{}][{}] Published msg: {}", sessionId, deviceName, msg); |
490 | - if(!StringUtils.isEmpty(msgId)){ | |
491 | - pushDeviceMsg(new TCPMessage(msgId)); | |
337 | + if (!StringUtils.isEmpty(msgId)) { | |
338 | + pushDeviceMsg(msgId.toString()); | |
492 | 339 | } |
493 | 340 | } |
494 | 341 | |
... | ... | @@ -499,31 +346,25 @@ public class TcpGatewaySessionHandler { |
499 | 346 | } |
500 | 347 | }; |
501 | 348 | } |
349 | + | |
502 | 350 | /** |
503 | 351 | * 往设备推送消息 |
504 | - * @param tcp | |
352 | + * @param message | |
505 | 353 | * @return |
506 | 354 | */ |
507 | - ChannelFuture pushDeviceMsg(TCPMessage tcp) { | |
355 | + ChannelFuture pushDeviceMsg(String message) { | |
508 | 356 | try { |
509 | - String message = tcp.getMessage(); | |
510 | - byte[] payloadInBytes ; | |
511 | - if(deviceSessionCtx.getPayloadType().equals(TcpDataTypeEnum.HEX)){ | |
512 | - payloadInBytes = ByteUtils.hexStr2Bytes(message); | |
513 | - }else{ | |
514 | - payloadInBytes = message.getBytes(ByteUtils.UTF_8); | |
515 | - } | |
516 | -// ByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false); | |
517 | -// ByteBuf payload = ALLOCATOR.buffer(); | |
518 | -// payload.writeBytes(payloadInBytes); | |
357 | + byte[] payloadInBytes; | |
358 | + payloadInBytes = message.getBytes(ByteUtils.UTF_8); | |
519 | 359 | ByteBuf payload = Unpooled.copiedBuffer(payloadInBytes); |
520 | 360 | |
521 | 361 | return channel.writeAndFlush(payload); |
522 | 362 | } catch (UnsupportedEncodingException e) { |
523 | - log.error(e.getMessage(),e); | |
363 | + log.error(e.getMessage(), e); | |
524 | 364 | throw new RuntimeException(e); |
525 | 365 | } |
526 | 366 | } |
367 | + | |
527 | 368 | private void ack(MqttPublishMessage msg) { |
528 | 369 | int msgId = getMsgId(msg); |
529 | 370 | if (msgId > 0) { | ... | ... |
... | ... | @@ -57,7 +57,9 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre |
57 | 57 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
58 | 58 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
59 | 59 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
60 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
60 | 61 | |
62 | +import java.util.List; | |
61 | 63 | import java.util.concurrent.ExecutorService; |
62 | 64 | import java.util.concurrent.atomic.AtomicInteger; |
63 | 65 | |
... | ... | @@ -76,6 +78,8 @@ public interface TransportService { |
76 | 78 | |
77 | 79 | GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg); |
78 | 80 | |
81 | + | |
82 | + | |
79 | 83 | void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, |
80 | 84 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); |
81 | 85 | |
... | ... | @@ -145,4 +149,11 @@ public interface TransportService { |
145 | 149 | boolean hasSession(SessionInfoProto sessionInfo); |
146 | 150 | |
147 | 151 | void createGaugeStats(String openConnections, AtomicInteger connectionsCounter); |
152 | + | |
153 | + | |
154 | + | |
155 | + | |
156 | + | |
157 | + //Thingskit function | |
158 | + List<ScriptProto> getScripts(ScriptProto msg); | |
148 | 159 | } | ... | ... |
... | ... | @@ -81,6 +81,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
81 | 81 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
82 | 82 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
83 | 83 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
84 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
84 | 85 | import org.thingsboard.server.queue.TbQueueCallback; |
85 | 86 | import org.thingsboard.server.queue.TbQueueConsumer; |
86 | 87 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
... | ... | @@ -315,6 +316,8 @@ public class DefaultTransportService implements TransportService { |
315 | 316 | } |
316 | 317 | } |
317 | 318 | |
319 | + | |
320 | + | |
318 | 321 | @Override |
319 | 322 | public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds(TransportProtos.GetSnmpDevicesRequestMsg requestMsg) { |
320 | 323 | TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( |
... | ... | @@ -1241,4 +1244,25 @@ public class DefaultTransportService implements TransportService { |
1241 | 1244 | log.info("Transport Stats: {}", values); |
1242 | 1245 | } |
1243 | 1246 | } |
1247 | + | |
1248 | + | |
1249 | + | |
1250 | + | |
1251 | + | |
1252 | + | |
1253 | + | |
1254 | + | |
1255 | + | |
1256 | + //Thingskit function | |
1257 | + @Override | |
1258 | + public List<ScriptProto> getScripts(ScriptProto msg) { | |
1259 | + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = | |
1260 | + new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build()); | |
1261 | + try { | |
1262 | + TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | |
1263 | + return response.getValue().getScriptsResponseMsgList(); | |
1264 | + } catch (InterruptedException | ExecutionException e) { | |
1265 | + throw new RuntimeException(e); | |
1266 | + } | |
1267 | + } | |
1244 | 1268 | } | ... | ... |
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptFactory.java
deleted
100644 → 0
1 | -/** | |
2 | - * Copyright © 2016-2022 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.common.yunteng.script; | |
17 | - | |
18 | -public class TkScriptFactory { | |
19 | - | |
20 | - public static final String MSG = "params"; | |
21 | - | |
22 | - public static final String RULE_NODE_FUNCTION_NAME = "tcpTransportFunc"; | |
23 | - | |
24 | - public static final String INCLUD_ORIGINAL_DATA = "out.source=params;"; | |
25 | - private static final String JS_WRAPPER_PREFIX_TEMPLATE = "function %s(params) { " + | |
26 | - " var out = new Object(); " + | |
27 | - " return JSON.stringify(%s(params));" + | |
28 | - " function %s(%s) {"; | |
29 | - private static final String JS_WRAPPER_SUFFIX = "return out; \n }" + | |
30 | - "\n}"; | |
31 | - | |
32 | - | |
33 | - public static String generateRuleNodeScript(String functionName, String scriptBody, String... argNames) { | |
34 | - String msgArg; | |
35 | - | |
36 | - msgArg = (argNames != null && argNames.length >= 1) ? argNames[0]:MSG; | |
37 | - | |
38 | - String jsWrapperPrefix = String.format(JS_WRAPPER_PREFIX_TEMPLATE | |
39 | - , functionName | |
40 | - ,RULE_NODE_FUNCTION_NAME | |
41 | - , RULE_NODE_FUNCTION_NAME, msgArg); | |
42 | - String result = jsWrapperPrefix + scriptBody + JS_WRAPPER_SUFFIX; | |
43 | - return result; | |
44 | - } | |
45 | - | |
46 | -} |
common/transport/transport-api/src/main/java/org/thingsboard/server/common/yunteng/script/TkScriptType.java
deleted
100644 → 0
1 | -/** | |
2 | - * Copyright © 2016-2022 The Thingsboard Authors | |
3 | - * | |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | - * you may not use this file except in compliance with the License. | |
6 | - * You may obtain a copy of the License at | |
7 | - * | |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | - * | |
10 | - * Unless required by applicable law or agreed to in writing, software | |
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | - * See the License for the specific language governing permissions and | |
14 | - * limitations under the License. | |
15 | - */ | |
16 | -package org.thingsboard.server.common.yunteng.script; | |
17 | - | |
18 | -public enum TkScriptType { | |
19 | - TCP_TRANSPORT_SCRIPT | |
20 | -} |
... | ... | @@ -7,21 +7,27 @@ import lombok.EqualsAndHashCode; |
7 | 7 | import org.apache.ibatis.type.BooleanTypeHandler; |
8 | 8 | import org.apache.ibatis.type.EnumTypeHandler; |
9 | 9 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; |
10 | -import org.thingsboard.server.common.data.yunteng.enums.TcpDataTypeEnum; | |
10 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
11 | 11 | |
12 | 12 | @Data |
13 | 13 | @TableName(value = ModelConstants.Table.TK_DEVICE_SCRIPT_TABLE_NAME, autoResultMap = true) |
14 | 14 | @EqualsAndHashCode(callSuper = true) |
15 | 15 | public class TkDeviceScriptEntity extends TenantBaseEntity { |
16 | - private String name; | |
17 | - private String convertJs; | |
18 | - /** 告警状态:0:正常 1:告警 */ | |
19 | - private Integer status; | |
16 | + private String name; | |
17 | + private String convertJs; | |
18 | + /** | |
19 | + * 告警状态:0:正常 1:告警 | |
20 | + */ | |
21 | + private Integer status; | |
20 | 22 | |
21 | - private String description; | |
22 | - @TableField(typeHandler = BooleanTypeHandler.class) | |
23 | - private boolean saveOriginalData; | |
24 | - /** 脚本编数据编码类型 */ | |
25 | - @TableField(typeHandler = EnumTypeHandler.class) | |
26 | - private TcpDataTypeEnum dataType; | |
23 | + private String description; | |
24 | + @TableField(typeHandler = BooleanTypeHandler.class) | |
25 | + private boolean saveOriginalData; | |
26 | + | |
27 | + | |
28 | + /** | |
29 | + * 脚本类型 | |
30 | + */ | |
31 | + @TableField(typeHandler = EnumTypeHandler.class) | |
32 | + private TkScriptFunctionType scriptType; | |
27 | 33 | } | ... | ... |
... | ... | @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio |
19 | 19 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
20 | 20 | import org.thingsboard.server.common.data.yunteng.dto.*; |
21 | 21 | import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; |
22 | +import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; | |
22 | 23 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
23 | 24 | import org.thingsboard.server.dao.yunteng.entities.*; |
24 | 25 | import org.thingsboard.server.dao.yunteng.jpa.dao.TkJpaDeviceProfileDao; |
... | ... | @@ -244,22 +245,11 @@ public class TkDeviceProfileServiceImpl |
244 | 245 | } |
245 | 246 | |
246 | 247 | @Override |
247 | - public List<DeviceProfileDTO> findDeviceProfileByIds(String tenantId, List<String> ids) { | |
248 | + public List<DeviceProfileDTO> findDeviceProfileByIds(String tenantId, List<String> ids, TransportTypeEnum transportType) { | |
248 | 249 | if (StringUtils.isEmpty(tenantId) || null == ids) { |
249 | 250 | throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); |
250 | 251 | } |
251 | - List<TkDeviceProfileEntity> entities = | |
252 | - baseMapper.selectList( | |
253 | - new LambdaQueryWrapper<TkDeviceProfileEntity>() | |
254 | - .eq(TkDeviceProfileEntity::getTenantId, tenantId) | |
255 | - .in(TkDeviceProfileEntity::getId, ids)); | |
256 | - | |
257 | - if (null == entities || entities.isEmpty()) { | |
258 | - return null; | |
259 | - } | |
260 | - return entities.stream() | |
261 | - .map(obj -> obj.getDTO(DeviceProfileDTO.class)) | |
262 | - .collect(Collectors.toList()); | |
252 | + return baseMapper.profileByTransportAndIds(tenantId,ids,transportType); | |
263 | 253 | } |
264 | 254 | |
265 | 255 | @Override | ... | ... |
... | ... | @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; |
8 | 8 | import org.apache.commons.lang3.StringUtils; |
9 | 9 | import org.springframework.stereotype.Service; |
10 | 10 | import org.springframework.transaction.annotation.Transactional; |
11 | +import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration; | |
11 | 12 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
12 | 13 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; |
13 | 14 | import org.thingsboard.server.common.data.yunteng.constant.QueryConstant; |
... | ... | @@ -17,6 +18,8 @@ import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
17 | 18 | import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; |
18 | 19 | import org.thingsboard.server.common.data.yunteng.dto.TkCustomerDeviceDTO; |
19 | 20 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
21 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
22 | +import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; | |
20 | 23 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
21 | 24 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity; |
22 | 25 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceScriptEntity; |
... | ... | @@ -98,14 +101,21 @@ public class TkDeviceScriptServiceImpl |
98 | 101 | } |
99 | 102 | |
100 | 103 | @Override |
101 | - public String getScriptText(String tenantId, String scriptId) { | |
104 | + public List<TkDeviceScriptDTO> getScriptes(TkScriptFunctionType type, UUID tenantId, UUID projectId, UUID scriptId){ | |
102 | 105 | LambdaQueryWrapper<TkDeviceScriptEntity> queryWrapper = |
103 | - new QueryWrapper<TkDeviceScriptEntity>() | |
104 | - .lambda() | |
105 | - .eq(TkDeviceScriptEntity::getTenantId, tenantId) | |
106 | - .eq(TkDeviceScriptEntity::getId, scriptId); | |
107 | - TkDeviceScriptEntity result = baseMapper.selectOne(queryWrapper); | |
108 | - return (result == null || result.getStatus() == 0) ? null : result.getConvertJs(); | |
106 | + new QueryWrapper<TkDeviceScriptEntity>().lambda(); | |
107 | + if(scriptId == null){ | |
108 | + queryWrapper.eq(TkDeviceScriptEntity::getScriptType, type); | |
109 | + }else{ | |
110 | + queryWrapper.eq(TkDeviceScriptEntity::getId, scriptId.toString()); | |
111 | + } | |
112 | + if(tenantId != null){ | |
113 | + queryWrapper.eq(TkDeviceScriptEntity::getTenantId, tenantId.toString()); | |
114 | + } | |
115 | + List<TkDeviceScriptEntity> result = baseMapper.selectList(queryWrapper); | |
116 | + return result.stream() | |
117 | + .map(item -> item.getDTO(TkDeviceScriptDTO.class)) | |
118 | + .collect(Collectors.toList()); | |
109 | 119 | } |
110 | 120 | |
111 | 121 | @Override |
... | ... | @@ -264,13 +274,19 @@ public class TkDeviceScriptServiceImpl |
264 | 274 | .map(DeviceDTO::getDeviceProfileId) |
265 | 275 | .collect(Collectors.toList()); |
266 | 276 | List<DeviceProfileDTO> deviceProfileDTOList = |
267 | - tkDeviceProfileService.findDeviceProfileByIds(tenantId, deviceProfiles); | |
277 | + tkDeviceProfileService.findDeviceProfileByIds(tenantId, deviceProfiles, TransportTypeEnum.TCP); | |
268 | 278 | return Optional.ofNullable(deviceProfileDTOList) |
269 | 279 | .map( |
270 | - deviceProfileDTOS -> | |
271 | - deviceProfileDTOS.stream() | |
272 | - .map(DeviceProfileDTO::getScriptId) | |
273 | - .collect(Collectors.toSet())) | |
280 | + deviceProfileDTOS ->{ | |
281 | + Set<String> tcpScriptes = new HashSet<>(); | |
282 | + deviceProfileDTOS.forEach(p->{ | |
283 | + TkTcpDeviceProfileTransportConfiguration config = (TkTcpDeviceProfileTransportConfiguration) p.getProfileData().getTransportConfiguration(); | |
284 | + tcpScriptes.add(config.getUpScriptId()); | |
285 | + tcpScriptes.add(config.getUpScriptId()); | |
286 | + tcpScriptes.add(config.getUpScriptId()); | |
287 | + }); | |
288 | + return tcpScriptes; | |
289 | + }) | |
274 | 290 | .orElse(null); |
275 | 291 | } |
276 | 292 | return null; | ... | ... |
... | ... | @@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param; |
7 | 7 | import org.thingsboard.server.common.data.DeviceTransportType; |
8 | 8 | import org.thingsboard.server.common.data.yunteng.dto.*; |
9 | 9 | import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; |
10 | +import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; | |
10 | 11 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity; |
11 | 12 | |
12 | 13 | import java.util.List; |
... | ... | @@ -28,10 +29,17 @@ public interface TkDeviceProfileMapper extends BaseMapper<TkDeviceProfileEntity> |
28 | 29 | @Param("transportType") String transportType, |
29 | 30 | @Param("deviceProfileIds") List<String> deviceProfileIds); |
30 | 31 | |
32 | + @Deprecated | |
31 | 33 | List<DeviceProfileDTO> profileByScriptId( |
32 | - @Param("tenantId") String tenantId, | |
33 | - @Param("scriptId") String scriptId, | |
34 | - @Param("deviceType") DeviceTypeEnum deviceType); | |
34 | + @Param("tenantId") String tenantId, | |
35 | + @Param("scriptId") String scriptId, | |
36 | + @Param("deviceType") DeviceTypeEnum deviceType); | |
37 | + | |
38 | + List<DeviceProfileDTO> profileByTransportAndIds( | |
39 | + @Param("tenantId") String tenantId, | |
40 | + @Param("projectIds") List<String> projectIds, | |
41 | + @Param("deviceType") TransportTypeEnum transportType); | |
42 | + | |
35 | 43 | |
36 | 44 | List<String> getDeviceProfileIds( |
37 | 45 | @Param("tenantId") String tenantId, | ... | ... |
... | ... | @@ -3,6 +3,7 @@ package org.thingsboard.server.dao.yunteng.service; |
3 | 3 | import org.thingsboard.server.common.data.id.CustomerId; |
4 | 4 | import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; |
5 | 5 | import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; |
6 | +import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; | |
6 | 7 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
7 | 8 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity; |
8 | 9 | |
... | ... | @@ -29,7 +30,7 @@ public interface TkDeviceProfileService extends BaseService<TkDeviceProfileEntit |
29 | 30 | List<DeviceProfileDTO> findCustomerDeviceProfiles( |
30 | 31 | String tenantId, CustomerId customerId, DeviceTypeEnum deviceType); |
31 | 32 | |
32 | - List<DeviceProfileDTO> findDeviceProfileByIds(String tenantId, List<String> ids); | |
33 | + List<DeviceProfileDTO> findDeviceProfileByIds(String tenantId, List<String> ids, TransportTypeEnum transportType); | |
33 | 34 | |
34 | 35 | List<DeviceProfileDTO> findDeviceProfile(String tenantId); |
35 | 36 | /** 验证表单数据有效性 */ | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | |
3 | 3 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
4 | +import org.thingsboard.server.common.data.yunteng.enums.TkScriptFunctionType; | |
4 | 5 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
5 | 6 | import org.thingsboard.server.dao.yunteng.entities.TkDeviceScriptEntity; |
6 | 7 | |
7 | -import java.util.List; | |
8 | -import java.util.Map; | |
9 | -import java.util.Optional; | |
10 | -import java.util.Set; | |
8 | +import java.util.*; | |
11 | 9 | |
12 | 10 | public interface TkDeviceScriptService extends BaseService<TkDeviceScriptEntity>{ |
13 | 11 | |
... | ... | @@ -17,7 +15,7 @@ public interface TkDeviceScriptService extends BaseService<TkDeviceScriptEntity> |
17 | 15 | * @param scriptId |
18 | 16 | * @return |
19 | 17 | */ |
20 | - String getScriptText(String tenantId, String scriptId); | |
18 | + List<TkDeviceScriptDTO> getScriptes(TkScriptFunctionType type, UUID tenantId, UUID projectId, UUID scriptId); | |
21 | 19 | |
22 | 20 | TkDeviceScriptDTO insertOrUpdate(TkDeviceScriptDTO deviceDTO); |
23 | 21 | ... | ... |
... | ... | @@ -12,7 +12,6 @@ |
12 | 12 | <result property="image" column="image"/> |
13 | 13 | <result property="description" column="description"/> |
14 | 14 | <result property="tenantId" column="tenant_id"/> |
15 | - <result property="scriptId" column="script_id"/> | |
16 | 15 | <result property="transportType" column="transport_type"/> |
17 | 16 | <result property="provisionType" column="provision_type"/> |
18 | 17 | <result property="deviceType" column="device_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> |
... | ... | @@ -86,6 +85,25 @@ |
86 | 85 | </where> |
87 | 86 | </select> |
88 | 87 | |
88 | + <select id="profileByTransportAndIds" resultMap="detail"> | |
89 | + SELECT | |
90 | + <include refid="basicColumns"/> | |
91 | + FROM device_profile base | |
92 | + LEFT JOIN tk_device_profile iot ON iot.tb_profile_id = base.id::TEXT | |
93 | + <where> | |
94 | + iot.tenant_id = #{tenantId} | |
95 | + <if test="projectIds != null"> | |
96 | + AND iot.id IN | |
97 | + <foreach collection="projectIds" item="id" open="(" separator="," close=")"> | |
98 | + #{id} | |
99 | + </foreach> | |
100 | + </if> | |
101 | + <if test="transportType !=null"> | |
102 | + AND iot.transport_type = #{transportType} | |
103 | + </if> | |
104 | + </where> | |
105 | + </select> | |
106 | + | |
89 | 107 | <select id="getDeviceProfileIds" resultType="java.lang.String"> |
90 | 108 | SELECT iot.id |
91 | 109 | FROM device_profile base | ... | ... |