Commit ec153776902d082327b0ad0ed0b289ace7f886ea

Authored by xp.Huang
2 parents eee8a553 0911607e

Merge branch 'fix_tcp_microservice' into 'master_dev'

fix: tcp微服务部署时启动异常

See merge request yunteng/thingskit!411
... ... @@ -202,8 +202,11 @@ public class TkDeviceProfileController extends BaseController {
202 202 .getProfileData().getTransportConfiguration();
203 203 if(tcpProfile.getTcpAuthType().equals(TcpAuthTypeEnum.DATA_COMBINATION)){
204 204 String key = deviceProfileDTO.getTenantId() + "_" + deviceProfileDTO.getTbProfileId();
205   - Map<String,Object> cacheMap = (Map<String, Object>)
206   - cacheUtils.get(cacheName, FastIotConstants.OtherKey.DATA_COMBINATION_KEY).get();
  205 + Optional<Object> stringObjectMap = cacheUtils.get(cacheName, FastIotConstants.OtherKey.DATA_COMBINATION_KEY);
  206 + Map<String,Object> cacheMap = new HashMap<>();
  207 + if(stringObjectMap.isPresent()){
  208 + cacheMap = (Map<String,Object>)stringObjectMap.get();
  209 + }
207 210 cacheMap.put(key,tcpProfile);
208 211 cacheUtils.put(cacheName,FastIotConstants.OtherKey.DATA_COMBINATION_KEY,cacheMap);
209 212 }
... ...
... ... @@ -84,9 +84,8 @@ public class TkDeviceScriptController extends BaseController {
84 84
85 85 /**脚本引擎启用/禁用时,刷新设备接入服务中的脚本,禁用时使用默认脚本*/
86 86 scriptService.updateScriptStatus(tenantId, id, status);
87   - scriptService.getDeviceScript(tenantId, id).ifPresent(i->{
88   - tbClusterService.onJsScriptChange(i,null);
89   - });
  87 + scriptDTO.setStatus(status);
  88 + tbClusterService.onJsScriptChange(scriptDTO,null);
90 89 return ResponseEntity.ok(true);
91 90 }
92 91
... ...
... ... @@ -65,12 +65,14 @@ import org.thingsboard.server.common.data.page.PageData;
65 65 import org.thingsboard.server.common.data.page.PageLink;
66 66 import org.thingsboard.server.common.data.queue.Queue;
67 67 import org.thingsboard.server.common.data.relation.EntityRelation;
  68 +import org.thingsboard.server.common.data.script.ScriptLanguage;
68 69 import org.thingsboard.server.common.data.security.DeviceCredentials;
69 70 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
70 71 import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager;
71 72 import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;
72 73 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
73 74 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
  75 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
74 76 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;
75 77 import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO;
76 78 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;
... ... @@ -158,7 +160,7 @@ public class DefaultTransportApiService implements TransportApiService {
158 160 //thingskit
159 161 private final CacheUtils cacheUtils;
160 162 private final TkDeviceService tkDeviceService;
161   - private final TkDeviceScriptService scriptService;
  163 + private final TkDeviceScriptService tkDeviceScriptService;
162 164 private final TkVideoChannelService channelService;
163 165 private final TkMediaServerNodeService mediaServerNodeService;
164 166 private final VideoStreamSessionManager videoStreamSessionManager;
... ... @@ -254,6 +256,10 @@ public class DefaultTransportApiService implements TransportApiService {
254 256 TransportProtos.ValidateTcpDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTcpTokenRequestMsg();
255 257 final String token = msg.getToken();
256 258 result = handlerExecutor.submit(() -> validateTcpUdpCredentials(token, DeviceCredentialsType.ACCESS_TOKEN));
  259 + } else if(transportApiRequestMsg.hasUpScriptRequestMsg()){
  260 + result = handle(transportApiRequestMsg.getUpScriptRequestMsg());
  261 + } else if(transportApiRequestMsg.hasDataCombinationRequest()){
  262 + result = handle(transportApiRequestMsg.getDataCombinationRequest());
257 263 }
258 264
259 265 return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture),
... ... @@ -833,25 +839,41 @@ public class DefaultTransportApiService implements TransportApiService {
833 839 }
834 840 // Thingskit function
835 841 private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) {
836   - List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes();
837   - TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();
838   - allScriptes.forEach(
839   - item -> {
840   - UUID tenantId = UUID.fromString(item.getTenantId());
841   - UUID id = UUID.fromString(item.getId());
842   - responseBuilder.addScriptsResponseMsg(
843   - TransportProtos.ScriptProto.newBuilder()
844   - .setConvertJs(item.getConvertJs())
845   - .setTenantIdLSB(tenantId.getLeastSignificantBits())
846   - .setTenantIdMSB(tenantId.getMostSignificantBits())
847   - .setScriptIdLSB(id.getLeastSignificantBits())
848   - .setScriptIdMSB(id.getMostSignificantBits())
849   - .setFunctionType(item.getScriptType())
850   - .setStatus(item.getStatus()));
851   - });
  842 + List<TkDeviceScriptDTO> scriptDTOS = tkDeviceScriptService.findAllEnabledScript();
  843 + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();
  844 + if(null != scriptDTOS && !scriptDTOS.isEmpty()){
  845 + responseBuilder.addAllScriptResponseProto(scriptDTOS.stream().map(script->{
  846 + UUID uuid = UUID.fromString(script.getTenantId());
  847 + return TransportProtos.ScriptResponseProto.newBuilder().setTenantIdLSB(uuid.getLeastSignificantBits())
  848 + .setTenantIdMSB(uuid.getMostSignificantBits())
  849 + .setScriptId(script.getId())
  850 + .setScriptLanguage(script.getScriptLanguage().name())
  851 + .setScriptType(script.getScriptType())
  852 + .setContent(script.getScriptLanguage().equals(ScriptLanguage.TBEL)?
  853 + script.getConvertTbel():script.getConvertJs()).build();
  854 + }).collect(Collectors.toList())).build();
  855 + }
852 856 return Futures.immediateFuture(responseBuilder.build());
853 857 }
854 858
  859 + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.DataCombinationMsg requestMsg){
  860 + try {
  861 + List<DeviceProfile> profiles = deviceProfileService.findByDataCombinationIsTrue().get();
  862 + if(null != profiles && !profiles.isEmpty()){
  863 + Map<String, Object> cacheMap = new HashMap<>();
  864 + for (DeviceProfile deviceProfile : profiles) {
  865 + cacheMap.put(deviceProfile.getTenantId() + "_" +
  866 + deviceProfile.getId().toString(),deviceProfile.getProfileData().getTransportConfiguration());
  867 + }
  868 + cacheUtils.put(FastIotConstants.CacheConfigKey.TCP_DATA_COMBINATION_KEY, FastIotConstants.OtherKey.DATA_COMBINATION_KEY,cacheMap);
  869 + }
  870 + }catch (Exception e){
  871 + log.error(ErrorMessage.CACHE_DATA_COMBINATION_FAILED.getMessage());
  872 + }
  873 + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();
  874 + return Futures.immediateFuture(responseBuilder.build());
  875 + }
  876 +
855 877 private ListenableFuture<TransportApiResponseMsg> handleGbt(
856 878 TransportProtos.Gbt28181RequestMsg requestMsg) {
857 879 TransportProtos.Gbt28181ResponseMsg.Builder responseMsgBuilder =
... ... @@ -1023,5 +1045,17 @@ public class DefaultTransportApiService implements TransportApiService {
1023 1045 }
1024 1046 return null;
1025 1047 }
1026   -
  1048 + //thingskit
  1049 + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.UpScriptProto requestMsg){
  1050 + String upScriptId = requestMsg.getUpScriptId();
  1051 + TransportProtos.UpScriptResponseProto.Builder builder = TransportProtos.UpScriptResponseProto.newBuilder();
  1052 + if(StringUtils.isNotEmpty(upScriptId)){
  1053 + ScriptLanguage language = tkDeviceScriptService.findScriptLanguageById(upScriptId);
  1054 + builder.setScriptLanguage(null != language ? language.name():null);
  1055 + }
  1056 + return Futures.immediateFuture(
  1057 + TransportApiResponseMsg.newBuilder()
  1058 + .setUpScriptResponseMsg(builder.build())
  1059 + .build());
  1060 + }
