From a1c880c476327032fe174af8c80d6f78a590dae9 Mon Sep 17 00:00:00 2001 From: wjc <1243177876@qq.com> Date: 星期五, 07 二月 2025 16:35:22 +0800 Subject: [PATCH] Merge branch '1.5.1' into dev --- sdk/src/main/java/com/hdl/sdk/link/core/connect/HDLConnectHelper.java | 564 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 564 insertions(+), 0 deletions(-) diff --git a/sdk/src/main/java/com/hdl/sdk/link/core/connect/HDLConnectHelper.java b/sdk/src/main/java/com/hdl/sdk/link/core/connect/HDLConnectHelper.java new file mode 100644 index 0000000..bd41479 --- /dev/null +++ b/sdk/src/main/java/com/hdl/sdk/link/core/connect/HDLConnectHelper.java @@ -0,0 +1,564 @@ +package com.hdl.sdk.link.core.connect; + +import android.text.TextUtils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.hdl.link.error.ErrorUtils; +import com.hdl.link.error.HDLLinkCode; +import com.hdl.sdk.link.common.event.EventDispatcher; +import com.hdl.sdk.link.common.event.EventListener; +import com.hdl.sdk.link.common.utils.LogUtils; +import com.hdl.sdk.link.common.utils.ThreadToolUtils; +import com.hdl.sdk.link.core.bean.BusProResponse; +import com.hdl.sdk.link.core.bean.LinkRequest; +import com.hdl.sdk.link.core.bean.LinkResponse; +import com.hdl.sdk.link.core.bean.ModbusResponse; +import com.hdl.sdk.link.core.bean.RealLinkResponse; +import com.hdl.sdk.link.core.bean.ZigbeeResponse; +import com.hdl.sdk.link.core.bean.gateway.GatewayBean; +import com.hdl.sdk.link.core.config.HDLLinkConfig; +import com.hdl.sdk.link.core.utils.ByteUtils; +import com.hdl.sdk.link.core.utils.EncryptUtil; +import com.hdl.sdk.link.core.utils.JsonUtils; +import com.hdl.sdk.link.core.utils.mqtt.MqttRecvClient; +import com.hdl.sdk.link.gateway.HDLLinkLocalGateway; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by Tong on 2021/11/11. + */ +public class HDLConnectHelper { + + private static final String TAG="HDLConnectHelper"; + private static final Long DEF_SEND_TIMEOUT = 8000L; + private static final int DEF_MAX_RETRY = 1;//鏈�澶ч噸鍙戞暟 + private static final int DEF_SEND_ONE = 1; + private static final int TCP_PORT = 8586; + private static final int UDP_PORT = 8585; + + private final Long sendAwaitTime; + private final int maxRetry; + + /** + * 鏄惁tcp鍙戦�佺被鍨� + */ + private boolean isTcp; + /** + * 璁惧mac + */ + private String mac; + /** + * 鍙戦�佺殑鐩爣IP + */ + private String ipAddress; + /** + * 鍙戦�佺殑鐩爣鍦板潃 + */ + private int port; + private final LinkRequest linkRequest; + private final EventListener eventListener; + + private final AtomicInteger sendNumber = new AtomicInteger(0); + + private final AtomicBoolean isSend = new AtomicBoolean(false); + + private HdlSocketListener listener; + + private static ScheduledExecutorService scheduledExecutorService; + + private ScheduledFuture<?> scheduledFuture; + + private String replyTopic; + + private boolean useSubThread=false; + + public interface HdlSocketListener { + void onSucceed(Object msg); + + void onFailure(HDLLinkCode hdlLinkCode); + } + + public HDLConnectHelper(Long sendAwaitTime, int maxRetry, String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp) { + this(sendAwaitTime,maxRetry,ipAddress,port,linkRequest,listener,isTcp,false); + } + /** + * 鍙戦�乁DP鎴栬�匱CP鏁版嵁 + * + * @param sendAwaitTime 姣忔鍙戦�佺瓑寰呮椂闂� + * @param maxRetry 閲嶈瘯娆℃暟 + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param port 鍙戦�佺洰鏍囩鍙� + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(Long sendAwaitTime, int maxRetry, String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp,boolean useSubThread) { + this.sendAwaitTime = sendAwaitTime; + this.maxRetry = maxRetry; + this.ipAddress = ipAddress; + this.port = port; + this.linkRequest = linkRequest; + this.replyTopic = linkRequest.getReplyTopic(); + this.listener = listener; + this.isTcp = isTcp; + this.useSubThread=useSubThread; + + + eventListener = new EventListener() { + @Override + public void onMessage(Object object) { + isSend.set(true); + try { + if (object instanceof LinkResponse) {//杩欎釜鏄吋瀹逛互鍓嶄娇鐢ㄤ富棰樺仛涓哄洖璋冪殑鏂瑰紡锛屽悗缁彲浠ヤ笉闇�瑕佷娇鐢紝link杩樻槸鐢ㄤ俊鎭痠d鍚堢悊浜� + LinkResponse linkResponse = (LinkResponse) object; + JSONObject jsonObject = JSON.parseObject(linkResponse.getData()); + String id = null; + Integer code=null; + if(jsonObject!=null) { + id = jsonObject.getString("id"); + code = jsonObject.getInteger("code"); + } + /** + * 鍙兘杩斿洖code灞炴�у彲鑳芥病鏈� 娌℃湁鐨勮瘽鐩存帴鎴愬姛 鏈夌殑璇濆彧鏈�200鎵嶄細鎴愬姛 + */ + if (code == null || code.intValue() == 200 || code.intValue() == 0) { + notifySucceed(object); + } else { + notifyFailure(ErrorUtils.getByCode(code)); + } + } else if (object instanceof ZigbeeResponse) { + notifySucceed(object); + } else if (object instanceof ModbusResponse) { + notifySucceed(object); + } else if (object instanceof BusProResponse) { + notifySucceed(object); + } else if(object instanceof RealLinkResponse){ + //鐪熷疄鐨刲ink鏁版嵁锛屼笉鍖呭惈閫忎紶鐨勫師鐢熸暟鎹� + notifySucceed(object); + } + else { + notifyFailure(new HDLLinkCode(HDLLinkCode.HDL_OBJECT_NOT_SUPPORT.getCode(), "Object Name:" + object)); + } + } catch (Exception e) { + notifyFailure(new HDLLinkCode(HDLLinkCode.HDL_APPLICATION_CODE.getCode(), e.getMessage())); + } + } + }; + //娉ㄥ唽鐩戝惉 + registerListener(); + } + + /** + * 鍙戦�乁DP鎴栬�匱CP鏁版嵁(鍙傛暟鏈塵ac) + * + * @param sendAwaitTime 姣忔鍙戦�佺瓑寰呮椂闂� + * @param maxRetry 閲嶈瘯娆℃暟 + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param port 鍙戦�佺洰鏍囩鍙� + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + * @param mac 璁惧mac + */ + public HDLConnectHelper(Long sendAwaitTime, int maxRetry, String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp, String mac) { + this(sendAwaitTime, maxRetry, ipAddress, port, linkRequest, listener, isTcp,false); + this.mac = mac; + } + + public HDLConnectHelper(Long sendAwaitTime, int maxRetry, String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp, String mac,boolean subThread) { + this(sendAwaitTime, maxRetry, ipAddress, port, linkRequest, listener, isTcp,subThread); + this.mac = mac; + } + + /** + * 鎸夌収鎸囧畾娆℃暟鍙戯紝鍥炶皟 + * + * @param maxRetry 閲嶈瘯娆℃暟 + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param port 鍙戦�佺洰鏍囩鍙� + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(int maxRetry, String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp) { + this(DEF_SEND_TIMEOUT, maxRetry, ipAddress, port, linkRequest, listener, isTcp); + } + + /** + * 鎸夌収鎸囧畾娆℃暟鍙戯紝鍥炶皟 + * + * @param maxRetry 閲嶈瘯娆℃暟 + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(int maxRetry, String ipAddress, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp) { + this(maxRetry, ipAddress, isTcp ? TCP_PORT : UDP_PORT, linkRequest, listener, isTcp); + } + + /** + * 鎸夌収鎸囧畾娆℃暟鍙戯紝涓嶅洖璋� + * + * @param maxRetry 閲嶈瘯娆℃暟 + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(int maxRetry, String ipAddress, + LinkRequest linkRequest, boolean isTcp) { + this(maxRetry, ipAddress, linkRequest, null, isTcp); + } + + /** + * 鎸夌収榛樿閲嶅彂鏈哄埗鍙戦�� + * + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param port 鍙戦�佺洰鏍囩鍙� + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(String ipAddress, int port, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp) { + this(DEF_MAX_RETRY, ipAddress, port, linkRequest, listener, isTcp); + } + + /** + * 榛樿绔彛鍙戦�� + * + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(String ipAddress, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp) { + this(DEF_SEND_TIMEOUT, DEF_MAX_RETRY, ipAddress, isTcp ? TCP_PORT : UDP_PORT, linkRequest, listener, isTcp); + } + + /** + * 榛樿绔彛鍙戦��(鍙傛暟鏈塵ac) + * + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param listener 鍥炶皟 + * @param isTcp 鏄惁TCP + * @param mac 璁惧mac + */ + public HDLConnectHelper(String ipAddress, + LinkRequest linkRequest, HdlSocketListener listener, boolean isTcp, String mac) { + this(DEF_SEND_TIMEOUT, DEF_MAX_RETRY, ipAddress, isTcp ? TCP_PORT : UDP_PORT, linkRequest, listener, isTcp, mac); + } + + + /** + * 鍙戦�佷竴娆� + * + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(String ipAddress, LinkRequest linkRequest, boolean isTcp) { + this(DEF_SEND_TIMEOUT, DEF_SEND_ONE, ipAddress, isTcp ? TCP_PORT : UDP_PORT, linkRequest, null, isTcp); + } + + /** + * 鍙戦�佷竴娆� + * + * @param ipAddress 鍙戦�佺洰鏍嘔P + * @param linkRequest 鍙戦�佸璞� + * @param isTcp 鏄惁TCP + */ + public HDLConnectHelper(Long timeout, String ipAddress, LinkRequest linkRequest, boolean isTcp) { + this(timeout, DEF_SEND_ONE, ipAddress, isTcp ? TCP_PORT : UDP_PORT, linkRequest, null, isTcp); + } + + + /** + * 娉ㄥ唽鐩戝惉 + */ + private void registerListener() { + if (!TextUtils.isEmpty(replyTopic) && null != listener) { + if(useSubThread){//浣跨敤瀛愮嚎绋嬪洖璋� + EventDispatcher.getInstance().asyncRegister(replyTopic, eventListener); + } + else { + //榛樿鐢ㄤ富绾跨▼ + EventDispatcher.getInstance().register(replyTopic, eventListener); + } + } + } + + /** + * 绉婚櫎鐩戝惉 + */ + private void removeListener() { + if (!TextUtils.isEmpty(replyTopic)) { + EventDispatcher.getInstance().remove(replyTopic, eventListener); + } + } + + public static boolean isLocal() { + String ip = HDLLinkConfig.getInstance().getIpAddress(); + if (ip == null) { + //濡傛槸鏈湴鏄彲浠ユ悳绱㈠埌ip鐨� + return false; + } + + //鏈湴鏄彲浠ヨ繙绋嬫垚鍔熺殑 + return HDLTcpConnect.getTcpSocketBoot(ip).isConnected(); + } + + public void send() { + + scheduledFuture= getSendThread().scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + try { + //鍙戦�佹鏁板皬浜庨噸鍙戞鏁� + if ((sendNumber.get() < maxRetry)) { + try { + + //杩樻病鏈夋敹鍒板洖澶嶏紝鍐嶅彂閫� + if (!isSend.get()) { + sendNumber.set(sendNumber.get() + 1); + + //濡傛槸tcp鎴栬�卪qtt + if (isTcp) { + //mqtt + if (TextUtils.isEmpty(ipAddress) || !HDLTcpConnect.getTcpSocketBoot(ipAddress).isConnected()) { + if (!linkRequest.getTopic().endsWith("heartbeat")) {//蹇冭烦涓婚鏁版嵁杩囧锛岃繃婊や笅 + //LogUtils.i("蹇冭烦鍖呭彂閫佹暟鎹細\r\n" + new String(linkRequest.getCloudSendBytes())); + } else { + return;//浜戠鎯呭喌涓嬶紝蹇冭烦鍙互涓嶇敤 + } + String requestTopic = linkRequest.getCloudTopic(); + GatewayBean gatewayBean = HDLLinkLocalGateway.getInstance().getLocalGateway(mac); + //缃戝叧鐨勬暟鎹� + String aes = HDLLinkConfig.getInstance().getAesKey();//榛樿鐢ㄤ富缃戝叧鐨勫瘑閽� + if (gatewayBean != null) { + aes = gatewayBean.getAesKey(); + } + //鍙兘瀵硅薄涓病鏈夎缃瘑閽ワ紝涓嶅簲璇ュ瓨鍦ㄨ繖绉嶆儏鍐点�� + if (TextUtils.isEmpty(aes)) { + LogUtils.e(TAG, "鎵句笉鍒拌繙绋嬪姞瀵嗙殑瀵嗛挜锛岃繖涓棶棰樿鎺掓湡瑙e喅"); + return; + } + byte[] encryBytes = EncryptUtil.encryBytes(linkRequest.getCloudSendBytes(), aes); + if (MqttRecvClient.getInstance() != null) { + MqttRecvClient.getInstance().send(requestTopic, encryBytes); + if (HDLConnectHelper.isInverterTopic(linkRequest.getCloudTopic())) { + LogUtils.i(TAG, "杩滅▼鍙戦�佹暟鎹紝涓婚锛�" + linkRequest.getCloudTopic() + "\r\nPayload锛�" + ByteUtils.encodeHexString(linkRequest.getData())); + } else { + LogUtils.i(TAG, "杩滅▼鍙戦�佹暟鎹紝涓婚锛�" + linkRequest.getCloudTopic() + "\r\nPayload锛�" + new String(linkRequest.getCloudSendBytes())); + } + } + } + //鏈湴TCP + else { + if (!linkRequest.getTopic().endsWith("heartbeat")) {//蹇冭烦涓婚鏁版嵁杩囧锛岃繃婊や笅 + if (JsonUtils.isJson(linkRequest.getData())) { + LogUtils.i(TAG, "鏈湴鍙戦�佹暟鎹甛r\n" + new String(linkRequest.getSendBytes())); + } else { + LogUtils.i(TAG, String.format("鏈湴鍙戦�佷富棰橈細%s\r\nPayload锛�%s", linkRequest.getTopic(), ByteUtils.encodeHexString(linkRequest.getData()))); + } + } + HDLTcpConnect.getTcpSocketBoot(ipAddress).sendMsg(EncryptUtil.getEncryBytes(linkRequest)); + } + } else { + //濡傛灉鏄痷dp + LogUtils.i(TAG, "鏈湴鍙戦�乁DP鏁版嵁\r\n" + new String(linkRequest.getSendBytes())); + HDLUdpConnect.getInstance().getUdpBoot().sendMsg(ipAddress, port, EncryptUtil.getEncryBytes(linkRequest)); + } + } + } catch (Exception e) { + LogUtils.e(TAG, "鏁版嵁鍙戦�佸紓甯革細" + e.getMessage()); + } + } else { + //瓒呭嚭閲嶅彂娆℃暟骞舵病鏈夋敹鍒板洖澶� + if (!isSend.get()) { + if (linkRequest.getTopic().endsWith("heartbeat")) {//蹇冭烦涓婚鍏堜笉閫氱煡 + notifyFailure(null); + } else { + if (!TextUtils.isEmpty(replyTopic) && null != listener) {//闇�瑕佹墦鍗板嚭澶辫触鐨勬棩蹇� + LogUtils.e(TAG, "鍙戦�佸け璐ユ暟鎹富棰�:" + linkRequest.getTopic()); + } + if (isTcp) { + //mqtt + if (TextUtils.isEmpty(ipAddress) || !HDLTcpConnect.getTcpSocketBoot(ipAddress).isConnected()) { + notifyFailure(HDLLinkCode.HDL_GATEWAY_REMOTE_NOT_RESPONSE); + } + //鏈湴TCP锛屽苟鏄繛鎺ョ姸鎬� + else { + notifyFailure(HDLLinkCode.HDL_TIMEOUT_ERROR); + } + } else { + notifyFailure(HDLLinkCode.HDL_TIMEOUT_ERROR); + } + } + } + } + }catch (Exception e){ + e.printStackTrace(); + } + } + }, 0, sendAwaitTime, TimeUnit.MILLISECONDS); + //initialdelay - 棣栨鎵ц鐨勫欢杩熸椂闂� 0 + //delay - 涓�娆℃墽琛岀粓姝㈠拰涓嬩竴娆℃墽琛屽紑濮嬩箣闂寸殑寤惰繜 + } + + /** + * 鑾峰彇鍙戦�佺嚎绋� + * + * @return 杩斿洖鑾峰彇鍒扮殑绾跨▼ + */ + private synchronized ScheduledExecutorService getSendThread() { + if (scheduledExecutorService == null) { + scheduledExecutorService = ThreadToolUtils.getInstance().newScheduledThreadPool(3); + } + return scheduledExecutorService; + } + + /** + * 鍙戦�佸け璐� + */ + private void notifyFailure(HDLLinkCode hdlLinkCode) { + //绉婚櫎鐩戝惉 + removeListener(); + if(scheduledFuture!=null){ + scheduledFuture.cancel(false); + } +// if (sendThread != null) { +// sendThread.shutdownNow(); +// sendThread = null; +// } + if (listener != null && hdlLinkCode != null) { + listener.onFailure(hdlLinkCode); + listener = null; + } + } + + + + // /** +// * 鏀寔姣背绫诲瀷 +// * +// * @return 绫诲瀷鍒楄〃 +// */ +// public static List<String> getGatewayTypeList() { +// List<String> typeList = new ArrayList<>(); +//// typeList.add("sensor.mmv_sleep");//鐫$湢姣背娉pk +//// typeList.add("sensor.mmv_pose");//濮挎�佹绫虫尝spk +// typeList.add("energy.hdl_inverter");//閫嗗彉鍣╯pk +// typeList.add("sensor.mmv_sleep");//鐫$湢姣背娉pk +// typeList.add("sensor.mmv_pose");//濮挎�佹绫虫尝spk +// typeList.add("sensor.hdl_mmw_pose");//Wi-Fi姣背娉T鐗堟湰 +// return typeList; +// } +// + public static List<String> getMillimeterTypeList() { + List<String> typeList = new ArrayList<>(); +// typeList.add("AGATEWAY");//缃戝叧 + typeList.add("sensor.mmv_sleep");//鐫$湢姣背娉pk + typeList.add("sensor.mmv_pose");//濮挎�佹绫虫尝spk + typeList.add("sensor.hdl_mmw_pose");//Wi-Fi姣背娉T鐗堟湰 + typeList.add("sensor.hdl_mmw_sleep");//Wi-Fi姣背娉㈢潯鐪犵増 + return typeList; + } + + public static List<String> getGatewayModelList() { + List<String> typeList = new ArrayList<>(); + typeList.add("MIR01R-LK.10");//鐫$湢姣背娉pk + typeList.add("MSMWP-LK.30");//濮挎�佹绫虫尝spk + typeList.add("MSMWH-LK.30");//濮挎�佹绫虫尝spk + return typeList; + } + + /** + * 鑾峰彇闄や簡缃戝叧鐨勫叾瀹冪綉缁滆澶囷紝涓婇潰鍐欑殑閭d袱涓柟娉曚笉涓�鑷磄etGatewayTypeList锛実etMillimeterTypeList锛岀粺涓�浜嗕笅锛屼互鍏嶅悗鏈熷嚭闂 + * @return + */ + public static List<String> getNotGatewayTypeList(){ + List<String> typeList = new ArrayList<>(); + typeList.add("energy.hdl_inverter");//閫嗗彉鍣╯pk + typeList.add("sensor.mmv_sleep");//鐫$湢姣背娉pk + typeList.add("sensor.mmv_pose");//濮挎�佹绫虫尝spk + typeList.add("sensor.hdl_mmw_pose");//Wi-Fi姣背娉T鐗堟湰 + typeList.add("sensor.hdl_mmw_sleep");//Wi-Fi姣背娉㈢潯鐪犵増 + return typeList; + } + + public static List<String> getNewMillimeterTypeList() { + List<String> typeList = new ArrayList<>(); + typeList.add("sensor.hdl_mmw_pose");//Wi-Fi姣背娉T鐗堟湰 + typeList.add("sensor.hdl_mmw_sleep");//Wi-Fi姣背娉㈢潯鐪犵増 + return typeList; + } + + private void notifySucceed(Object msg) { + //绉婚櫎鐩戝惉 + removeListener(); + if(scheduledFuture!=null){ + scheduledFuture.cancel(false); + } +// if (sendThread != null) { +// sendThread.shutdownNow(); +// sendThread = null; +// } + if (listener != null) { + listener.onSucceed(msg); + listener = null; + } + } + + + + public static boolean isInverterTopic(String topic) { + if (TextUtils.isEmpty(topic)) { + return false; + } + return topic.endsWith("custom/native/inverter/down_reply") + || topic.endsWith("custom/native/inverter/down") + || topic.endsWith("custom/native/inverter/up"); + } + + /** + * byte鏁扮粍杞崲鎴恑nt鏁扮粍(涓轰簡鎵撳嵃鍑烘棤绗﹀彿鐨刡tye鏁扮粍鏁版嵁) + * + * @param bytes 鏁扮粍 + * @return + */ + public static Integer[] byteArrayConvertIntArray(byte[] bytes) { + if (bytes == null || bytes.length == 0) { + return new Integer[]{}; + } + Integer[] arr = new Integer[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + arr[i] = bytes[i] & 0xff; + } + return arr; + } + + public boolean isUseSubThread() { + return useSubThread; + } + + public void setUseSubThread(boolean useSubThread) { + this.useSubThread = useSubThread; + } +} -- Gitblit v1.8.0