49 changed files with 1044 additions and 87 deletions
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.Chan; |
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class JDKLockBarrierImpl implements PublishBarrier{ |
||||
|
||||
/** |
||||
* 在我的实现中是采用一个定期清理的TimedCache储存请求 |
||||
*/ |
||||
private final ConcurrentHashMap<String, JDKHolder> container = new ConcurrentHashMap<>(); |
||||
|
||||
@Override |
||||
public String generateIdentity(CommonTopicRequest requestData) { |
||||
return requestData.getTid(); |
||||
} |
||||
|
||||
@Override |
||||
public String generateIdentity(CommonTopicResponse receiveData) { |
||||
return receiveData.getTid(); |
||||
} |
||||
|
||||
@Override |
||||
public void put(String identity, CommonTopicResponse receiveData) { |
||||
if(hasIdentity(identity)){ |
||||
container.get(identity).setData(receiveData); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerRequest(String identity, CommonTopicRequest requestData) { |
||||
container.put(identity,new JDKHolder()); |
||||
} |
||||
|
||||
@Override |
||||
public PublishBarrierResult await(String identity, long timeout) { |
||||
JDKHolder jdkHolder = container.get(identity); |
||||
if(Objects.isNull(jdkHolder)){ |
||||
throw new RuntimeException("等待指令返回前未注册指令到栅栏"); |
||||
} |
||||
jdkHolder.await(timeout); |
||||
|
||||
return jdkHolder.getResult(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasIdentity(String identity) { |
||||
return container.containsKey(identity); |
||||
} |
||||
|
||||
public static class JDKHolder{ |
||||
volatile Object locker = new Object(); |
||||
CommonTopicResponse response = null; |
||||
|
||||
public void await(long timeout) { |
||||
synchronized (locker){ |
||||
try { |
||||
locker.wait(timeout); |
||||
}catch (InterruptedException e){} |
||||
} |
||||
} |
||||
|
||||
public void setData(CommonTopicResponse receiveData) { |
||||
this.response = receiveData; |
||||
synchronized (locker){ |
||||
locker.notify(); |
||||
} |
||||
} |
||||
|
||||
public PublishBarrierResult getResult() { |
||||
if(Objects.nonNull(response)){ |
||||
return PublishBarrierResult.ok(response); |
||||
}else{ |
||||
return PublishBarrierResult.EMPTY; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月25日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.cloudapi.device.DeviceDomainEnum; |
||||
import com.dji.sdk.cloudapi.device.DeviceEnum; |
||||
import com.dji.sdk.cloudapi.device.DeviceSubTypeEnum; |
||||
import com.dji.sdk.cloudapi.device.DeviceTypeEnum; |
||||
import com.dji.sdk.exception.CloudSDKErrorEnum; |
||||
import com.dji.sdk.exception.CloudSDKException; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.Optional; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class LocalCacheSDKManager implements SDKManager{ |
||||
|
||||
final ConcurrentHashMap<String, GatewayManager> SDK_MAP = new ConcurrentHashMap<>(16); |
||||
|
||||
|
||||
@Override |
||||
public GatewayManager getDeviceSDK(String gatewaySn) { |
||||
if (SDK_MAP.containsKey(gatewaySn)) { |
||||
return SDK_MAP.get(gatewaySn); |
||||
} |
||||
throw new CloudSDKException(CloudSDKErrorEnum.NOT_REGISTERED, |
||||
"The device has not been registered, please call the 'SDKManager.registerDevice()' method to register the device first."); |
||||
} |
||||
|
||||
@Override |
||||
public Optional<GatewayManager> findDeviceSDK(String gatewaySn) { |
||||
if(SDK_MAP.containsKey(gatewaySn)){ |
||||
return Optional.of(SDK_MAP.get(gatewaySn)); |
||||
}else { |
||||
return Optional.empty(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public GatewayManager registerDevice(String gatewaySn, String droneSn, DeviceDomainEnum domain, DeviceTypeEnum type, DeviceSubTypeEnum subType, String gatewayThingVersion, String droneThingVersion) { |
||||
return registerDevice(gatewaySn, droneSn, GatewayTypeEnum.find(DeviceEnum.find(domain, type, subType)), gatewayThingVersion, droneThingVersion); |
||||
} |
||||
|
||||
@Override |
||||
public GatewayManager registerDevice(String gatewaySn, String droneSn, GatewayTypeEnum type, String gatewayThingVersion, String droneThingVersion) { |
||||
return registerDevice(new GatewayManager(Objects.requireNonNull(gatewaySn), droneSn, type, gatewayThingVersion, droneThingVersion)); |
||||
} |
||||
|
||||
@Override |
||||
public GatewayManager registerDevice(GatewayManager gateway) { |
||||
SDK_MAP.put(gateway.getGatewaySn(), gateway); |
||||
return gateway; |
||||
} |
||||
|
||||
@Override |
||||
public void logoutDevice(String gatewaySn) { |
||||
SDK_MAP.remove(gatewaySn); |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
public interface PublishBarrier { |
||||
|
||||
//构建栅栏标识方法
|
||||
String generateIdentity(CommonTopicRequest requestData); |
||||
String generateIdentity(CommonTopicResponse receiveData); |
||||
|
||||
void put(String identity, CommonTopicResponse receiveData); |
||||
|
||||
void registerRequest(String identity, CommonTopicRequest requestData); |
||||
|
||||
PublishBarrierResult await(String identity,long timeout); |
||||
|
||||
boolean hasIdentity(String identity); |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
public class PublishBarrierResult implements PublishResult { |
||||
|
||||
public static PublishBarrierResult EMPTY = new PublishBarrierResult(); |
||||
|
||||
public static PublishBarrierResult ok(CommonTopicResponse data){ |
||||
return new PublishBarrierResult().setData(data); |
||||
} |
||||
|
||||
|
||||
boolean timeout = true; |
||||
|
||||
CommonTopicResponse data; |
||||
|
||||
private PublishBarrierResult() { |
||||
} |
||||
|
||||
private PublishBarrierResult setData(CommonTopicResponse data) { |
||||
this.data = data; |
||||
this.timeout = false; |
||||
return this; |
||||
} |
||||
|
||||
public boolean isTimeout(){ |
||||
return timeout; |
||||
} |
||||
|
||||
public CommonTopicResponse getData(){ |
||||
return data; |
||||
} |
||||
} |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class PublishConfiguration implements ReadonlyPublishConfiguration { |
||||
|
||||
String bid; |
||||
String tid; |
||||
|
||||
//默认超时
|
||||
int timeout = 3; |
||||
//请求发送前调用
|
||||
Consumer<PublishRequest> beforePublishHook = null; |
||||
//收到请求回信后调用
|
||||
BiConsumer<PublishRequest, PublishBarrierResult> afterPublishHook = null; |
||||
|
||||
|
||||
public String getBid() { |
||||
return bid; |
||||
} |
||||
|
||||
public String getTid() { |
||||
return tid; |
||||
} |
||||
|
||||
public long getTimeout() { |
||||
return timeout * 1000; |
||||
} |
||||
|
||||
public void setBizId(String bid) { |
||||
this.bid = bid; |
||||
} |
||||
|
||||
public void setTransactionId(String tid) { |
||||
this.tid = tid; |
||||
} |
||||
|
||||
public void setTimeout(int timeout) { |
||||
this.timeout = timeout; |
||||
} |
||||
|
||||
public void setBeforePublishHook(Consumer<PublishRequest> callback) { |
||||
beforePublishHook = callback; |
||||
} |
||||
|
||||
public void setAfterPublishReplyHook(BiConsumer<PublishRequest, PublishBarrierResult> callback) { |
||||
afterPublishHook = callback; |
||||
} |
||||
|
||||
public void invokeBeforePublishHook(PublishRequest req){ |
||||
if(Objects.nonNull(beforePublishHook)){ |
||||
try { |
||||
beforePublishHook.accept(req); |
||||
}catch (Throwable ex){ |
||||
//do nothing
|
||||
//业务层的异常不理会
|
||||
} |
||||
} |
||||
} |
||||
|
||||
public void invokeAfterPublishReplyHook(PublishRequest req, PublishBarrierResult result){ |
||||
if(Objects.nonNull(afterPublishHook)){ |
||||
try{ |
||||
afterPublishHook.accept(req,result); |
||||
}catch (Throwable ex){ |
||||
//do nothing
|
||||
//业务层的异常不理会
|
||||
} |
||||
} |
||||
} |
||||
|
||||
public boolean noneBeforePublishHook() { |
||||
return Objects.isNull(beforePublishHook); |
||||
} |
||||
|
||||
public boolean noneAfterPublishHook() { |
||||
return Objects.isNull(afterPublishHook); |
||||
} |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.google.common.base.Strings; |
||||
|
||||
import java.util.Objects; |
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
|
||||
public class PublishOption { |
||||
|
||||
public static Consumer<PublishOption> DEFAULT = (cfg)->{}; |
||||
|
||||
final PublishConfiguration configuration; |
||||
|
||||
public PublishOption(PublishConfiguration configuration) { |
||||
this.configuration = configuration; |
||||
} |
||||
|
||||
public PublishOption withBizId(String bid){ |
||||
if(!Strings.isNullOrEmpty(bid)){ |
||||
configuration.setBizId(bid); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption withTransactionId(String tid){ |
||||
if(!Strings.isNullOrEmpty(tid)){ |
||||
configuration.setTransactionId(tid); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption timeout(int second){ |
||||
configuration.setTimeout(second); |
||||
return this; |
||||
} |
||||
|
||||
public PublishOption beforePublish(Consumer<PublishRequest> callback){ |
||||
if(Objects.nonNull(callback)){ |
||||
configuration.setBeforePublishHook(callback); |
||||
} |
||||
return this; |
||||
} |
||||
public PublishOption afterPublishReply(BiConsumer<PublishRequest, PublishBarrierResult> callback){ |
||||
if(Objects.nonNull(callback)){ |
||||
configuration.setAfterPublishReplyHook(callback); |
||||
} |
||||
return this; |
||||
} |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月25日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.common.ReadonlyPublishConfiguration; |
||||
import com.dji.sdk.mqtt.CommonTopicRequest; |
||||
|
||||
public interface PublishRequest { |
||||
|
||||
String getTopic(); |
||||
|
||||
CommonTopicRequest getOriginRequest(); |
||||
|
||||
ReadonlyPublishConfiguration getConfiguration(); |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月25日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
import com.dji.sdk.mqtt.CommonTopicResponse; |
||||
|
||||
public interface PublishResult { |
||||
|
||||
boolean isTimeout(); |
||||
|
||||
CommonTopicResponse getData(); |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月25日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.common; |
||||
|
||||
public interface ReadonlyPublishConfiguration { |
||||
|
||||
String getBid(); |
||||
|
||||
String getTid(); |
||||
|
||||
long getTimeout(); |
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.config; |
||||
|
||||
import com.dji.sdk.common.*; |
||||
import com.dji.sdk.mqtt.ChanBarrierAdapter; |
||||
import com.dji.sdk.mqtt.GlobalPublishOption; |
||||
import com.dji.sdk.common.PublishRequest; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import java.util.UUID; |
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Supplier; |
||||
|
||||
@Configuration |
||||
public class DefaultBeanConfiguration { |
||||
|
||||
/** |
||||
* 全局发送默认设置 |
||||
* @return |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnMissingBean(GlobalPublishOption.class) |
||||
public GlobalPublishOption defaultPublishOption(){ |
||||
return new GlobalPublishOption() { |
||||
@Override |
||||
public Supplier<String> defaultTransactionId() { |
||||
return ()-> UUID.randomUUID().toString(); |
||||
} |
||||
|
||||
@Override |
||||
public Supplier<String> defaultBizId() { |
||||
return ()-> UUID.randomUUID().toString(); |
||||
} |
||||
|
||||
@Override |
||||
public Consumer<PublishRequest> defaultBeforePublishHook() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public BiConsumer<PublishRequest, PublishBarrierResult> defaultAfterPublishHook() { |
||||
return null; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean(SDKManager.class) |
||||
public SDKManager localCacheSDKManager(){ |
||||
return new LocalCacheSDKManager(); |
||||
} |
||||
|
||||
/** |
||||
* 使用者可以自定义PublishBarrier的实现,默认采用Chan实现 |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnMissingBean(PublishBarrier.class) |
||||
public PublishBarrier chanBarrier(){ |
||||
/** 原Chan实现 */ |
||||
return new ChanBarrierAdapter(); |
||||
} |
||||
|
||||
/** |
||||
* PublishBarrier 另一个实现, 采用同步锁 |
||||
*/ |
||||
// @Bean
|
||||
// @ConditionalOnMissingBean(PublishBarrier.class)
|
||||
// public PublishBarrier jdkBarrier(){
|
||||
// return new JDKLockBarrierImpl();
|
||||
// }
|
||||
} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月22日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.mqtt; |
||||
|
||||
import com.dji.sdk.common.PublishBarrier; |
||||
import com.dji.sdk.common.PublishBarrierResult; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
public class ChanBarrierAdapter implements PublishBarrier { |
||||
@Override |
||||
public String generateIdentity(CommonTopicRequest requestData) { |
||||
return requestData.getTid(); |
||||
} |
||||
|
||||
@Override |
||||
public String generateIdentity(CommonTopicResponse receiveData) { |
||||
return receiveData.getTid(); |
||||
} |
||||
|
||||
@Override |
||||
public void put(String identity, CommonTopicResponse receiveData) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
if(Objects.nonNull(instance)){ |
||||
instance.put(receiveData); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void registerRequest(String identity, CommonTopicRequest requestData) { |
||||
Chan.getInstance(identity, true); |
||||
} |
||||
|
||||
@Override |
||||
public PublishBarrierResult await(String identity,long timeout) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
|
||||
CommonTopicResponse response = instance.get(identity, timeout); |
||||
|
||||
return Objects.nonNull(response) ? PublishBarrierResult.ok(response) : PublishBarrierResult.EMPTY; |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasIdentity(String identity) { |
||||
Chan instance = Chan.getInstance(identity, false); |
||||
return Objects.nonNull(instance); |
||||
} |
||||
} |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年10月09日 |
||||
* @version: 1.0.0 |
||||
* @description: |
||||
**************************************************/ |
||||
package com.dji.sdk.mqtt; |
||||
|
||||
public class FlowTransformWrapper { |
||||
|
||||
public final static String DEFAULT_ERROR_MSG = "null"; |
||||
|
||||
public static FlowTransformWrapper error(){ |
||||
return new FlowTransformWrapper(DEFAULT_ERROR_MSG); |
||||
} |
||||
|
||||
public static FlowTransformWrapper ok(CommonTopicRequest request){ |
||||
return new FlowTransformWrapper(request); |
||||
} |
||||
|
||||
CommonTopicRequest request; |
||||
boolean bError; |
||||
String errorMessage; |
||||
|
||||
private FlowTransformWrapper(CommonTopicRequest request){ |
||||
this.request = request; |
||||
this.bError = false; |
||||
} |
||||
|
||||
private FlowTransformWrapper(String errorMessage){ |
||||
this.bError = true; |
||||
this.errorMessage = errorMessage; |
||||
} |
||||
|
||||
public CommonTopicRequest getRequest() { |
||||
return request; |
||||
} |
||||
|
||||
public boolean hasError() { |
||||
return bError; |
||||
} |
||||
|
||||
public boolean continuee(){ |
||||
return !hasError(); |
||||
} |
||||
|
||||
public String getErrorMessage() { |
||||
return errorMessage; |
||||
} |
||||
} |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/************************************************* |
||||
* @copyright 2017 Flision Corporation Inc. |
||||
* @author: Vincent Chan @ Canton |
||||
* @date: 2023年09月25日 |
||||
* @version: 1.0.0 |
||||
* @description: 全局发送默认配置 |
||||
**************************************************/ |
||||
package com.dji.sdk.mqtt; |
||||
|
||||
import com.dji.sdk.common.PublishBarrierResult; |
||||
import com.dji.sdk.common.PublishRequest; |
||||
|
||||
import java.util.function.BiConsumer; |
||||
import java.util.function.Consumer; |
||||
import java.util.function.Supplier; |
||||
|
||||
public interface GlobalPublishOption { |
||||
Supplier<String> defaultTransactionId(); |
||||
Supplier<String> defaultBizId(); |
||||
|
||||
Consumer<PublishRequest> defaultBeforePublishHook(); |
||||
BiConsumer<PublishRequest, PublishBarrierResult> defaultAfterPublishHook(); |
||||
|
||||
} |
Loading…
Reference in new issue