1027 1061 }
... ...
... ... @@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.validation.NoXss;
21 21 import org.thingsboard.server.common.data.yunteng.enums.ProtocolAnalysisEnum;
22 22 import org.thingsboard.server.common.data.yunteng.enums.TcpAuthTypeEnum;
23 23
  24 +import java.io.Serializable;
  25 +
24 26 @Data
25 27 public class TkTcpDeviceProfileTransportConfiguration implements DeviceProfileTransportConfiguration {
26 28 /**
... ... @@ -56,7 +58,8 @@ public class TkTcpDeviceProfileTransportConfiguration implements DeviceProfileTr
56 58 }
57 59
58 60 @Data
59   - public class DataCombinationAuth {
  61 + public class DataCombinationAuth implements Serializable {
  62 +
60 63 /**
61 64 * 数据截取开始的下标
62 65 */
... ...
... ... @@ -17,22 +17,4 @@ public interface TkCommonService {
17 17 * @return 返回字典Item表
18 18 */
19 19 SysDictItemDTO getDictValueByCodeAndText(String dictCode, String codeValue);
20   -
21   - /**
22   - * 获取所有数据携带的产品即设备配置
23   - * @return 产品列表
24   - */
25   - ListenableFuture<List<DeviceProfile>> findByDataCombinationIsTrue();
26   -
27   - /**
28   - * 根据脚本ID查询脚本使用的语言
29   - * @param scriptId 脚本ID
30   - * @return 脚本语言
31   - */
32   - ScriptLanguage getScriptLanguageById(String scriptId);
33   -
34   - /**
35   - * 启动所有的脚本
36   - */
37   - void evalAllEnabledScript();
38 20 }
... ...
... ... @@ -1278,6 +1278,8 @@ message TransportApiRequestMsg {
1278 1278 Gbt28181RequestMsg gbt28181RequestMsg = 17;
1279 1279 Gbt28181MediaServerMsg gbt28181MediaServerMsg = 18;
1280 1280 ValidateTcpDeviceTokenRequestMsg validateTcpTokenRequestMsg = 19;
  1281 + UpScriptProto upScriptRequestMsg = 20;
  1282 + DataCombinationMsg dataCombinationRequest = 21;
1281 1283 }
1282 1284
1283 1285 /* Response from ThingsBoard Core Service to Transport Service */
... ... @@ -1294,9 +1296,10 @@ message TransportApiResponseMsg {
1294 1296 GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10;
1295 1297 repeated GetQueueRoutingInfoResponseMsg getQueueRoutingInfoResponseMsgs = 11;
1296 1298 //Thingskit function
1297   - repeated ScriptProto scriptsResponseMsg = 12;
  1299 + UpScriptResponseProto upScriptResponseMsg = 12;
1298 1300 Gbt28181ResponseMsg gbt28181ResponseMsg = 13;
1299 1301 repeated Gbt28181MediaServerMsg gbt28181MediaServerMsg = 14;
  1302 + repeated ScriptResponseProto scriptResponseProto = 15;
1300 1303 }
1301 1304
1302 1305 /* Messages that are handled by ThingsBoard Core Service */
... ... @@ -1435,17 +1438,29 @@ message LifecycleEventProto {
1435 1438 string error = 8;
1436 1439 }
1437 1440
1438   -//Thingskit function 请求:functionType、;响应:tenantId、projectId、scriptId、convertJs
  1441 +//Thingskit function
  1442 +
  1443 +message DataCombinationMsg{
  1444 +
  1445 +}
  1446 +
1439 1447 message ScriptProto{
  1448 +
  1449 +}
  1450 +message ScriptResponseProto{
1440 1451 int64 tenantIdMSB = 1;
1441 1452 int64 tenantIdLSB = 2;
1442   -// int64 projectIdMSB = 3;
1443   -// int64 projectIdLSB = 4;
1444   - int64 scriptIdMSB = 3;
1445   - int64 scriptIdLSB = 4;
1446   - string functionType = 5;
1447   - string convertJs = 6;
1448   - int32 status = 7;
  1453 + string scriptId = 3;
  1454 + string scriptLanguage = 4;
  1455 + string scriptType = 5;
  1456 + string content = 6;
  1457 +
  1458 +}
  1459 +message UpScriptProto{
  1460 + string upScriptId = 1;
  1461 +}
  1462 +message UpScriptResponseProto{
  1463 + string scriptLanguage = 1;
1449 1464 }
1450 1465 //thingskit function 设备上报的物模型事件
1451 1466 message PostEventMsg {
... ...
1 1 /**
2 2 * Copyright © 2016-2022 The Thingsboard Authors
3 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
  4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 6 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 8 *
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
  9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 12 * limitations under the License.
15 13 */
16 14 package org.thingsboard.server.transport.tcp;
... ... @@ -24,140 +22,185 @@ import org.springframework.beans.factory.annotation.Value;
24 22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
25 23 import org.springframework.boot.context.event.ApplicationReadyEvent;
26 24 import org.springframework.context.event.EventListener;
27   -import org.springframework.core.annotation.Order;
28 25 import org.springframework.stereotype.Component;
29 26 import org.thingsboard.common.util.ThingsBoardThreadFactory;
  27 +import org.thingsboard.script.api.ScriptType;
30 28 import org.thingsboard.script.api.js.JsInvokeService;
31 29 import org.thingsboard.script.api.tbel.TbelInvokeService;
32   -import org.thingsboard.server.common.data.DeviceProfile;
33   -import org.thingsboard.server.common.data.yunteng.common.TkCommonService;
  30 +import org.thingsboard.server.common.data.id.TenantId;
  31 +import org.thingsboard.server.common.data.script.ScriptLanguage;
34 32 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
35 33 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
36   -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  34 +import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO;
  35 +import org.thingsboard.server.common.data.yunteng.enums.StatusEnum;
37 36 import org.thingsboard.server.common.transport.TransportContext;
  37 +import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent;
  38 +import org.thingsboard.server.queue.util.AfterStartUp;
38 39 import org.thingsboard.server.transport.tcp.adaptors.JsonTcpAdaptor;
39 40
40 41 import javax.annotation.PostConstruct;
41 42 import java.net.InetSocketAddress;
42   -import java.util.HashMap;
  43 +
  44 +import org.thingsboard.server.gen.transport.TransportProtos;
  45 +
43 46 import java.util.List;
44   -import java.util.Map;
  47 +import java.util.Objects;
  48 +import java.util.UUID;
  49 +import java.util.concurrent.ExecutionException;
45 50 import java.util.concurrent.Executors;
46 51 import java.util.concurrent.ScheduledExecutorService;
47 52 import java.util.concurrent.TimeUnit;
48 53 import java.util.concurrent.atomic.AtomicInteger;
49 54
50   -/**
51   - * Created by ashvayka on 04.10.18.
52   - */
  55 +/** Created by ashvayka on 04.10.18. */
53 56 @Slf4j
54 57 @Component
55   -@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.tcp.enabled}'=='true')")
  58 +@ConditionalOnExpression(
  59 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.tcp.enabled}'=='true')")
56 60 public class TcpTransportContext extends TransportContext {
57 61
58   - @Getter
59   - @Autowired(required = false)
60   - private TcpSslHandlerProvider sslHandlerProvider;
61   -
62   - /**注入多种数据协议处理器,例如:modbus等*/
63   - @Getter
64   - @Autowired
65   - private JsonTcpAdaptor jsonTcpAdaptor;
66   -
67   - @Getter
68   - @Autowired
69   - private JsInvokeService jsEngine;
70   -
71   - @Getter
72   - @Autowired
73   - private TbelInvokeService tbelInvokeService;
74   -
75   - @Getter
76   - @Autowired
77   - private CacheUtils cacheUtils;
78   -
79   - @Getter
80   - @Autowired
81   - private TkCommonService tkCommonService;
82   -
83   - @Getter
84   - @Value("${transport.tcp.netty.max_payload_size}")
85   - private Integer maxPayloadSize;
86   -
87   - @Getter
88   - @Value("${transport.tcp.ssl.skip_validity_check_for_client_cert:false}")
89   - private boolean skipValidityCheckForClientCert;
90   -
91   - @Getter
92   - @Setter
93   - private SslHandler sslHandler;
94   -
95   - @Getter
96   - @Value("${transport.tcp.msg_queue_size_per_device_limit:100}")
97   - private int messageQueueSizePerDeviceLimit;
98   -
99   - @Getter
100   - @Value("${transport.tcp.timeout:10000}")
101   - private long timeout;
102   -
103   - @Getter
104   - @Value("${transport.tcp.proxy_enabled:false}")
105   - private boolean proxyEnabled;
106   -
107   - private final AtomicInteger connectionsCounter = new AtomicInteger();
108   - protected ScheduledExecutorService schedulerExecutor;
109   - @Getter
110   - private boolean ready=false;
111   - @PostConstruct
112   - public void init() {
113   - super.init();
114   - transportService.createGaugeStats("openConnections", connectionsCounter);
115   - schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("tcp-init"));
  62 + @Getter
  63 + @Autowired(required = false)
  64 + private TcpSslHandlerProvider sslHandlerProvider;
  65 +
  66 + /** 注入多种数据协议处理器,例如:modbus等 */
  67 + @Getter @Autowired private JsonTcpAdaptor jsonTcpAdaptor;
  68 +
  69 + @Getter @Autowired private JsInvokeService jsEngine;
  70 +
  71 + @Getter @Autowired private TbelInvokeService tbelInvokeService;
  72 +
  73 + @Getter @Autowired private CacheUtils cacheUtils;
  74 +
  75 + @Getter
  76 + @Value("${transport.tcp.netty.max_payload_size}")
  77 + private Integer maxPayloadSize;
  78 +
  79 + @Getter
  80 + @Value("${transport.tcp.ssl.skip_validity_check_for_client_cert:false}")
  81 + private boolean skipValidityCheckForClientCert;
  82 +
  83 + @Getter @Setter private SslHandler sslHandler;
  84 +
  85 + @Getter
  86 + @Value("${transport.tcp.msg_queue_size_per_device_limit:100}")
  87 + private int messageQueueSizePerDeviceLimit;
  88 +
  89 + @Getter
  90 + @Value("${transport.tcp.timeout:10000}")
  91 + private long timeout;
  92 +
  93 + @Getter
  94 + @Value("${transport.tcp.proxy_enabled:false}")
  95 + private boolean proxyEnabled;
  96 +
  97 + private final AtomicInteger connectionsCounter = new AtomicInteger();
  98 + protected ScheduledExecutorService schedulerExecutor;
  99 + @Getter private boolean ready = false;
  100 +
  101 + @PostConstruct
  102 + public void init() {
  103 + super.init();
  104 + transportService.createGaugeStats("openConnections", connectionsCounter);
  105 + schedulerExecutor =
  106 + Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("tcp-init"));
  107 + }
  108 +
  109 + public void channelRegistered() {
  110 + connectionsCounter.incrementAndGet();
  111 + }
  112 +
  113 + public void channelUnregistered() {
  114 + connectionsCounter.decrementAndGet();
  115 + }
  116 +
  117 + public boolean checkAddress(InetSocketAddress address) {
  118 + return rateLimitService.checkAddress(address);
  119 + }
  120 +
  121 + public void onAuthSuccess(InetSocketAddress address) {
  122 + rateLimitService.onAuthSuccess(address);
  123 + }
  124 +
  125 + public void onAuthFailure(InetSocketAddress address) {
  126 + rateLimitService.onAuthFailure(address);
  127 + }
  128 +
  129 + @EventListener(ApplicationReadyEvent.class)
  130 + @AfterStartUp(order = AfterStartUp.AFTER_TRANSPORT_SERVICE)
  131 + public void onApplicationEvent() {
  132 + String cacheName = FastIotConstants.CacheConfigKey.TCP_DATA_COMBINATION_KEY;
  133 + // 先清理掉数据携带的所有缓存
  134 + cacheUtils.invalidateCacheName(cacheName);
  135 + transportService.process(TransportProtos.DataCombinationMsg.newBuilder().build());
  136 + List<TransportProtos.ScriptResponseProto> protoList =
  137 + transportService.findAllEnabledScript(TransportProtos.ScriptProto.newBuilder().build());
  138 +
  139 + if (null != protoList && !protoList.isEmpty()) {
  140 + for (TransportProtos.ScriptResponseProto script : protoList) {
  141 + TenantId tbTenantId =
  142 + TenantId.fromUUID(new UUID(script.getTenantIdMSB(), script.getTenantIdLSB()));
  143 + String scriptId = script.getScriptId();
  144 + ScriptType scriptType = ScriptType.valueOf(script.getScriptType());
  145 + String content = script.getContent();
  146 + evalScript(
  147 + scriptId,
  148 + scriptType,
  149 + content,
  150 + ScriptLanguage.valueOf(script.getScriptLanguage()),
  151 + tbTenantId,
  152 + StatusEnum.ENABLE.getIndex());
  153 + }
116 154 }
117   -
118   - public void channelRegistered() {
119   - connectionsCounter.incrementAndGet();
120   - }
121   -
122   - public void channelUnregistered() {
123   - connectionsCounter.decrementAndGet();
124   - }
125   -
126   - public boolean checkAddress(InetSocketAddress address) {
127   - return rateLimitService.checkAddress(address);
128   - }
129   -
130   - public void onAuthSuccess(InetSocketAddress address) {
131   - rateLimitService.onAuthSuccess(address);
132   - }
133   -
134   - public void onAuthFailure(InetSocketAddress address) {
135   - rateLimitService.onAuthFailure(address);
136   - }
137   -
138   -
139   - @EventListener(ApplicationReadyEvent.class)
140   - @Order(value = 2)
141   - public void onApplicationEvent() {
142   - String cacheName = FastIotConstants.CacheConfigKey.TCP_DATA_COMBINATION_KEY;
143   - //先清理掉数据携带的所有缓存
144   - cacheUtils.invalidateCacheName(cacheName);
145   - try{
146   - //检查是否有数据携带的产品,如果有则进行缓存
147   - List<DeviceProfile> profiles = tkCommonService.findByDataCombinationIsTrue().get();
148   - if(null != profiles && !profiles.isEmpty()){
149   - Map<String, Object> cacheMap = new HashMap<>();
150   - for (DeviceProfile deviceProfile : profiles) {
151   - cacheMap.put(deviceProfile.getTenantId() + "_" +
152   - deviceProfile.getId().toString(),deviceProfile.getProfileData().getTransportConfiguration());
153   - }
154   - cacheUtils.put(cacheName, FastIotConstants.OtherKey.DATA_COMBINATION_KEY,cacheMap);
155   - }
156   - //获取所有启动的脚本,调用对应的脚本eval
157   - tkCommonService.evalAllEnabledScript();
158   - }catch (Exception e){
159   - log.error(ErrorMessage.CACHE_DATA_COMBINATION_FAILED.getMessage());
  155 + schedulerExecutor.schedule(() -> ready = true, timeout, TimeUnit.MILLISECONDS);
  156 + }
  157 +
  158 + @EventListener(ScriptUpdatedEvent.class)
  159 + public void onScriptUpdatedEvent(ScriptUpdatedEvent event) {
  160 + TkDeviceScriptDTO script = event.getScript();
  161 + TenantId tenantId = TenantId.fromUUID(UUID.fromString(script.getTenantId()));
  162 + String content =
  163 + Objects.equals(script.getScriptLanguage(), ScriptLanguage.JS)
  164 + ? script.getConvertJs()
  165 + : script.getConvertTbel();
  166 + evalScript(
  167 + script.getId(),
  168 + ScriptType.valueOf(script.getScriptType()),
  169 + content,
  170 + script.getScriptLanguage(),
  171 + tenantId,
  172 + script.getStatus());
  173 + }
  174 +
  175 + private void evalScript(
  176 + String scriptId,
  177 + ScriptType scriptType,
  178 + String content,
  179 + ScriptLanguage scriptLanguage,
  180 + TenantId tenantId,
  181 + Integer status) {
  182 + String[] argNames = new String[] {"msg", "metadata", "msgType"};
  183 + boolean enabled = status.equals(StatusEnum.ENABLE.getIndex());
  184 + String message = enabled ? "eval" : "release";
  185 + try {
  186 + if (Objects.equals(scriptLanguage, ScriptLanguage.JS)) {
  187 + if (enabled) {
  188 + jsEngine.eval(tenantId, UUID.fromString(scriptId), scriptType, content, argNames).get();
  189 + } else {
  190 + jsEngine.release(UUID.fromString(scriptId));
  191 + }
  192 + }
  193 + if (Objects.equals(scriptLanguage, ScriptLanguage.TBEL)) {
  194 + if (enabled) {
  195 + tbelInvokeService
  196 + .eval(tenantId, UUID.fromString(scriptId), scriptType, content, argNames)
  197 + .get();
  198 + } else {
  199 + tbelInvokeService.release(UUID.fromString(scriptId));
160 200 }
161   - schedulerExecutor.schedule(()->ready=true,timeout, TimeUnit.MILLISECONDS);
  201 + }
  202 + } catch (ExecutionException | InterruptedException e) {
  203 + log.error("脚本{}{}失败", message, scriptId);
162 204 }
  205 + }
163 206 }
... ...
... ... @@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.id.TenantId;
19 19 import org.thingsboard.server.common.data.script.ScriptLanguage;
20 20 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
21 21 import org.thingsboard.server.common.data.yunteng.enums.ProtocolAnalysisEnum;
  22 +import org.thingsboard.server.common.transport.TransportServiceCallback;
22 23 import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
23 24 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
24 25 import org.thingsboard.server.gen.transport.TransportProtos;
... ... @@ -99,7 +100,18 @@ public abstract class TcpDeviceWareSessionContext extends DeviceAwareSessionCont
99 100 TkTcpDeviceProfileTransportConfiguration tcpConfiguration = (TkTcpDeviceProfileTransportConfiguration) transportConfiguration;
100 101 if( tcpConfiguration.getProtocol().equals(ProtocolAnalysisEnum.CUSTOM)){
101 102 this.telemetryScriptId = UUID.fromString(tcpConfiguration.getUpScriptId());
102   - this.scriptLanguage = context.getTkCommonService().getScriptLanguageById(tcpConfiguration.getUpScriptId());
  103 + getContext().getTransportService().process(sessionInfo, TransportProtos.UpScriptProto.newBuilder()
  104 + .setUpScriptId(tcpConfiguration.getUpScriptId()).build(), new TransportServiceCallback<TransportProtos.UpScriptResponseProto>() {
  105 + @Override
  106 + public void onSuccess(TransportProtos.UpScriptResponseProto msg) {
  107 + scriptLanguage = ScriptLanguage.valueOf(msg.getScriptLanguage());
  108 + }
  109 +
  110 + @Override
  111 + public void onError(Throwable e) {
  112 + log.error("通过上行脚本id获取脚本语言失败");
  113 + }
  114 + });
103 115 }
104 116
105 117 }
... ...
... ... @@ -164,7 +164,7 @@ public interface TransportService {
164 164 void createGaugeStats(String openConnections, AtomicInteger connectionsCounter);
165 165
166 166 // Thingskit function:begin
167   - List<TransportProtos.ScriptProto> getScripts(TransportProtos.ScriptProto msg);
  167 + List<TransportProtos.ScriptResponseProto> findAllEnabledScript(TransportProtos.ScriptProto msg);
168 168
169 169 void process(SessionInfoProto sessionInfo, TransportProtos.PostEventMsg msg, TransportServiceCallback<Void> callback,
170 170 String topicName);
... ... @@ -178,5 +178,10 @@ public interface TransportService {
178 178
179 179 void process(DeviceTransportType transportType, TransportProtos.ValidateTcpDeviceTokenRequestMsg msg,
180 180 TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
  181 +
  182 + void process(SessionInfoProto sessionInfoProto,TransportProtos.UpScriptProto msg,TransportServiceCallback<
  183 + TransportProtos.UpScriptResponseProto> callback);
  184 +
  185 + void process(TransportProtos.DataCombinationMsg msg);
181 186 // Thingskit function:end
182 187 }
... ...
... ... @@ -1329,22 +1329,20 @@ public class DefaultTransportService extends TransportActivityManager implements
1329 1329 }
1330 1330
1331 1331 // Thingskit function
1332   - @Override
1333   - public List<TransportProtos.ScriptProto> getScripts(TransportProtos.ScriptProto msg) {
1334   - TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
1335   - new TbProtoQueueMsg<>(
1336   - UUID.randomUUID(),
1337   - TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build());
1338   - try {
1339   - TbProtoQueueMsg<TransportApiResponseMsg> response =
1340   - transportApiRequestTemplate.send(protoMsg).get();
1341   - return response.getValue().getScriptsResponseMsgList();
1342   - } catch (InterruptedException | ExecutionException e) {
1343   - throw new RuntimeException(e);
1344   - }
1345   - }
1346   -
1347   - // thingskit start
  1332 + @Override
  1333 + public List<TransportProtos.ScriptResponseProto> findAllEnabledScript(TransportProtos.ScriptProto msg){
  1334 + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
  1335 + new TbProtoQueueMsg<>(
  1336 + UUID.randomUUID(),
  1337 + TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build());
  1338 + try {
  1339 + TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();
  1340 + return response.getValue().getScriptResponseProtoList();
  1341 + } catch (InterruptedException | ExecutionException e) {
  1342 + throw new RuntimeException(e);
  1343 + }
  1344 + }
  1345 + // thingskit start
1348 1346 @Override
1349 1347 public void process(
1350 1348 TransportProtos.SessionInfoProto sessionInfo,
... ... @@ -1390,5 +1388,23 @@ public class DefaultTransportService extends TransportActivityManager implements
1390 1388 TransportApiRequestMsg.newBuilder().setValidateTcpTokenRequestMsg(msg).build());
1391 1389 doProcess(transportType, protoMsg, callback);
1392 1390 }
  1391 + @Override
  1392 + public void process(TransportProtos.SessionInfoProto sessionInfo,TransportProtos.UpScriptProto msg,TransportServiceCallback<
  1393 + TransportProtos.UpScriptResponseProto> callback){
  1394 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(),
  1395 + TransportApiRequestMsg.newBuilder().setUpScriptRequestMsg(msg).build());
  1396 +
  1397 + AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> {
  1398 + callback.onSuccess(response.getValue().getUpScriptResponseMsg());
  1399 + }, callback::onError, transportCallbackExecutor);
  1400 + }
  1401 +
  1402 + @Override
  1403 + public void process(TransportProtos.DataCombinationMsg msg) {
  1404 + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
  1405 + new TbProtoQueueMsg<>(
  1406 + UUID.randomUUID(),TransportApiRequestMsg.newBuilder().setDataCombinationRequest(msg).build());
  1407 + transportApiRequestTemplate.send(protoMsg);
  1408 + }
1393 1409 // thingskit end
1394 1410 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.impl;
2 2
3   -import com.google.common.util.concurrent.ListenableFuture;
4 3 import lombok.RequiredArgsConstructor;
5 4 import lombok.extern.slf4j.Slf4j;
6 5 import org.springframework.stereotype.Service;
7   -import org.thingsboard.server.common.data.DeviceProfile;
8   -import org.thingsboard.server.common.data.StringUtils;
9   -import org.thingsboard.server.common.data.script.ScriptLanguage;
10 6 import org.thingsboard.server.common.data.yunteng.common.TkCommonService;
11   -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
12 7 import org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO;
13   -import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO;
14   -import org.thingsboard.server.dao.device.DeviceProfileService;
15 8 import org.thingsboard.server.dao.yunteng.mapper.SysDictItemMapper;
16   -import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService;
17   -
18   -import java.util.List;
19   -import java.util.Optional;
20   -import java.util.concurrent.CompletableFuture;
21 9
22 10 @Slf4j
23 11 @Service
24 12 @RequiredArgsConstructor
25 13 public class TkCommonServiceImpl implements TkCommonService {
26 14
27   - private final SysDictItemMapper sysDictItemMapper;
28   - private final DeviceProfileService deviceProfileService;
29   - private final TkDeviceScriptService tkDeviceScriptService;
30   - @Override
31   - public SysDictItemDTO getDictValueByCodeAndText(String dictCode, String codeValue) {
32   - return sysDictItemMapper.getDictValueByCodeAndText(dictCode, codeValue);
33   - }
34   -
35   - public ListenableFuture<List<DeviceProfile>> findByDataCombinationIsTrue(){
36   - return deviceProfileService.findByDataCombinationIsTrue();
37   - }
38   -
39   - @Override
40   - public ScriptLanguage getScriptLanguageById(String scriptId) {
41   - return tkDeviceScriptService.findScriptLanguageById(scriptId);
42   - }
  15 + private final SysDictItemMapper sysDictItemMapper;
43 16
44   - @Override
45   - public void evalAllEnabledScript() {
46   - List<TkDeviceScriptDTO> scriptDTOS = tkDeviceScriptService.findAllEnabledScript();
47   - if(null != scriptDTOS && !scriptDTOS.isEmpty()){
48   - for (TkDeviceScriptDTO scriptDTO : scriptDTOS){
49   - try {
50   - tkDeviceScriptService.eval(scriptDTO.getTenantId(),scriptDTO.getId());
51   - }catch (Exception e){
52   - log.error(String.format(ErrorMessage.SCRIPT_EVAL_FAILED.getMessage(),scriptDTO.getTenantId(),scriptDTO.getId(),e.getMessage()));
53   - }
54   - }
  17 + @Override
  18 + public SysDictItemDTO getDictValueByCodeAndText(String dictCode, String codeValue) {
  19 + return sysDictItemMapper.getDictValueByCodeAndText(dictCode, codeValue);
55 20 }
56   - }
57 21 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.impl;
2 2
3   -
4 3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
5 4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 5 import com.baomidou.mybatisplus.core.metadata.IPage;
... ... @@ -12,7 +11,10 @@ import org.springframework.transaction.annotation.Transactional;
12 11 import org.thingsboard.script.api.ScriptType;
13 12 import org.thingsboard.script.api.js.JsInvokeService;
14 13 import org.thingsboard.script.api.tbel.TbelInvokeService;
  14 +import org.thingsboard.server.cluster.TbClusterService;
  15 +import org.thingsboard.server.common.data.DeviceProfile;
15 16 import org.thingsboard.server.common.data.device.profile.TkTcpDeviceProfileTransportConfiguration;
  17 +import org.thingsboard.server.common.data.id.DeviceProfileId;
16 18 import org.thingsboard.server.common.data.id.EntityId;
17 19 import org.thingsboard.server.common.data.id.TenantId;
18 20 import org.thingsboard.server.common.data.script.ScriptLanguage;
... ... @@ -26,6 +28,7 @@ import org.thingsboard.server.common.data.yunteng.enums.*;
26 28 import org.thingsboard.server.common.data.yunteng.utils.ByteUtils;
27 29 import org.thingsboard.server.common.data.yunteng.utils.CrcUtils;
28 30 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
  31 +import org.thingsboard.server.dao.device.DeviceProfileService;
29 32 import org.thingsboard.server.dao.exception.DataValidationException;
30 33 import org.thingsboard.server.dao.yunteng.entities.TkDeviceScriptEntity;
31 34 import org.thingsboard.server.dao.yunteng.mapper.TkDeviceScriptMapper;
... ... @@ -48,6 +51,9 @@ public class TkDeviceScriptServiceImpl
48 51 private final TkDeviceService tkDeviceService;
49 52 private final JsInvokeService jsInvokeService;
50 53 private final TbelInvokeService tbelInvokeService;
  54 + private final TbClusterService tbClusterService;
  55 + private final DeviceProfileService deviceProfileService;
  56 + private final TkTenantService tenantService;
51 57
52 58 @Override
53 59 public boolean validateFormdata(TkDeviceScriptDTO scriptDTO, boolean created) {
... ... @@ -107,27 +113,31 @@ public class TkDeviceScriptServiceImpl
107 113 }
108 114
109 115 @Override
110   - public List<TkDeviceScriptDTO> getScriptes(){
  116 + public List<TkDeviceScriptDTO> getScriptes() {
111 117 LambdaQueryWrapper<TkDeviceScriptEntity> queryWrapper =
112 118 new QueryWrapper<TkDeviceScriptEntity>().lambda();
113 119 queryWrapper.eq(TkDeviceScriptEntity::getStatus, StatusEnum.ENABLE.getIndex());
114 120 List<TkDeviceScriptEntity> result = baseMapper.selectList(queryWrapper);
115 121 return result.stream()
116   - .map(item -> item.getDTO(TkDeviceScriptDTO.class))
117   - .collect(Collectors.toList());
  122 + .map(item -> item.getDTO(TkDeviceScriptDTO.class))
  123 + .collect(Collectors.toList());
118 124 }
119 125
120 126 @Override
121 127 public TkDeviceScriptDTO insertOrUpdate(TkDeviceScriptDTO deviceDTO) {
122   - //判断脚本的内容
123   - if(null == deviceDTO.getScriptLanguage()){
  128 + // 判断脚本的内容
  129 + if (null == deviceDTO.getScriptLanguage()) {
124 130 deviceDTO.setScriptLanguage(ScriptLanguage.JS);
125 131 }
126   - if(Objects.equals(ScriptLanguage.JS,deviceDTO.getScriptLanguage()) && StringUtils.isEmpty(deviceDTO.getConvertJs())){
127   - throw new DataValidationException(String.format(ErrorMessage.SCRIPT_CONTENT_IS_EMPTY.getMessage(),ScriptLanguage.JS));
  132 + if (Objects.equals(ScriptLanguage.JS, deviceDTO.getScriptLanguage())
  133 + && StringUtils.isEmpty(deviceDTO.getConvertJs())) {
  134 + throw new DataValidationException(
  135 + String.format(ErrorMessage.SCRIPT_CONTENT_IS_EMPTY.getMessage(), ScriptLanguage.JS));
128 136 }
129   - if(Objects.equals(ScriptLanguage.TBEL,deviceDTO.getScriptLanguage())&& StringUtils.isEmpty(deviceDTO.getConvertTbel())){
130   - throw new DataValidationException(String.format(ErrorMessage.SCRIPT_CONTENT_IS_EMPTY.getMessage(),ScriptLanguage.TBEL));
  137 + if (Objects.equals(ScriptLanguage.TBEL, deviceDTO.getScriptLanguage())
  138 + && StringUtils.isEmpty(deviceDTO.getConvertTbel())) {
  139 + throw new DataValidationException(
  140 + String.format(ErrorMessage.SCRIPT_CONTENT_IS_EMPTY.getMessage(), ScriptLanguage.TBEL));
131 141 }
132 142 if (StringUtils.isBlank(deviceDTO.getId())) {
133 143 return insert(deviceDTO);
... ... @@ -139,15 +149,17 @@ public class TkDeviceScriptServiceImpl
139 149 @Override
140 150 public void checkDeviceScriptes(String tenantId, Set<String> ids) {
141 151 // check if ids bind to device
142   - if(ids == null || ids.isEmpty()){
  152 + if (ids == null || ids.isEmpty()) {
143 153 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
144 154 }
145   - for(String id : ids){
146   - List<DeviceProfileDTO> profileList = tkDeviceProfileService.findDeviceProfileByScriptId(tenantId,id);
147   - if(null != profileList && !profileList.isEmpty()){
148   -
149   - throw new TkDataValidationException(String.format(ErrorMessage.PROJECT_USED_SCRIPT.getMessage(),
150   - profileList.get(0).getName()));
  155 + for (String id : ids) {
  156 + List<DeviceProfileDTO> profileList =
  157 + tkDeviceProfileService.findDeviceProfileByScriptId(tenantId, id);
  158 + if (null != profileList && !profileList.isEmpty()) {
  159 +
  160 + throw new TkDataValidationException(
  161 + String.format(
  162 + ErrorMessage.PROJECT_USED_SCRIPT.getMessage(), profileList.get(0).getName()));
151 163 }
152 164 }
153 165 }
... ... @@ -174,9 +186,13 @@ public class TkDeviceScriptServiceImpl
174 186 ModelConstants.TablePropertyMapping.UPDATER,
175 187 ModelConstants.TablePropertyMapping.CREATE_TIME,
176 188 ModelConstants.TablePropertyMapping.UPDATE_TIME);
177   - profile.setScriptType(null == deviceDTO.getScriptType() ?ScriptType.TRANSPORT_TCP_UP:ScriptType.valueOf(deviceDTO.getScriptType()));
  189 + profile.setScriptType(
  190 + null == deviceDTO.getScriptType()
  191 + ? ScriptType.TRANSPORT_TCP_UP
  192 + : ScriptType.valueOf(deviceDTO.getScriptType()));
178 193 baseMapper.insert(profile);
179   - return profile.getDTO(TkDeviceScriptDTO.class);
  194 + deviceDTO.setId(profile.getId());
  195 + return deviceDTO;
180 196 }
181 197
182 198 private TkDeviceScriptDTO update(TkDeviceScriptDTO deviceDTO) {
... ... @@ -192,9 +208,35 @@ public class TkDeviceScriptServiceImpl
192 208 ModelConstants.TablePropertyMapping.CREATE_TIME,
193 209 ModelConstants.TablePropertyMapping.UPDATE,
194 210 ModelConstants.TablePropertyMapping.UPDATE_TIME);
  211 + String tenantId = deviceDTO.getTenantId();
  212 + String scriptId = deviceDTO.getId();
  213 + Optional<TkDeviceScriptDTO> optional = getDeviceScript(tenantId, scriptId);
  214 + if (optional.isPresent()) {
  215 + TkDeviceScriptDTO deviceScriptDTO = optional.get();
  216 + // 如果脚本语言有更新,且有正在使用的产品,则需通知产品进行变更(脚本语言进行变更)
  217 + if (!Objects.equals(deviceScriptDTO.getScriptLanguage(), deviceDTO.getScriptLanguage())) {
  218 + // 查找正在使用的产品
  219 + List<DeviceProfileDTO> profiles =
  220 + tkDeviceProfileService.findDeviceProfileByScriptId(tenantId, scriptId);
  221 + if (null != profiles && !profiles.isEmpty()) {
  222 + for (DeviceProfileDTO dto : profiles) {
  223 + DeviceProfileId deviceProfileId =
  224 + new DeviceProfileId(UUID.fromString(dto.getTbProfileId()));
  225 + DeviceProfile deviceProfile =
  226 + deviceProfileService.findDeviceProfileById(
  227 + TenantId.fromUUID(UUID.fromString(tenantId)), deviceProfileId);
  228 + if (null != deviceProfile) {
  229 + tbClusterService.onDeviceProfileChange(deviceProfile, null);
  230 + }
  231 + }
  232 + }
  233 + }
  234 + }
195 235 baseMapper.updateById(device);
196 236 device.setTenantId(deviceDTO.getTenantId());
197   - return device.getDTO(TkDeviceScriptDTO.class);
  237 + TkDeviceScriptDTO updateScriptDTO = device.getDTO(TkDeviceScriptDTO.class);
  238 + updateScriptDTO.setScriptType(deviceDTO.getScriptType());
  239 + return updateScriptDTO;
198 240 }
199 241
200 242 @Override
... ... @@ -202,12 +244,23 @@ public class TkDeviceScriptServiceImpl
202 244 LambdaQueryWrapper<TkDeviceScriptEntity> queryWrapper =
203 245 new QueryWrapper<TkDeviceScriptEntity>()
204 246 .lambda()
205   - .eq(TkDeviceScriptEntity::getId, id).and(a -> a
206   - .eq(TkDeviceScriptEntity::getTenantId, tenantId).or(b->b.eq(TkDeviceScriptEntity::getTenantId,EntityId.NULL_UUID.toString())));
  247 + .eq(TkDeviceScriptEntity::getId, id)
  248 + .and(
  249 + a ->
  250 + a.eq(TkDeviceScriptEntity::getTenantId, tenantId)
  251 + .or(
  252 + b ->
  253 + b.eq(
  254 + TkDeviceScriptEntity::getTenantId,
  255 + EntityId.NULL_UUID.toString())));
207 256 TkDeviceScriptEntity profile = baseMapper.selectOne(queryWrapper);
208 257 return Optional.ofNullable(profile)
209 258 .map(
210   - entity -> entity.getDTO(TkDeviceScriptDTO.class));
  259 + entity -> {
  260 + TkDeviceScriptDTO dto = entity.getDTO(TkDeviceScriptDTO.class);
  261 + dto.setScriptType(entity.getScriptType().name());
  262 + return dto;
  263 + });
211 264 }
212 265
213 266 @Override
... ... @@ -224,11 +277,9 @@ public class TkDeviceScriptServiceImpl
224 277 .map(Object::toString)
225 278 .orElse(null);
226 279 String name = Optional.ofNullable(queryMap.get("name")).map(Object::toString).orElse(null);
227   - LocalDateTime startTime =
228   - (LocalDateTime) queryMap.get("startTime");
229   - LocalDateTime endTime =
230   - (LocalDateTime) queryMap.get("endTime");
231   - Integer status = null != queryMap.get("status") ? (Integer)queryMap.get("status") : null;
  280 + LocalDateTime startTime = (LocalDateTime) queryMap.get("startTime");
  281 + LocalDateTime endTime = (LocalDateTime) queryMap.get("endTime");
  282 + Integer status = null != queryMap.get("status") ? (Integer) queryMap.get("status") : null;
232 283 Set<String> scriptIds = null;
233 284 if (!isTenantAdmin && StringUtils.isNotEmpty(customerId)) {
234 285 scriptIds = getCustomerScripts(customerId, tenantId);
... ... @@ -240,7 +291,7 @@ public class TkDeviceScriptServiceImpl
240 291 new QueryWrapper<TkDeviceScriptEntity>()
241 292 .lambda()
242 293 .eq(TkDeviceScriptEntity::getTenantId, tenantId)
243   - .eq(null != status,TkDeviceScriptEntity::getStatus,status)
  294 + .eq(null != status, TkDeviceScriptEntity::getStatus, status)
244 295 .like(StringUtils.isNotEmpty(name), TkDeviceScriptEntity::getName, name)
245 296 .and(
246 297 null != startTime && null != endTime,
... ... @@ -258,14 +309,15 @@ public class TkDeviceScriptServiceImpl
258 309 }
259 310
260 311 @Override
261   - public List<TkDeviceScriptDTO> findDeviceScript(String tenantId, ScriptType scriptType,DeviceTypeEnum serviceType) {
  312 + public List<TkDeviceScriptDTO> findDeviceScript(
  313 + String tenantId, ScriptType scriptType, DeviceTypeEnum serviceType) {
262 314 LambdaQueryWrapper<TkDeviceScriptEntity> queryWrapper =
263 315 new QueryWrapper<TkDeviceScriptEntity>()
264 316 .lambda()
265   - .eq(TkDeviceScriptEntity::getStatus,StatusEnum.ENABLE.getIndex())
266   - .eq(scriptType!=null,TkDeviceScriptEntity::getScriptType, scriptType)
267   - .eq(serviceType!=null,TkDeviceScriptEntity::getServiceType,serviceType)
268   - .eq(TkDeviceScriptEntity::getTenantId, tenantId);
  317 + .eq(TkDeviceScriptEntity::getStatus, StatusEnum.ENABLE.getIndex())
  318 + .eq(scriptType != null, TkDeviceScriptEntity::getScriptType, scriptType)
  319 + .eq(serviceType != null, TkDeviceScriptEntity::getServiceType, serviceType)
  320 + .eq(TkDeviceScriptEntity::getTenantId, tenantId);
269 321 return baseMapper.selectList(queryWrapper).stream()
270 322 .map(item -> item.getDTO(TkDeviceScriptDTO.class))
271 323 .collect(Collectors.toList());
... ... @@ -289,15 +341,19 @@ public class TkDeviceScriptServiceImpl
289 341 .map(DeviceDTO::getDeviceProfileId)
290 342 .collect(Collectors.toList());
291 343 List<DeviceProfileDTO> deviceProfileDTOList =
292   - tkDeviceProfileService.findDeviceProfileByIds(tenantId, deviceProfiles, TransportTypeEnum.TCP);
  344 + tkDeviceProfileService.findDeviceProfileByIds(
  345 + tenantId, deviceProfiles, TransportTypeEnum.TCP);
293 346 return Optional.ofNullable(deviceProfileDTOList)
294 347 .map(
295   - deviceProfileDTOS ->{
  348 + deviceProfileDTOS -> {
296 349 Set<String> tcpScriptes = new HashSet<>();
297   - deviceProfileDTOS.forEach(p->{
298   - TkTcpDeviceProfileTransportConfiguration config = (TkTcpDeviceProfileTransportConfiguration) p.getProfileData().getTransportConfiguration();
299   - tcpScriptes.add(config.getUpScriptId());
300   - });
  350 + deviceProfileDTOS.forEach(
  351 + p -> {
  352 + TkTcpDeviceProfileTransportConfiguration config =
  353 + (TkTcpDeviceProfileTransportConfiguration)
  354 + p.getProfileData().getTransportConfiguration();
  355 + tcpScriptes.add(config.getUpScriptId());
  356 + });
301 357 return tcpScriptes;
302 358 })
303 359 .orElse(null);
... ... @@ -315,113 +371,154 @@ public class TkDeviceScriptServiceImpl
315 371 String functionCode = config.getMethod();
316 372 result.append(functionCode);
317 373 String addrStr = ByteUtils.integerToHex(config.getRegisterAddress());
318   - result.append(addrStr.substring(addrStr.length()-4));
  374 + result.append(addrStr.substring(addrStr.length() - 4));
319 375
320 376 List<Integer> values = config.getRegisterValues();
321   - Integer registerNum = config.getRegisterNumber()==null?1:config.getRegisterNumber();
322   - if(values ==null || values.isEmpty()){
323   - //读寄存器数据
  377 + Integer registerNum = config.getRegisterNumber() == null ? 1 : config.getRegisterNumber();
  378 + if (values == null || values.isEmpty()) {
  379 + // 读寄存器数据
324 380 result.append(modelHex(registerNum));
325   - }else if(values.size() == 1 &&(TkModBusFunctionCode.WRITE_ONE_COIL.getCode().equals(functionCode) || TkModBusFunctionCode.WRITE_ONE_REGISTER.getCode().equals(functionCode) )){
326   - //单个写入
  381 + } else if (values.size() == 1
  382 + && (TkModBusFunctionCode.WRITE_ONE_COIL.getCode().equals(functionCode)
  383 + || TkModBusFunctionCode.WRITE_ONE_REGISTER.getCode().equals(functionCode))) {
  384 + // 单个写入
327 385 result.append(modelHex(values.get(0)));
328   - }else{
329   - //多个写入
  386 + } else {
  387 + // 多个写入
330 388 result.append(modelHex(registerNum));
331   - result.append(multData(functionCode,values));
  389 + result.append(multData(functionCode, values));
332 390 }
333   - result.append(CrcUtils.getSendBuf(config.getCrc(),result.toString()));
334   -
  391 + result.append(CrcUtils.getSendBuf(config.getCrc(), result.toString()));
335 392
336 393 return result.toString();
337 394 }
338 395
339 396 @Override
340   - public void eval(String tenantId, String scriptId) throws ExecutionException, InterruptedException {
341   - TkDeviceScriptEntity entity = baseMapper.selectOne(new LambdaQueryWrapper<TkDeviceScriptEntity>()
342   - .eq(TkDeviceScriptEntity::getId,scriptId));
343   - if(null == entity){
  397 + public void eval(String tenantId, String scriptId)
  398 + throws ExecutionException, InterruptedException {
  399 + TkDeviceScriptEntity entity =
  400 + baseMapper.selectOne(
  401 + new LambdaQueryWrapper<TkDeviceScriptEntity>()
  402 + .eq(TkDeviceScriptEntity::getId, scriptId));
  403 + if (null == entity) {
344 404 throw new TkDataValidationException("脚本不存在");
345 405 }
346 406 TenantId tbTenantId = new TenantId(UUID.fromString(tenantId));
347 407 UUID scriptUUID = null;
348   - String[] argNames = new String[]{"msg", "metadata", "msgType"};
349   - if(Objects.equals(entity.getScriptLanguage(),ScriptLanguage.JS)){
350   - scriptUUID= jsInvokeService.eval(tbTenantId,UUID.fromString(scriptId),entity.getScriptType(),
351   - entity.getConvertJs(),argNames).get();
  408 + String[] argNames = new String[] {"msg", "metadata", "msgType"};
  409 + if (Objects.equals(entity.getScriptLanguage(), ScriptLanguage.JS)) {
  410 + scriptUUID =
  411 + jsInvokeService
  412 + .eval(
  413 + tbTenantId,
  414 + UUID.fromString(scriptId),
  415 + entity.getScriptType(),
  416 + entity.getConvertJs(),
  417 + argNames)
  418 + .get();
352 419 }
353   - if(Objects.equals(entity.getScriptLanguage(),ScriptLanguage.TBEL)){
354   - scriptUUID = tbelInvokeService.eval(tbTenantId,UUID.fromString(scriptId),entity.getScriptType(),
355   - entity.getConvertTbel(),argNames).get();
  420 + if (Objects.equals(entity.getScriptLanguage(), ScriptLanguage.TBEL)) {
  421 + scriptUUID =
  422 + tbelInvokeService
  423 + .eval(
  424 + tbTenantId,
  425 + UUID.fromString(scriptId),
  426 + entity.getScriptType(),
  427 + entity.getConvertTbel(),
  428 + argNames)
  429 + .get();
356 430 }
357 431 System.out.printf("UUID:" + scriptUUID.toString());
358 432 }
359 433
360 434 @Override
361 435 public void release(String tenantId, String scriptId) {
362   - TkDeviceScriptEntity entity = baseMapper.selectOne(new LambdaQueryWrapper<TkDeviceScriptEntity>()
363   - .eq(TkDeviceScriptEntity::getId,scriptId));
364   - if(null == entity){
  436 + TkDeviceScriptEntity entity =
  437 + baseMapper.selectOne(
  438 + new LambdaQueryWrapper<TkDeviceScriptEntity>()
  439 + .eq(TkDeviceScriptEntity::getId, scriptId));
  440 + if (null == entity) {
365 441 throw new TkDataValidationException("脚本不存在");
366 442 }
367   - if(Objects.equals(entity.getScriptLanguage(),ScriptLanguage.JS)){
  443 + if (Objects.equals(entity.getScriptLanguage(), ScriptLanguage.JS)) {
368 444 jsInvokeService.release(UUID.fromString(scriptId));
369 445 }
370   - if(Objects.equals(entity.getScriptLanguage(),ScriptLanguage.TBEL)){
  446 + if (Objects.equals(entity.getScriptLanguage(), ScriptLanguage.TBEL)) {
371 447 tbelInvokeService.release(UUID.fromString(scriptId));
372 448 }
373 449 }
374 450
375 451 @Override
376 452 public ScriptLanguage findScriptLanguageById(String scriptId) {
377   - return Optional.ofNullable(baseMapper.selectById(scriptId)).map(entity->entity.getScriptLanguage()).orElse(null);
  453 + return Optional.ofNullable(baseMapper.selectById(scriptId))
  454 + .map(entity -> entity.getScriptLanguage())
  455 + .orElse(null);
378 456 }
379 457
380 458 @Override
381 459 public List<TkDeviceScriptDTO> findAllEnabledScript() {
382   - List<TkDeviceScriptEntity> entities = baseMapper.selectList(new LambdaQueryWrapper<TkDeviceScriptEntity>().
383   - eq(TkDeviceScriptEntity::getStatus,StatusEnum.ENABLE.getIndex())
384   - .ne(TkDeviceScriptEntity::getTenantId,EntityId.NULL_UUID.toString()));
385   - return Optional.ofNullable(entities).map(objects-> objects.stream().map(entity->entity.getDTO(TkDeviceScriptDTO.class))
386   - .collect(Collectors.toList())).orElse(null);
  460 + //找到所有的租户
  461 + List<TenantDTO> tenants = tenantService.getAllTenant();
  462 + if(null == tenants || tenants.isEmpty()){
  463 + return null;
  464 + }
  465 + List<String> tenantIds = tenants.stream().map(entity->entity.getTenantId()).collect(Collectors.toList());
  466 + List<TkDeviceScriptEntity> entities =
  467 + baseMapper.selectList(
  468 + new LambdaQueryWrapper<TkDeviceScriptEntity>()
  469 + .eq(TkDeviceScriptEntity::getStatus, StatusEnum.ENABLE.getIndex())
  470 + .in(TkDeviceScriptEntity::getTenantId, tenantIds));
  471 + return Optional.ofNullable(entities)
  472 + .map(
  473 + objects ->
  474 + objects.stream()
  475 + .map(
  476 + entity -> {
  477 + TkDeviceScriptDTO scriptDTO = entity.getDTO(TkDeviceScriptDTO.class);
  478 + scriptDTO.setScriptType(entity.getScriptType().name());
  479 + return scriptDTO;
  480 + })
  481 + .collect(Collectors.toList()))
  482 + .orElse(null);
387 483 }
388 484
389   - private String modelHex(Integer max){
  485 + private String modelHex(Integer max) {
390 486 String addrStr = ByteUtils.integerToHex(max);
391   - return addrStr.substring(addrStr.length()-4);
  487 + return addrStr.substring(addrStr.length() - 4);
392 488 }
393 489
394   - private String dataLength(Integer max){
  490 + private String dataLength(Integer max) {
395 491 String addrStr = ByteUtils.integerToHex(max);
396   - return addrStr.substring(addrStr.length()-2);
  492 + return addrStr.substring(addrStr.length() - 2);
397 493 }
398   - private String multData(String functionCode,List<Integer>datas){
  494 +
  495 + private String multData(String functionCode, List<Integer> datas) {
399 496 StringBuilder dataStr = new StringBuilder();
400 497 int dataLength = datas.size();
401   - if(TkModBusFunctionCode.WRITE_MANY_REGISTER.getCode().equals(functionCode)){
402   - dataStr.append(dataLength(dataLength*2));
403   - for(Integer item: datas){
  498 + if (TkModBusFunctionCode.WRITE_MANY_REGISTER.getCode().equals(functionCode)) {
  499 + dataStr.append(dataLength(dataLength * 2));
  500 + for (Integer item : datas) {
404 501 dataStr.append(modelHex(item));
405 502 }
406   - }else{
  503 + } else {
407 504
408   - int residue = dataLength%8;
409   - int num = dataLength/8;
410   - dataStr.append(dataLength(residue == 0 ?num:num+1));
  505 + int residue = dataLength % 8;
  506 + int num = dataLength / 8;
  507 + dataStr.append(dataLength(residue == 0 ? num : num + 1));
411 508
412   - Integer wordVal=0;
413   - for(int dataIndex=0,wordIndex=0;dataIndex<dataLength;dataIndex++){
  509 + Integer wordVal = 0;
  510 + for (int dataIndex = 0, wordIndex = 0; dataIndex < dataLength; dataIndex++) {
414 511 Integer itemVal = datas.get(dataIndex);
415   - if(itemVal == 1){
  512 + if (itemVal == 1) {
416 513 byte one = 1;
417   - one<<=wordIndex;
418   - wordVal+=one;
  514 + one <<= wordIndex;
  515 + wordVal += one;
419 516 }
420   - if(dataIndex%8==7 || dataLength == dataIndex+1){
  517 + if (dataIndex % 8 == 7 || dataLength == dataIndex + 1) {
421 518 dataStr.append(ByteUtils.byteToHex(wordVal.byteValue()));
422   - wordVal=0;
423   - wordIndex=0;
424   - }else{
  519 + wordVal = 0;
  520 + wordIndex = 0;
  521 + } else {
425 522 wordIndex++;
426 523 }
427 524 }
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.gbt28181;
17 17
18 18 import org.springframework.boot.SpringApplication;
19 19 import org.springframework.boot.SpringBootConfiguration;
  20 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
20 21 import org.springframework.context.annotation.ComponentScan;
21 22 import org.springframework.scheduling.annotation.EnableAsync;
22 23 import org.springframework.scheduling.annotation.EnableScheduling;
... ... @@ -26,6 +27,7 @@ import java.util.Arrays;
26 27 @SpringBootConfiguration
27 28 @EnableAsync
28 29 @EnableScheduling
  30 +@EnableAutoConfiguration
29 31 @ComponentScan({"org.thingsboard.server.gbt28181", "org.thingsboard.server.common", "org.thingsboard.server.transport.gbt28181", "org.thingsboard.server.queue", "org.thingsboard.server.cache"})
30 32 public class ThingsboardGBT28181TransportApplication {
31 33
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.tcp;
17 17
18 18 import org.springframework.boot.SpringApplication;
19 19 import org.springframework.boot.SpringBootConfiguration;
  20 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
20 21 import org.springframework.context.annotation.ComponentScan;
21 22 import org.springframework.scheduling.annotation.EnableAsync;
22 23 import org.springframework.scheduling.annotation.EnableScheduling;
... ... @@ -26,7 +27,8 @@ import java.util.Arrays;
26 27 @SpringBootConfiguration
27 28 @EnableAsync
28 29 @EnableScheduling
29   -@ComponentScan({"org.thingsboard.server.tcp", "org.thingsboard.server.common", "org.thingsboard.server.transport.tcp", "org.thingsboard.server.transport.udp", "org.thingsboard.server.queue", "org.thingsboard.server.cache"})
  30 +@EnableAutoConfiguration
  31 +@ComponentScan({"org.thingsboard.server.tcp", "org.thingsboard.server.common", "org.thingsboard.server.transport.tcp", "org.thingsboard.server.queue", "org.thingsboard.server.cache","org.thingsboard.script.api"})
30 32 public class ThingsboardTcpTransportApplication {
31 33
32 34 private static final String SPRING_CONFIG_NAME_KEY = "--spring.config.name";
... ...