sean.zhou
3 years ago
173 changed files with 6123 additions and 998 deletions
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
package com.dji.sample.common.error; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/25 |
||||
*/ |
||||
public enum StorageErrorEnum implements IErrorInfo { |
||||
|
||||
GENERATE_CREDENTIALS_ERROR(217001, "Failed to generate temporary credentials."), |
||||
|
||||
NO_BUCKET(217002, "The bucket does not exist."), |
||||
|
||||
ILLEGAL_PATH_FORMAT(217006, "Illegal path format."), |
||||
|
||||
FILE_CREATION_FAILED(217007, "File creation failed."), |
||||
|
||||
DIR_CREATION_FAILED(217008, "Directory creation failed"); |
||||
|
||||
private String msg; |
||||
|
||||
private int code; |
||||
|
||||
StorageErrorEnum(int code, String msg) { |
||||
this.msg = msg; |
||||
this.code = code; |
||||
} |
||||
|
||||
@Override |
||||
public String getErrorMsg() { |
||||
return msg; |
||||
} |
||||
|
||||
@Override |
||||
public Integer getErrorCode() { |
||||
return code; |
||||
} |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.redis.RedisOpsUtils; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.3 |
||||
* @date 2022/2/21 |
||||
*/ |
||||
public abstract class AbstractStateTopicHandler { |
||||
|
||||
protected AbstractStateTopicHandler handler; |
||||
|
||||
@Autowired |
||||
protected ObjectMapper mapper; |
||||
|
||||
@Autowired |
||||
protected RedisOpsUtils redisOps; |
||||
|
||||
protected AbstractStateTopicHandler(AbstractStateTopicHandler handler) { |
||||
this.handler = handler; |
||||
} |
||||
|
||||
/** |
||||
* Passing dataNode data, using different processing methods depending on the data selection. |
||||
* @param dataNode |
||||
* @param stateReceiver |
||||
* @param sn |
||||
* @return |
||||
* @throws JsonProcessingException |
||||
*/ |
||||
public abstract CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException; |
||||
} |
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.ChannelName; |
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.mqtt.model.EventsMethodEnum; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.integration.dsl.IntegrationFlow; |
||||
import org.springframework.integration.dsl.IntegrationFlows; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/1 |
||||
*/ |
||||
@Configuration |
||||
public class EventsRouter { |
||||
|
||||
@Autowired |
||||
private ObjectMapper mapper; |
||||
|
||||
@Bean |
||||
public IntegrationFlow eventsMethodRouterFlow() { |
||||
return IntegrationFlows |
||||
.from(ChannelName.INBOUND_EVENTS) |
||||
.<byte[], CommonTopicReceiver>transform(payload -> { |
||||
try { |
||||
return mapper.readValue(payload, CommonTopicReceiver.class); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return new CommonTopicReceiver(); |
||||
}) |
||||
.<CommonTopicReceiver, EventsMethodEnum>route( |
||||
receiver -> EventsMethodEnum.find(receiver.getMethod()), |
||||
mapping -> { |
||||
mapping.channelMapping(EventsMethodEnum.FILE_UPLOAD_CALLBACK, ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK); |
||||
mapping.channelMapping(EventsMethodEnum.FLIGHT_TASK_PROGRESS, ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS); |
||||
mapping.channelMapping(EventsMethodEnum.HMS, ChannelName.INBOUND_EVENTS_HMS); |
||||
mapping.channelMapping(EventsMethodEnum.UNKNOWN, ChannelName.DEFAULT); |
||||
}) |
||||
.get(); |
||||
} |
||||
} |
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.ChannelName; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.integration.annotation.Router; |
||||
import org.springframework.integration.mqtt.support.MqttHeaders; |
||||
import org.springframework.integration.router.AbstractMessageRouter; |
||||
import org.springframework.messaging.Message; |
||||
import org.springframework.messaging.MessageChannel; |
||||
import org.springframework.messaging.MessageHeaders; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import javax.annotation.Resource; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.regex.Pattern; |
||||
|
||||
import static com.dji.sample.component.mqtt.model.TopicConst.*; |
||||
|
||||
/** |
||||
* |
||||
* @author sean.zhou |
||||
* @date 2021/11/10 |
||||
* @version 0.1 |
||||
*/ |
||||
@Component |
||||
@Slf4j |
||||
public class InboundMessageRouter extends AbstractMessageRouter { |
||||
|
||||
@Resource(name = ChannelName.INBOUND) |
||||
private MessageChannel inboundChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_STATUS) |
||||
private MessageChannel statusChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_STATE) |
||||
private MessageChannel stateChannel; |
||||
|
||||
@Resource(name = ChannelName.DEFAULT) |
||||
private MessageChannel defaultChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_SERVICE_REPLY) |
||||
private MessageChannel serviceReplyChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_OSD) |
||||
private MessageChannel osdChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_REQUESTS) |
||||
private MessageChannel requestsChannel; |
||||
|
||||
@Resource(name = ChannelName.INBOUND_EVENTS) |
||||
private MessageChannel eventsChannel; |
||||
|
||||
private static final Pattern PATTERN_TOPIC_STATUS = |
||||
Pattern.compile("^" + BASIC_PRE + PRODUCT + REGEX_SN + STATUS_SUF + "$"); |
||||
|
||||
private static final Pattern PATTERN_TOPIC_STATE = |
||||
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + STATE_SUF + "$"); |
||||
|
||||
private static final Pattern PATTERN_TOPIC_SERVICE_REPLY = |
||||
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + SERVICES_SUF + _REPLY_SUF + "$"); |
||||
|
||||
private static final Pattern PATTERN_TOPIC_OSD = |
||||
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + OSD_SUF + "$"); |
||||
|
||||
private static final Pattern PATTERN_TOPIC_REQUESTS = |
||||
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + REQUESTS_SUF + "$"); |
||||
|
||||
private static final Pattern PATTERN_TOPIC_EVENTS = |
||||
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + EVENTS_SUF + "$"); |
||||
|
||||
/** |
||||
* All mqtt broker messages will arrive here before distributing them to different channels. |
||||
* @param message message from mqtt broker |
||||
* @return channel |
||||
*/ |
||||
@Override |
||||
@Router(inputChannel = ChannelName.INBOUND) |
||||
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) { |
||||
MessageHeaders headers = message.getHeaders(); |
||||
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString(); |
||||
byte[] payload = (byte[])message.getPayload(); |
||||
|
||||
// osd
|
||||
if (PATTERN_TOPIC_OSD.matcher(topic).matches()) { |
||||
return Collections.singleton(osdChannel); |
||||
} |
||||
|
||||
log.debug("received topic :{} \t payload :{}", topic, new String(payload)); |
||||
|
||||
// status
|
||||
if (PATTERN_TOPIC_STATUS.matcher(topic).matches()) { |
||||
return Collections.singleton(statusChannel); |
||||
} |
||||
|
||||
// state
|
||||
if (PATTERN_TOPIC_STATE.matcher(topic).matches()) { |
||||
return Collections.singleton(stateChannel); |
||||
} |
||||
|
||||
// services_reply
|
||||
if (PATTERN_TOPIC_SERVICE_REPLY.matcher(topic).matches()) { |
||||
return Collections.singleton(serviceReplyChannel); |
||||
} |
||||
|
||||
// requests
|
||||
if (PATTERN_TOPIC_REQUESTS.matcher(topic).matches()) { |
||||
return Collections.singleton(requestsChannel); |
||||
} |
||||
|
||||
// events
|
||||
if (PATTERN_TOPIC_EVENTS.matcher(topic).matches()) { |
||||
return Collections.singleton(eventsChannel); |
||||
} |
||||
|
||||
return Collections.singleton(defaultChannel); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.ChannelName; |
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.mqtt.model.RequestsMethodEnum; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.integration.dsl.IntegrationFlow; |
||||
import org.springframework.integration.dsl.IntegrationFlows; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/25 |
||||
*/ |
||||
@Configuration |
||||
public class RequestsRouter { |
||||
|
||||
@Autowired |
||||
private ObjectMapper mapper; |
||||
|
||||
@Bean |
||||
public IntegrationFlow requestsMethodRouterFlow() { |
||||
return IntegrationFlows |
||||
.from(ChannelName.INBOUND_REQUESTS) |
||||
.<byte[], CommonTopicReceiver>transform(payload -> { |
||||
try { |
||||
return mapper.readValue(payload, CommonTopicReceiver.class); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return new CommonTopicReceiver(); |
||||
}) |
||||
.<CommonTopicReceiver, RequestsMethodEnum>route( |
||||
receiver -> RequestsMethodEnum.find(receiver.getMethod()), |
||||
mapping -> { |
||||
mapping.channelMapping(RequestsMethodEnum.STORAGE_CONFIG_GET, ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET); |
||||
mapping.channelMapping(RequestsMethodEnum.AIRPORT_BIND_STATUS, ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS); |
||||
mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_GET, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET); |
||||
mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_BIND, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND); |
||||
mapping.channelMapping(RequestsMethodEnum.UNKNOWN, ChannelName.DEFAULT); |
||||
}) |
||||
.get(); |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.3 |
||||
* @date 2022/3/21 |
||||
*/ |
||||
@Service |
||||
public class StateDefaultHandler extends AbstractStateTopicHandler { |
||||
|
||||
protected StateDefaultHandler() { |
||||
super(null); |
||||
} |
||||
|
||||
@Override |
||||
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException { |
||||
// If no suitable handler is found for the data, it is not processed.
|
||||
return stateReceiver; |
||||
} |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.mqtt.model.StateDataEnum; |
||||
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.3 |
||||
* @date 2022/2/21 |
||||
*/ |
||||
@Service |
||||
public class StateDeviceBasicHandler extends AbstractStateTopicHandler { |
||||
|
||||
public StateDeviceBasicHandler(@Autowired @Qualifier("stateLiveCapacityHandler") AbstractStateTopicHandler handler) { |
||||
super(handler); |
||||
} |
||||
|
||||
@Override |
||||
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException { |
||||
// handle device basic data
|
||||
if (dataNode.containsKey(StateDataEnum.PAYLOADS.getDesc())) { |
||||
DeviceBasicReceiver data = mapper.convertValue(stateReceiver.getData(), DeviceBasicReceiver.class); |
||||
data.setDeviceSn(sn); |
||||
data.getPayloads().forEach(payload -> payload.setDeviceSn(sn)); |
||||
|
||||
stateReceiver.setData(data); |
||||
return stateReceiver; |
||||
} |
||||
return handler.handleState(dataNode, stateReceiver, sn); |
||||
} |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.mqtt.model.StateDataEnum; |
||||
import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
||||
import com.dji.sample.manage.model.enums.PayloadModelEnum; |
||||
import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.3 |
||||
* @date 2022/2/21 |
||||
*/ |
||||
@Service |
||||
public class StateFirmwareVersionHandler extends AbstractStateTopicHandler { |
||||
|
||||
protected StateFirmwareVersionHandler(@Autowired @Qualifier("stateDefaultHandler") AbstractStateTopicHandler handler) { |
||||
super(handler); |
||||
} |
||||
|
||||
@Override |
||||
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException { |
||||
// Parse the firmware version of the device.
|
||||
if (dataNode.containsKey(StateDataEnum.FIRMWARE_VERSION.getDesc())) { |
||||
FirmwareVersionReceiver firmware = mapper.convertValue(dataNode, FirmwareVersionReceiver.class); |
||||
firmware.setSn(sn); |
||||
firmware.setDomain(DeviceDomainEnum.SUB_DEVICE); |
||||
stateReceiver.setData(firmware); |
||||
return stateReceiver; |
||||
} |
||||
|
||||
// Parse the firmware version of the payload.
|
||||
List<String> payloads = PayloadModelEnum.getAllModel(); |
||||
long count = dataNode.keySet() |
||||
.stream() |
||||
.map(key -> { |
||||
int end = key.indexOf("-"); |
||||
return end == -1 ? key : key.substring(0, end); |
||||
}) |
||||
.filter(payloads::contains) |
||||
.count(); |
||||
if (count > 0) { |
||||
FirmwareVersionReceiver firmware = FirmwareVersionReceiver.builder() |
||||
.firmwareVersion(((Map<String, String>)(dataNode.values().iterator().next())) |
||||
.get(StateDataEnum.FIRMWARE_VERSION.getDesc())) |
||||
.sn(sn) |
||||
.domain(DeviceDomainEnum.PAYLOAD) |
||||
.build(); |
||||
stateReceiver.setData(firmware); |
||||
return stateReceiver; |
||||
} |
||||
|
||||
return handler.handleState(dataNode, stateReceiver, sn); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.component.mqtt.model.StateDataEnum; |
||||
import com.dji.sample.manage.model.receiver.LiveCapacityReceiver; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.3 |
||||
* @date 2022/2/21 |
||||
*/ |
||||
@Service |
||||
@Slf4j |
||||
public class StateLiveCapacityHandler extends AbstractStateTopicHandler { |
||||
|
||||
protected StateLiveCapacityHandler(@Autowired @Qualifier("stateFirmwareVersionHandler") AbstractStateTopicHandler handler) { |
||||
super(handler); |
||||
} |
||||
|
||||
@Override |
||||
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException { |
||||
// Determine if it is live capacity data based on name.
|
||||
if (dataNode.containsKey(StateDataEnum.LIVE_CAPACITY.getDesc())) { |
||||
stateReceiver.setData(mapper.convertValue( |
||||
dataNode.get(StateDataEnum.LIVE_CAPACITY.getDesc()), |
||||
LiveCapacityReceiver.class)); |
||||
log.info("Analyze live stream capabilities."); |
||||
return stateReceiver; |
||||
} |
||||
return handler.handleState(dataNode, stateReceiver, sn); |
||||
} |
||||
} |
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.ChannelName; |
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver; |
||||
import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver; |
||||
import com.dji.sample.manage.model.receiver.LiveCapacityReceiver; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.integration.annotation.MessageEndpoint; |
||||
import org.springframework.integration.annotation.Router; |
||||
import org.springframework.integration.annotation.ServiceActivator; |
||||
import org.springframework.integration.annotation.Splitter; |
||||
import org.springframework.integration.mqtt.support.MqttHeaders; |
||||
import org.springframework.integration.router.MessageRouter; |
||||
import org.springframework.integration.router.PayloadTypeRouter; |
||||
import org.springframework.messaging.Message; |
||||
|
||||
import javax.annotation.Resource; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
|
||||
import static com.dji.sample.component.mqtt.model.TopicConst.*; |
||||
|
||||
/** |
||||
* |
||||
* @author sean.zhou |
||||
* @date 2021/11/17 |
||||
* @version 0.1 |
||||
*/ |
||||
@MessageEndpoint |
||||
@Slf4j |
||||
@Configuration |
||||
public class StateRouter { |
||||
|
||||
@Resource(name = "stateDeviceBasicHandler") |
||||
private AbstractStateTopicHandler handler; |
||||
|
||||
@Autowired |
||||
private ObjectMapper mapper; |
||||
|
||||
/** |
||||
* Handles the routing of state topic messages. Depending on the data, it is assigned to different channels for handling. |
||||
* @param message |
||||
* @return |
||||
* @throws IOException |
||||
*/ |
||||
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE, outputChannel = ChannelName.INBOUND_STATE_SPLITTER) |
||||
public CommonTopicReceiver<?> resolveStateData(Message<?> message) throws IOException { |
||||
byte[] payload = (byte[])message.getPayload(); |
||||
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString(); |
||||
|
||||
CommonTopicReceiver stateReceiver = mapper.readValue(payload, CommonTopicReceiver.class); |
||||
// Get the sn of the topic source.
|
||||
String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(), |
||||
topic.indexOf(STATE_SUF)); |
||||
|
||||
try { |
||||
Map<String, Object> data = (Map<String, Object>) (stateReceiver.getData()); |
||||
|
||||
return handler.handleState(data, stateReceiver, from); |
||||
|
||||
} catch (UnrecognizedPropertyException e) { |
||||
log.info("The {} data is not processed.", e.getPropertyName()); |
||||
} |
||||
return stateReceiver; |
||||
} |
||||
|
||||
/** |
||||
* Split the state message data to different channels for handling according to their different types. |
||||
* @param receiver state message |
||||
* @return |
||||
*/ |
||||
@Splitter(inputChannel = ChannelName.INBOUND_STATE_SPLITTER, outputChannel = ChannelName.INBOUND_STATE_ROUTER) |
||||
public Collection<Object> splitState(CommonTopicReceiver receiver) { |
||||
ArrayList<Object> type = new ArrayList<>(); |
||||
type.add(receiver.getData()); |
||||
return type; |
||||
} |
||||
|
||||
@Bean |
||||
@Router(inputChannel = ChannelName.INBOUND_STATE_ROUTER) |
||||
public MessageRouter resolveStateRouter() { |
||||
PayloadTypeRouter router = new PayloadTypeRouter(); |
||||
// Channel mapping for basic data.
|
||||
router.setChannelMapping(DeviceBasicReceiver.class.getName(), |
||||
ChannelName.INBOUND_STATE_BASIC); |
||||
// Channel mapping for live streaming capabilities.
|
||||
router.setChannelMapping(LiveCapacityReceiver.class.getName(), |
||||
ChannelName.INBOUND_STATE_CAPACITY); |
||||
router.setChannelMapping(FirmwareVersionReceiver.class.getName(), |
||||
ChannelName.INBOUND_STATE_FIRMWARE_VERSION); |
||||
router.setChannelMapping(Map.class.getName(), |
||||
ChannelName.DEFAULT); |
||||
return router; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
package com.dji.sample.component.mqtt.handler; |
||||
|
||||
import com.dji.sample.component.mqtt.model.ChannelName; |
||||
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; |
||||
import com.dji.sample.manage.model.receiver.StatusGatewayReceiver; |
||||
import com.fasterxml.jackson.core.type.TypeReference; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.integration.annotation.MessageEndpoint; |
||||
import org.springframework.integration.annotation.Router; |
||||
import org.springframework.integration.annotation.ServiceActivator; |
||||
import org.springframework.integration.mqtt.support.MqttHeaders; |
||||
import org.springframework.messaging.Message; |
||||
import org.springframework.util.CollectionUtils; |
||||
|
||||
import static com.dji.sample.component.mqtt.model.TopicConst.*; |
||||
|
||||
/** |
||||
* |
||||
* @author sean.zhou |
||||
* @date 2021/11/12 |
||||
* @version 0.1 |
||||
*/ |
||||
@MessageEndpoint |
||||
public class StatusRouter { |
||||
|
||||
@Autowired |
||||
private ObjectMapper mapper; |
||||
|
||||
/** |
||||
* Converts the status data sent by the gateway device into an object. |
||||
* @param message |
||||
* @return |
||||
*/ |
||||
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATUS, outputChannel = ChannelName.INBOUND_STATUS_ROUTER) |
||||
public CommonTopicReceiver<StatusGatewayReceiver> resolveStatus(Message<?> message) { |
||||
CommonTopicReceiver<StatusGatewayReceiver> statusReceiver = new CommonTopicReceiver<>(); |
||||
try { |
||||
statusReceiver = mapper.readValue( |
||||
(byte[])message.getPayload(), |
||||
new TypeReference<CommonTopicReceiver<StatusGatewayReceiver>>() {}); |
||||
|
||||
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString(); |
||||
|
||||
// set gateway's sn
|
||||
statusReceiver.getData().setSn( |
||||
topic.substring((BASIC_PRE + PRODUCT).length(), |
||||
topic.indexOf(STATUS_SUF))); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return statusReceiver; |
||||
} |
||||
|
||||
/** |
||||
* Handles the routing of status topic messages. Depending on the data, it is assigned to different channels for handling. |
||||
* @param receiver |
||||
* @return |
||||
*/ |
||||
@Router(inputChannel = ChannelName.INBOUND_STATUS_ROUTER) |
||||
public String resolveStatusRouter(CommonTopicReceiver<StatusGatewayReceiver> receiver) { |
||||
// Determine whether the drone is online or offline according to whether the data of the sub-device is empty.
|
||||
return CollectionUtils.isEmpty(receiver.getData().getSubDevices()) ? |
||||
ChannelName.INBOUND_STATUS_OFFLINE : ChannelName.INBOUND_STATUS_ONLINE; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import java.util.concurrent.locks.LockSupport; |
||||
|
||||
/** |
||||
* The demo is only for functional closure, which is not recommended. |
||||
* @author sean.zhou |
||||
* @date 2021/11/22 |
||||
* @version 0.1 |
||||
*/ |
||||
public class Chan<T> { |
||||
|
||||
private static final long THREAD_WAIT_TIME = 1000_000 * 2000; |
||||
|
||||
private volatile T data; |
||||
|
||||
private volatile Thread t; |
||||
|
||||
private Chan () { |
||||
|
||||
} |
||||
|
||||
public static Chan getInstance() { |
||||
return ChanSingleton.INSTANCE; |
||||
} |
||||
|
||||
public T get(Object blocker) { |
||||
this.t = Thread.currentThread(); |
||||
LockSupport.parkNanos(blocker, THREAD_WAIT_TIME); |
||||
this.t = null; |
||||
return data; |
||||
} |
||||
|
||||
public void put(T data) { |
||||
this.data = data; |
||||
if (t == null) { |
||||
return; |
||||
} |
||||
LockSupport.unpark(t); |
||||
} |
||||
|
||||
private static class ChanSingleton { |
||||
private static final Chan<?> INSTANCE = new Chan<>(); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import com.dji.sample.common.model.ResponseResult; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/14 |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
public class ErrorInfoReply { |
||||
|
||||
private String sn; |
||||
|
||||
private Integer errCode; |
||||
|
||||
public static ErrorInfoReply success(String sn) { |
||||
return new ErrorInfoReply(sn, ResponseResult.CODE_SUCCESS); |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/1 |
||||
*/ |
||||
public enum EventsMethodEnum { |
||||
|
||||
FLIGHT_TASK_PROGRESS("flighttask_progress"), |
||||
|
||||
FILE_UPLOAD_CALLBACK("file_upload_callback"), |
||||
|
||||
HMS("hms"), |
||||
|
||||
UNKNOWN("Unknown"); |
||||
|
||||
private String method; |
||||
|
||||
EventsMethodEnum(String method) { |
||||
this.method = method; |
||||
} |
||||
|
||||
public String getMethod() { |
||||
return method; |
||||
} |
||||
|
||||
public static EventsMethodEnum find(String method) { |
||||
return Arrays.stream(EventsMethodEnum.values()) |
||||
.filter(methodEnum -> methodEnum.method.equals(method)) |
||||
.findAny() |
||||
.orElse(UNKNOWN); |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/9 |
||||
*/ |
||||
@Data |
||||
@JsonIgnoreProperties(ignoreUnknown = true) |
||||
public class EventsReceiver<T> { |
||||
|
||||
private Integer result; |
||||
|
||||
private T output; |
||||
|
||||
private String bid; |
||||
|
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/14 |
||||
*/ |
||||
public final class MapKeyConst { |
||||
|
||||
private MapKeyConst(){ |
||||
|
||||
} |
||||
|
||||
public static final String ORGANIZATION_NAME = "organization_name"; |
||||
|
||||
public static final String DEVICES = "devices"; |
||||
|
||||
public static final String SN = "sn"; |
||||
|
||||
public static final String BIND_DEVICES = "bind_devices"; |
||||
|
||||
public static final String ERR_INFOS = "err_infos"; |
||||
|
||||
public static final String TINY_FINGERPRINTS = "tiny_fingerprints"; |
||||
|
||||
public static final String BIND_STATUS = "bind_status"; |
||||
|
||||
public static final String LIST = "list"; |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/25 |
||||
*/ |
||||
public enum RequestsMethodEnum { |
||||
|
||||
STORAGE_CONFIG_GET("storage_config_get"), |
||||
|
||||
AIRPORT_BIND_STATUS("airport_bind_status"), |
||||
|
||||
AIRPORT_ORGANIZATION_BIND("airport_organization_bind"), |
||||
|
||||
AIRPORT_ORGANIZATION_GET("airport_organization_get"), |
||||
|
||||
UNKNOWN("Unknown"); |
||||
|
||||
private String method; |
||||
|
||||
RequestsMethodEnum(String method) { |
||||
this.method = method; |
||||
} |
||||
|
||||
public String getMethod() { |
||||
return method; |
||||
} |
||||
|
||||
public static RequestsMethodEnum find(String method) { |
||||
return Arrays.stream(RequestsMethodEnum.values()) |
||||
.filter(methodEnum -> methodEnum.method.equals(method)) |
||||
.findAny() |
||||
.orElse(UNKNOWN); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import com.dji.sample.common.error.IErrorInfo; |
||||
import com.dji.sample.common.model.ResponseResult; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/13 |
||||
*/ |
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class RequestsReply<T> { |
||||
|
||||
private Integer result; |
||||
|
||||
private T output; |
||||
|
||||
|
||||
public static RequestsReply error(IErrorInfo errorInfo) { |
||||
return RequestsReply.builder() |
||||
.result(errorInfo.getErrorCode()) |
||||
.output(errorInfo.getErrorMsg()) |
||||
.build(); |
||||
} |
||||
|
||||
public static <T> RequestsReply success(T data) { |
||||
return RequestsReply.builder() |
||||
.result(ResponseResult.CODE_SUCCESS) |
||||
.output(data) |
||||
.build(); |
||||
} |
||||
public static RequestsReply success() { |
||||
return RequestsReply.builder() |
||||
.result(ResponseResult.CODE_SUCCESS) |
||||
.build(); |
||||
} |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean.zhou |
||||
* @version 0.1 |
||||
* @date 2021/11/22 |
||||
*/ |
||||
@Data |
||||
@JsonIgnoreProperties(ignoreUnknown = true) |
||||
public class ServiceReply<T> { |
||||
|
||||
private Integer result; |
||||
|
||||
private T info; |
||||
|
||||
private T output; |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
/** |
||||
* @author sean.zhou |
||||
* @date 2021/11/22 |
||||
* @version 0.1 |
||||
*/ |
||||
public enum ServicesMethodEnum { |
||||
|
||||
LIVE_START_PUSH("live_start_push"), |
||||
|
||||
LIVE_STOP_PUSH("live_stop_push"), |
||||
|
||||
LIVE_SET_QUALITY("live_set_quality"), |
||||
|
||||
FLIGHTTASK_CREATE("flighttask_create"), |
||||
|
||||
UNKNOWN("unknown"); |
||||
|
||||
private String method; |
||||
|
||||
ServicesMethodEnum(String method) { |
||||
this.method = method; |
||||
} |
||||
|
||||
public String getMethod() { |
||||
return method; |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package com.dji.sample.component.mqtt.model; |
||||
|
||||
/** |
||||
* |
||||
* @author sean.zhou |
||||
* @date 2021/11/18 |
||||
* @version 0.1 |
||||
*/ |
||||
public enum StateDataEnum { |
||||
|
||||
FIRMWARE_VERSION("firmware_version"), |
||||
|
||||
LIVE_CAPACITY("live_capacity"), |
||||
|
||||
PAYLOADS("payloads"); |
||||
|
||||
private String desc; |
||||
|
||||
StateDataEnum(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return this.desc; |
||||
} |
||||
} |
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
package com.dji.sample.component.oss.model; |
||||
|
||||
import lombok.Data; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 0.2 |
||||
* @date 2021/12/9 |
||||
*/ |
||||
@ConfigurationProperties(prefix = "oss") |
||||
@Component |
||||
@Data |
||||
public class OssConfiguration { |
||||
|
||||
/** |
||||
* @see com.dji.sample.component.oss.model.enums.OssTypeEnum |
||||
*/ |
||||
private String provider; |
||||
|
||||
/** |
||||
* Whether to use the object storage service. |
||||
*/ |
||||
private boolean enable; |
||||
|
||||
/** |
||||
* The protocol needs to be included at the beginning of the address. |
||||
*/ |
||||
private String endpoint; |
||||
|
||||
private String accessKey; |
||||
|
||||
private String secretKey; |
||||
|
||||
private String region; |
||||
|
||||
private Long expire; |
||||
|
||||
private String roleSessionName; |
||||
|
||||
private String roleArn; |
||||
|
||||
private String bucket; |
||||
|
||||
private String objectDirPrefix; |
||||
|
||||
public void setProvider(String provider) { |
||||
this.provider = provider; |
||||
} |
||||
|
||||
public void setEnable(boolean enable) { |
||||
this.enable = enable; |
||||
} |
||||
|
||||
public void setEndpoint(String endpoint) { |
||||
this.endpoint = endpoint; |
||||
} |
||||
|
||||
public void setAccessKey(String accessKey) { |
||||
this.accessKey = accessKey; |
||||
} |
||||
|
||||
public void setSecretKey(String secretKey) { |
||||
this.secretKey = secretKey; |
||||
} |
||||
|
||||
public void setRegion(String region) { |
||||
this.region = region; |
||||
} |
||||
|
||||
public void setExpire(Long expire) { |
||||
this.expire = expire; |
||||
} |
||||
|
||||
public void setRoleSessionName(String roleSessionName) { |
||||
this.roleSessionName = roleSessionName; |
||||
} |
||||
|
||||
public void setRoleArn(String roleArn) { |
||||
this.roleArn = roleArn; |
||||
} |
||||
|
||||
public void setBucket(String bucket) { |
||||
this.bucket = bucket; |
||||
} |
||||
|
||||
public void setObjectDirPrefix(String objectDirPrefix) { |
||||
this.objectDirPrefix = objectDirPrefix; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
package com.dji.sample.component.oss.model.enums; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/30 |
||||
*/ |
||||
public enum OssTypeEnum { |
||||
|
||||
ALIYUN("ali"), |
||||
|
||||
AWS("aws"), |
||||
|
||||
/* |
||||
* MinIO is temporarily unavailable. |
||||
*/ |
||||
MINIO("minio"); |
||||
|
||||
private String type; |
||||
|
||||
OssTypeEnum(String type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getType() { |
||||
return type; |
||||
} |
||||
} |
@ -0,0 +1,135 @@
@@ -0,0 +1,135 @@
|
||||
package com.dji.sample.component.oss.service.impl; |
||||
|
||||
import com.amazonaws.HttpMethod; |
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider; |
||||
import com.amazonaws.auth.BasicAWSCredentials; |
||||
import com.amazonaws.services.s3.AmazonS3; |
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder; |
||||
import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration; |
||||
import com.amazonaws.services.s3.model.CORSRule; |
||||
import com.amazonaws.services.s3.model.S3Object; |
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; |
||||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; |
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; |
||||
import com.amazonaws.services.securitytoken.model.AssumeRoleResult; |
||||
import com.amazonaws.services.securitytoken.model.Credentials; |
||||
import com.dji.sample.component.AuthInterceptor; |
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
||||
import com.dji.sample.component.oss.model.enums.OssTypeEnum; |
||||
import com.dji.sample.component.oss.service.IOssService; |
||||
import com.dji.sample.media.model.CredentialsDTO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.net.URL; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/27 |
||||
*/ |
||||
@Service |
||||
public class AmazonS3ServiceImpl implements IOssService { |
||||
|
||||
@Autowired |
||||
private OssConfiguration configuration; |
||||
|
||||
@Override |
||||
public String getOssType() { |
||||
return OssTypeEnum.AWS.getType(); |
||||
} |
||||
|
||||
@Override |
||||
public CredentialsDTO getCredentials() { |
||||
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard() |
||||
.withCredentials(new AWSStaticCredentialsProvider( |
||||
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey()))) |
||||
.withRegion(configuration.getRegion()).build(); |
||||
|
||||
AssumeRoleRequest request = new AssumeRoleRequest() |
||||
.withRoleArn(configuration.getRoleArn()) |
||||
.withRoleSessionName(configuration.getRoleSessionName()) |
||||
.withDurationSeconds(Math.toIntExact(configuration.getExpire())); |
||||
AssumeRoleResult result = stsClient.assumeRole(request); |
||||
Credentials credentials = result.getCredentials(); |
||||
stsClient.shutdown(); |
||||
return new CredentialsDTO(credentials); |
||||
} |
||||
|
||||
@Override |
||||
public URL getObjectUrl(String bucket, String objectKey) { |
||||
AmazonS3 client = this.createClient(); |
||||
URL url = client.generatePresignedUrl(bucket, objectKey, |
||||
new Date(System.currentTimeMillis() + configuration.getExpire() * 1000), HttpMethod.GET); |
||||
client.shutdown(); |
||||
return url; |
||||
} |
||||
|
||||
@Override |
||||
public Boolean deleteObject(String bucket, String objectKey) { |
||||
AmazonS3 client = this.createClient(); |
||||
client.deleteObject(bucket, objectKey); |
||||
client.shutdown(); |
||||
return true; |
||||
} |
||||
|
||||
public byte[] getObject(String bucket, String objectKey) { |
||||
AmazonS3 client = this.createClient(); |
||||
S3Object object = client.getObject(bucket, objectKey); |
||||
InputStream stream = object.getObjectContent().getDelegateStream(); |
||||
try { |
||||
return stream.readAllBytes(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
try { |
||||
stream.close(); |
||||
client.shutdown(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
return new byte[0]; |
||||
} |
||||
|
||||
private AmazonS3 createClient() { |
||||
return AmazonS3ClientBuilder.standard() |
||||
.withCredentials( |
||||
new AWSStaticCredentialsProvider( |
||||
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey()))) |
||||
.withRegion(configuration.getRegion()) |
||||
.build(); |
||||
} |
||||
|
||||
/** |
||||
* Configuring cross-origin resource sharing |
||||
*/ |
||||
@PostConstruct |
||||
private void configCORS() { |
||||
if (!configuration.isEnable() || !OssTypeEnum.AWS.getType().equals(configuration.getProvider())) { |
||||
return; |
||||
} |
||||
List<CORSRule.AllowedMethods> allowedMethods = new ArrayList<>(); |
||||
allowedMethods.add(CORSRule.AllowedMethods.GET); |
||||
allowedMethods.add(CORSRule.AllowedMethods.POST); |
||||
allowedMethods.add(CORSRule.AllowedMethods.DELETE); |
||||
|
||||
CORSRule rule = new CORSRule() |
||||
.withId("CORSAccessRule") |
||||
.withAllowedOrigins(List.of("*")) |
||||
.withAllowedHeaders(List.of(AuthInterceptor.PARAM_TOKEN)) |
||||
.withAllowedMethods(allowedMethods); |
||||
|
||||
AmazonS3 client = this.createClient(); |
||||
|
||||
client.setBucketCrossOriginConfiguration(this.configuration.getBucket(), |
||||
new BucketCrossOriginConfiguration().withRules(rule)); |
||||
client.shutdown(); |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package com.dji.sample.component.oss.service.impl; |
||||
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
||||
import org.aspectj.lang.annotation.Aspect; |
||||
import org.aspectj.lang.annotation.Before; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/20 |
||||
*/ |
||||
@Component |
||||
@Aspect |
||||
public class OssAspectHandler { |
||||
|
||||
@Autowired |
||||
private OssServiceContext ossServiceContext; |
||||
|
||||
@Autowired |
||||
private OssConfiguration configuration; |
||||
|
||||
@Before("execution(public * com.dji.sample.component.oss.service.impl.OssServiceContext.*(..))") |
||||
public void before() { |
||||
if (!this.configuration.isEnable()) { |
||||
throw new IllegalArgumentException("Please enable OssConfiguration."); |
||||
} |
||||
if (this.ossServiceContext.getOssService() == null) { |
||||
throw new IllegalArgumentException("Please check the OssConfiguration configuration."); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
package com.dji.sample.component.oss.service.impl; |
||||
|
||||
import com.dji.sample.component.oss.model.OssConfiguration; |
||||
import com.dji.sample.component.oss.model.enums.OssTypeEnum; |
||||
import com.dji.sample.component.oss.service.IOssService; |
||||
import com.dji.sample.media.model.CredentialsDTO; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.net.URL; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/30 |
||||
*/ |
||||
@Service |
||||
public class OssServiceContext { |
||||
|
||||
private IOssService ossService; |
||||
|
||||
private OssConfiguration configuration; |
||||
|
||||
@Autowired |
||||
public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) { |
||||
this.configuration = configuration; |
||||
if (!configuration.isEnable()) { |
||||
return; |
||||
} |
||||
this.ossService = ossServices.stream() |
||||
.filter(ossService -> ossService.getOssType().equals(configuration.getProvider())) |
||||
.findFirst() |
||||
.orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " + |
||||
Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray()))); |
||||
} |
||||
|
||||
IOssService getOssService() { |
||||
return this.ossService; |
||||
} |
||||
|
||||
public CredentialsDTO getCredentials() { |
||||
return this.ossService.getCredentials(); |
||||
} |
||||
|
||||
public URL getObjectUrl(String bucket, String objectKey) { |
||||
return this.ossService.getObjectUrl(bucket, objectKey); |
||||
} |
||||
|
||||
public Boolean deleteObject(String bucket, String objectKey) { |
||||
return this.ossService.deleteObject(bucket, objectKey); |
||||
} |
||||
|
||||
public byte[] getObject(String bucket, String objectKey) { |
||||
return this.ossService.getObject(bucket, objectKey); |
||||
} |
||||
} |
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
package com.dji.sample.component.redis; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude; |
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
||||
import com.fasterxml.jackson.databind.MapperFeature; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy; |
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; |
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; |
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; |
||||
import org.springframework.data.redis.serializer.StringRedisSerializer; |
||||
|
||||
import java.time.LocalDateTime; |
||||
import java.time.format.DateTimeFormatter; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/19 |
||||
*/ |
||||
@Configuration |
||||
@EnableRedisRepositories |
||||
public class RedisConfiguration { |
||||
|
||||
@Bean |
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { |
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); |
||||
redisTemplate.setConnectionFactory(factory); |
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
JavaTimeModule timeModule = new JavaTimeModule(); |
||||
timeModule.addDeserializer(LocalDateTime.class, |
||||
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
||||
timeModule.addSerializer(LocalDateTime.class, |
||||
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
||||
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS); |
||||
objectMapper.registerModules(timeModule); |
||||
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), |
||||
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); |
||||
|
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); |
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); |
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
||||
|
||||
|
||||
StringRedisSerializer serializer = new StringRedisSerializer(); |
||||
redisTemplate.setKeySerializer(serializer); |
||||
redisTemplate.setHashKeySerializer(serializer); |
||||
|
||||
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper); |
||||
redisTemplate.setValueSerializer(jsonRedisSerializer); |
||||
redisTemplate.setHashValueSerializer(jsonRedisSerializer); |
||||
redisTemplate.afterPropertiesSet(); |
||||
return redisTemplate; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
package com.dji.sample.component.redis; |
||||
|
||||
import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/21 |
||||
*/ |
||||
public final class RedisConst { |
||||
|
||||
private RedisConst() { |
||||
|
||||
} |
||||
|
||||
public static final Integer DEVICE_ALIVE_SECOND = 60; |
||||
|
||||
public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24; |
||||
|
||||
public static final String ONLINE_PREFIX = "online:"; |
||||
|
||||
public static final String DEVICE_ONLINE_PREFIX = ONLINE_PREFIX + DeviceDomainEnum.SUB_DEVICE + ":"; |
||||
|
||||
public static final String WEBSOCKET_PREFIX = "webSocket:"; |
||||
|
||||
public static final String WEBSOCKET_ALL = "webSocket:all"; |
||||
|
||||
public static final String HMS_PREFIX = "hms:"; |
||||
} |
@ -0,0 +1,187 @@
@@ -0,0 +1,187 @@
|
||||
package com.dji.sample.component.redis; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.data.redis.core.RedisTemplate; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.util.List; |
||||
import java.util.Set; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/19 |
||||
*/ |
||||
@Component |
||||
public class RedisOpsUtils { |
||||
|
||||
@Autowired |
||||
private RedisTemplate<String, Object> redisTemplate; |
||||
|
||||
/** |
||||
* HSET |
||||
* @param key |
||||
* @param field |
||||
* @param value |
||||
*/ |
||||
public void hashSet(String key, String field, Object value) { |
||||
redisTemplate.opsForHash().put(key, field, value); |
||||
} |
||||
|
||||
/** |
||||
* HGET |
||||
* @param key |
||||
* @param field |
||||
* @return |
||||
*/ |
||||
public Object hashGet(String key, String field) { |
||||
return redisTemplate.opsForHash().get(key, field); |
||||
} |
||||
|
||||
/** |
||||
* HKEYS |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public Set<Object> hashKeys(String key) { |
||||
return redisTemplate.opsForHash().keys(key); |
||||
} |
||||
|
||||
/** |
||||
* HEXISTS |
||||
* @param key |
||||
* @param field |
||||
* @return |
||||
*/ |
||||
public boolean hashCheck(String key, String field) { |
||||
return redisTemplate.opsForHash().hasKey(key, field); |
||||
} |
||||
|
||||
/** |
||||
* HDEL |
||||
* @param key |
||||
* @param fields |
||||
* @return |
||||
*/ |
||||
public boolean hashDel(String key, Object[] fields) { |
||||
return redisTemplate.opsForHash().delete(key, fields) > 0; |
||||
} |
||||
|
||||
/** |
||||
* EXPIRE |
||||
* @param key |
||||
* @param timeout |
||||
* @return |
||||
*/ |
||||
public boolean expireKey(String key, long timeout) { |
||||
return redisTemplate.expire(key, timeout, TimeUnit.SECONDS); |
||||
} |
||||
|
||||
/** |
||||
* SET |
||||
* @param key |
||||
* @param value |
||||
*/ |
||||
public void set(String key, Object value) { |
||||
redisTemplate.opsForValue().set(key, value); |
||||
} |
||||
|
||||
/** |
||||
* GET |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public Object get(String key) { |
||||
return redisTemplate.opsForValue().get(key); |
||||
} |
||||
|
||||
/** |
||||
* SETEX |
||||
* @param key |
||||
* @param value |
||||
* @param expire |
||||
*/ |
||||
public void setWithExpire(String key, Object value, long expire) { |
||||
redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS); |
||||
} |
||||
|
||||
/** |
||||
* TTL |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public long getExpire(String key) { |
||||
return redisTemplate.getExpire(key, TimeUnit.SECONDS); |
||||
} |
||||
|
||||
/** |
||||
* EXISTS |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public boolean checkExist(String key) { |
||||
return redisTemplate.hasKey(key); |
||||
} |
||||
|
||||
/** |
||||
* DEL |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public boolean del(String key) { |
||||
return this.checkExist(key) && redisTemplate.delete(key); |
||||
} |
||||
|
||||
/** |
||||
* KEYS |
||||
* @param pattern |
||||
* @return |
||||
*/ |
||||
public Set<String> getAllKeys(String pattern) { |
||||
return redisTemplate.keys(pattern); |
||||
} |
||||
|
||||
/** |
||||
* RPUSH |
||||
* @param key |
||||
* @param value |
||||
*/ |
||||
public void listRPush(String key, Object... value) { |
||||
if (value.length == 0) { |
||||
return; |
||||
} |
||||
for (Object val : value) { |
||||
redisTemplate.opsForList().rightPush(key, val); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* LRANGE |
||||
* @param key |
||||
* @param start |
||||
* @param end |
||||
* @return |
||||
*/ |
||||
public List<Object> listGet(String key, long start, long end) { |
||||
return redisTemplate.opsForList().range(key, start, end); |
||||
} |
||||
|
||||
/** |
||||
* LRANGE |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public List<Object> listGetAll(String key) { |
||||
return redisTemplate.opsForList().range(key, 0, -1); |
||||
} |
||||
|
||||
/** |
||||
* LLen |
||||
* @param key |
||||
* @return |
||||
*/ |
||||
public Long listLen(String key) { |
||||
return redisTemplate.opsForList().size(key); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
package com.dji.sample.component.websocket.service; |
||||
|
||||
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/25 |
||||
*/ |
||||
public interface IWebSocketManageService { |
||||
|
||||
void put(String key, ConcurrentWebSocketSession val); |
||||
|
||||
void remove(String key, String sessionId); |
||||
|
||||
Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId); |
||||
|
||||
Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType); |
||||
|
||||
Long getConnectedCount(); |
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
package com.dji.sample.component.websocket.service.impl; |
||||
|
||||
import com.dji.sample.component.redis.RedisConst; |
||||
import com.dji.sample.component.redis.RedisOpsUtils; |
||||
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession; |
||||
import com.dji.sample.component.websocket.service.IWebSocketManageService; |
||||
import com.dji.sample.manage.model.enums.UserTypeEnum; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.Objects; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/25 |
||||
*/ |
||||
@Slf4j |
||||
@Service |
||||
public class WebSocketManageServiceImpl implements IWebSocketManageService { |
||||
|
||||
private static final ConcurrentHashMap<String, ConcurrentWebSocketSession> SESSIONS = new ConcurrentHashMap<>(16); |
||||
|
||||
@Autowired |
||||
private RedisOpsUtils redisOps; |
||||
|
||||
@Override |
||||
public void put(String key, ConcurrentWebSocketSession val) { |
||||
String[] name = key.split("/"); |
||||
if (name.length != 3) { |
||||
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]"); |
||||
return; |
||||
} |
||||
String sessionId = val.getId(); |
||||
String workspaceKey = RedisConst.WEBSOCKET_PREFIX + name[0]; |
||||
String userTypeKey = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc(); |
||||
redisOps.hashSet(workspaceKey, sessionId, name[2]); |
||||
redisOps.hashSet(userTypeKey, sessionId, name[2]); |
||||
SESSIONS.put(sessionId, val); |
||||
redisOps.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND); |
||||
redisOps.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND); |
||||
} |
||||
|
||||
@Override |
||||
public void remove(String key, String sessionId) { |
||||
String[] name = key.split("/"); |
||||
if (name.length != 3) { |
||||
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]"); |
||||
return; |
||||
} |
||||
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId}); |
||||
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])), new String[] {sessionId}); |
||||
SESSIONS.remove(sessionId); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId) { |
||||
if (!StringUtils.hasText(workspaceId)) { |
||||
return Collections.emptySet(); |
||||
} |
||||
String key = RedisConst.WEBSOCKET_PREFIX + workspaceId; |
||||
|
||||
return redisOps.hashKeys(key) |
||||
.stream() |
||||
.map(SESSIONS::get) |
||||
.filter(Objects::nonNull) |
||||
.collect(Collectors.toSet()); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType) { |
||||
String key = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(userType).getDesc(); |
||||
return redisOps.hashKeys(key) |
||||
.stream() |
||||
.map(SESSIONS::get) |
||||
.filter(Objects::nonNull) |
||||
.collect(Collectors.toSet()); |
||||
} |
||||
|
||||
@Override |
||||
public Long getConnectedCount() { |
||||
return SESSIONS.mappingCount(); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package com.dji.sample.configuration; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude; |
||||
import com.fasterxml.jackson.core.JsonGenerator; |
||||
import com.fasterxml.jackson.core.JsonParser; |
||||
import com.fasterxml.jackson.databind.*; |
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; |
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; |
||||
|
||||
import java.io.IOException; |
||||
import java.time.LocalDateTime; |
||||
import java.time.format.DateTimeFormatter; |
||||
|
||||
@Configuration |
||||
public class SpringBeanConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean(ObjectMapper.class) |
||||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { |
||||
ObjectMapper objectMapper = builder.createXmlMapper(false).build(); |
||||
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); |
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); |
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
||||
|
||||
JavaTimeModule timeModule = new JavaTimeModule(); |
||||
timeModule.addDeserializer(LocalDateTime.class, |
||||
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
||||
timeModule.addSerializer(LocalDateTime.class, |
||||
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); |
||||
|
||||
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS); |
||||
objectMapper.registerModules(timeModule); |
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
||||
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); |
||||
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); |
||||
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() { |
||||
@Override |
||||
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
||||
gen.writeString(""); |
||||
} |
||||
}); |
||||
return objectMapper; |
||||
} |
||||
} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
package com.dji.sample.manage.controller; |
||||
|
||||
import com.dji.sample.common.model.PaginationData; |
||||
import com.dji.sample.common.model.ResponseResult; |
||||
import com.dji.sample.manage.model.dto.DeviceHmsDTO; |
||||
import com.dji.sample.manage.model.param.DeviceHmsQueryParam; |
||||
import com.dji.sample.manage.service.IDeviceHmsService; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/7 |
||||
*/ |
||||
|
||||
@RestController |
||||
@Slf4j |
||||
@RequestMapping("${url.manage.prefix}${url.manage.version}/devices") |
||||
public class DeviceHmsController { |
||||
|
||||
@Autowired |
||||
private IDeviceHmsService deviceHmsService; |
||||
|
||||
@GetMapping("/{workspace_id}/devices/hms") |
||||
public ResponseResult<PaginationData<DeviceHmsDTO>> getBoundDevicesWithDomain(DeviceHmsQueryParam param, |
||||
@PathVariable("workspace_id") String workspaceId) { |
||||
PaginationData<DeviceHmsDTO> devices = deviceHmsService.getDeviceHmsByParam(param); |
||||
|
||||
return ResponseResult.success(devices); |
||||
} |
||||
|
||||
@PutMapping("/{workspace_id}/devices/hms/{device_sn}") |
||||
public ResponseResult updateReadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) { |
||||
deviceHmsService.updateUnreadHms(deviceSn); |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
@GetMapping("/{workspace_id}/devices/hms/{device_sn}") |
||||
public ResponseResult<List<DeviceHmsDTO>> getUnreadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) { |
||||
PaginationData<DeviceHmsDTO> paginationData = deviceHmsService.getDeviceHmsByParam( |
||||
DeviceHmsQueryParam.builder() |
||||
.deviceSn(new HashSet<>(Set.of(deviceSn))) |
||||
.updateTime(0L) |
||||
.build()); |
||||
return ResponseResult.success(paginationData.getList()); |
||||
} |
||||
} |
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
package com.dji.sample.manage.dao; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.dji.sample.manage.model.entity.DeviceHmsEntity; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/6 |
||||
*/ |
||||
public interface IDeviceHmsMapper extends BaseMapper<DeviceHmsEntity> { |
||||
} |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package com.dji.sample.manage.model.common; |
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/7 |
||||
*/ |
||||
@Slf4j |
||||
@Component |
||||
public class HmsJsonUtil { |
||||
|
||||
private static ObjectMapper mapper; |
||||
|
||||
@Autowired |
||||
public void setMapper(ObjectMapper mapper) { |
||||
HmsJsonUtil.mapper = mapper; |
||||
} |
||||
|
||||
private static JsonNode nodes; |
||||
|
||||
private HmsJsonUtil(){ |
||||
|
||||
} |
||||
|
||||
@PostConstruct |
||||
private void loadJsonFile() { |
||||
try (InputStream inputStream = new ClassPathResource("hms.json").getInputStream()){ |
||||
nodes = mapper.readTree(inputStream); |
||||
} catch (IOException e) { |
||||
log.error("hms.json failed to load."); |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public static HmsMessage get(String key) { |
||||
return mapper.convertValue(nodes.get(key), HmsMessage.class); |
||||
} |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
package com.dji.sample.manage.model.common; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/7 |
||||
*/ |
||||
@Data |
||||
public class HmsMessage { |
||||
|
||||
private String zh; |
||||
|
||||
private String en; |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
package com.dji.sample.manage.model.dto; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/8 |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Builder |
||||
public class DeviceHmsDTO implements Cloneable { |
||||
|
||||
private String hmsId; |
||||
|
||||
private String tid; |
||||
|
||||
private String bid; |
||||
|
||||
private String sn; |
||||
|
||||
private Integer level; |
||||
|
||||
private Integer module; |
||||
|
||||
private String key; |
||||
|
||||
private String messageZh; |
||||
|
||||
private String messageEn; |
||||
|
||||
private LocalDateTime createTime; |
||||
|
||||
private LocalDateTime updateTime; |
||||
|
||||
@Override |
||||
public DeviceHmsDTO clone() { |
||||
try { |
||||
return (DeviceHmsDTO) super.clone(); |
||||
} catch (CloneNotSupportedException e) { |
||||
return DeviceHmsDTO.builder() |
||||
.sn(this.sn) |
||||
.bid(this.bid) |
||||
.tid(this.tid) |
||||
.createTime(this.createTime) |
||||
.updateTime(this.updateTime) |
||||
.build(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
package com.dji.sample.manage.model.dto; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/18 |
||||
*/ |
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class UserListDTO { |
||||
|
||||
private String userId; |
||||
|
||||
private String username; |
||||
|
||||
private String workspaceName; |
||||
|
||||
private String userType; |
||||
|
||||
private String mqttUsername; |
||||
|
||||
private String mqttPassword; |
||||
|
||||
private LocalDateTime createTime; |
||||
} |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
package com.dji.sample.manage.model.entity; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/6 |
||||
*/ |
||||
@Data |
||||
@Builder |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@TableName(value = "manage_device_hms") |
||||
public class DeviceHmsEntity implements Serializable, Cloneable { |
||||
|
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private Long id; |
||||
|
||||
@TableField("hms_id") |
||||
private String hmsId; |
||||
|
||||
@TableField("tid") |
||||
private String tid; |
||||
|
||||
@TableField("bid") |
||||
private String bid; |
||||
|
||||
@TableField("sn") |
||||
private String sn; |
||||
|
||||
@TableField("level") |
||||
private Integer level; |
||||
|
||||
@TableField("module") |
||||
private Integer module; |
||||
|
||||
@TableField("hms_key") |
||||
private String hmsKey; |
||||
|
||||
@TableField("message_zh") |
||||
private String messageZh; |
||||
|
||||
@TableField("message_en") |
||||
private String messageEn; |
||||
|
||||
@TableField("create_time") |
||||
private Long createTime; |
||||
|
||||
@TableField("update_time") |
||||
private Long updateTime; |
||||
|
||||
@Override |
||||
public DeviceHmsEntity clone() { |
||||
try { |
||||
return (DeviceHmsEntity) super.clone(); |
||||
} catch (CloneNotSupportedException e) { |
||||
return DeviceHmsEntity.builder() |
||||
.bid(this.getBid()) |
||||
.tid(this.getTid()) |
||||
.createTime(this.getCreateTime()) |
||||
.updateTime(this.getUpdateTime()) |
||||
.sn(this.getSn()) |
||||
.build(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
package com.dji.sample.manage.model.enums; |
||||
|
||||
import lombok.Getter; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/7 |
||||
*/ |
||||
@Getter |
||||
public enum HmsEnum { |
||||
|
||||
IN_THE_SKY("_in_the_sky", 1); |
||||
|
||||
private int val; |
||||
|
||||
private String text; |
||||
|
||||
HmsEnum(String text, int val) { |
||||
this.text = text; |
||||
this.val = val; |
||||
} |
||||
|
||||
@Getter |
||||
public enum MessageLanguage { |
||||
|
||||
EN("en"), |
||||
|
||||
ZH("zh"); |
||||
|
||||
String language; |
||||
|
||||
MessageLanguage(String language) { |
||||
this.language = language; |
||||
} |
||||
} |
||||
|
||||
@Getter |
||||
public enum DomainType { |
||||
DRONE_NEST("drone_nest"), |
||||
|
||||
DRONE("drone"); |
||||
|
||||
private String domain; |
||||
|
||||
DomainType(String domain) { |
||||
this.domain = domain; |
||||
} |
||||
|
||||
} |
||||
|
||||
@Getter |
||||
public enum HmsFaqIdEnum { |
||||
|
||||
FPV_TIP("fpv_tip_"); |
||||
|
||||
private String text; |
||||
|
||||
HmsFaqIdEnum(String text) { |
||||
this.text = text; |
||||
} |
||||
|
||||
} |
||||
|
||||
@Getter |
||||
public enum HmsBatteryIndexEnum { |
||||
LEFT(0, "left", "左"), |
||||
|
||||
RIGHT(1, "right", "右"), |
||||
|
||||
UNKNOWN(-1, "unknown", "未知"); |
||||
|
||||
private int val; |
||||
|
||||
private String en; |
||||
|
||||
private String zh; |
||||
|
||||
HmsBatteryIndexEnum(int val, String en, String zh) { |
||||
this.val = val; |
||||
this.en = en; |
||||
this.zh = zh; |
||||
} |
||||
|
||||
public static HmsBatteryIndexEnum find(int val) { |
||||
return Arrays.stream(HmsBatteryIndexEnum.values()) |
||||
.filter(battery -> battery.val == val) |
||||
.findAny() |
||||
.orElse(UNKNOWN); |
||||
} |
||||
} |
||||
|
||||
@Getter |
||||
public enum HmsDockCoverIndexEnum { |
||||
LEFT(0, "left", "左"), |
||||
|
||||
RIGHT(1, "right", "右"), |
||||
|
||||
UNKNOWN(-1, "unknown", "未知"); |
||||
|
||||
private int val; |
||||
|
||||
private String en; |
||||
|
||||
private String zh; |
||||
|
||||
HmsDockCoverIndexEnum(int val, String en, String zh) { |
||||
this.val = val; |
||||
this.en = en; |
||||
this.zh = zh; |
||||
} |
||||
|
||||
public static HmsDockCoverIndexEnum find(int val) { |
||||
return Arrays.stream(HmsDockCoverIndexEnum.values()) |
||||
.filter(dockCover -> dockCover.val == val) |
||||
.findAny() |
||||
.orElse(UNKNOWN); |
||||
} |
||||
} |
||||
|
||||
@Getter |
||||
public enum HmsChargingRodIndexEnum { |
||||
|
||||
FRONT(0, "front", "前"), |
||||
|
||||
BACK(1, "back", "后"), |
||||
|
||||
LEFT(2, "left", "左"), |
||||
|
||||
RIGHT(3, "right", "右"), |
||||
|
||||
UNKNOWN(-1, "unknown", "未知"); |
||||
|
||||
private int val; |
||||
|
||||
private String en; |
||||
|
||||
private String zh; |
||||
|
||||
HmsChargingRodIndexEnum(int val, String en, String zh) { |
||||
this.val = val; |
||||
this.en = en; |
||||
this.zh = zh; |
||||
} |
||||
|
||||
public static HmsChargingRodIndexEnum find(int val) { |
||||
return Arrays.stream(HmsChargingRodIndexEnum.values()) |
||||
.filter(rod -> rod.val == val) |
||||
.findAny() |
||||
.orElse(UNKNOWN); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
package com.dji.sample.manage.model.enums; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/29 |
||||
*/ |
||||
public enum PayloadModelEnum { |
||||
|
||||
Z30("Z30", "20-0"), |
||||
|
||||
XT2("XT2", "26-0"), |
||||
|
||||
XTS("XTS", "41-0"), |
||||
|
||||
H20("H20", "42-0"), |
||||
|
||||
H20T("H20T", "43-0"), |
||||
|
||||
P1("P1", "50-65535"), |
||||
|
||||
M30("M30", "52-0"), |
||||
|
||||
M30T("M30T", "53-0"), |
||||
|
||||
H20N("H20N", "61-0"), |
||||
|
||||
DOCK("DOCK", "165-0"), |
||||
|
||||
L1("L1", "90742-0"); |
||||
|
||||
private String model; |
||||
|
||||
private String index; |
||||
|
||||
PayloadModelEnum(String model, String index) { |
||||
this.model = model; |
||||
this.index = index; |
||||
} |
||||
|
||||
public String getModel() { |
||||
return model; |
||||
} |
||||
|
||||
public String getIndex() { |
||||
return index; |
||||
} |
||||
|
||||
public static List<String> getAllModel() { |
||||
return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getModel).collect(Collectors.toList()); |
||||
} |
||||
|
||||
public static List<String> getAllIndex() { |
||||
return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getIndex).collect(Collectors.toList()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
package com.dji.sample.manage.model.param; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/8 |
||||
*/ |
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class DeviceHmsQueryParam implements Serializable { |
||||
|
||||
@JsonProperty("device_sn") |
||||
private Set<String> deviceSn; |
||||
|
||||
@JsonProperty("begin_time") |
||||
private Long beginTime; |
||||
|
||||
@JsonProperty("end_time") |
||||
private Long endTime; |
||||
|
||||
private String language; |
||||
|
||||
private String message; |
||||
|
||||
private Long page; |
||||
|
||||
@JsonProperty("page_size") |
||||
private Long pageSize; |
||||
|
||||
private Integer level; |
||||
|
||||
@JsonProperty("update_time") |
||||
private Long updateTime; |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/11 |
||||
*/ |
||||
@Data |
||||
public class AlternateLandPointReceiver { |
||||
|
||||
private Double latitude; |
||||
|
||||
private Double longitude; |
||||
|
||||
private Double safeLandHeight; |
||||
} |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/13 |
||||
*/ |
||||
@Data |
||||
public class BindDeviceReceiver { |
||||
|
||||
private String deviceBindingCode; |
||||
|
||||
private String organizationId; |
||||
|
||||
private String deviceCallsign; |
||||
|
||||
private String sn; |
||||
|
||||
private String deviceModelKey; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/14 |
||||
*/ |
||||
@Builder |
||||
@Data |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@JsonInclude |
||||
public class BindStatusReceiver { |
||||
|
||||
private String sn; |
||||
|
||||
private Boolean isDeviceBindOrganization; |
||||
|
||||
private String organizationId; |
||||
|
||||
private String organizationName; |
||||
|
||||
private String deviceCallsign; |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/6 |
||||
*/ |
||||
@Data |
||||
public class DeviceHmsReceiver { |
||||
|
||||
private String code; |
||||
|
||||
private String deviceType; |
||||
|
||||
private String domainType; |
||||
|
||||
private Integer imminent; |
||||
|
||||
private Integer inTheSky; |
||||
|
||||
private Integer level; |
||||
|
||||
private Integer module; |
||||
|
||||
private HmsArgsReceiver args; |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/17 |
||||
*/ |
||||
@Data |
||||
public class DockMediaFileDetailReceiver { |
||||
|
||||
private Integer remainUpload; |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/6/17 |
||||
*/ |
||||
@Data |
||||
public class DockSdrReceiver { |
||||
|
||||
private Integer downQuality; |
||||
|
||||
private Double frequencyBand; |
||||
|
||||
private Integer upQuality; |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/11 |
||||
*/ |
||||
@Data |
||||
public class DockSubDeviceReceiver { |
||||
|
||||
private String deviceSn; |
||||
|
||||
private Integer deviceOnlineStatus; |
||||
|
||||
private Integer devicePaired; |
||||
|
||||
private String deviceModelKey; |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/5/11 |
||||
*/ |
||||
@Data |
||||
public class DroneChargeStateReceiver { |
||||
|
||||
private Integer state; |
||||
|
||||
private Integer capacityPercent; |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import com.dji.sample.manage.model.enums.DeviceDomainEnum; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.0 |
||||
* @date 2022/4/28 |
||||
*/ |
||||
@Data |
||||
@Builder |
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
public class FirmwareVersionReceiver { |
||||
|
||||
private String firmwareVersion; |
||||
|
||||
private Integer compatibleStatus; |
||||
|
||||
private Integer firmwareUpgradeStatus; |
||||
|
||||
private String sn; |
||||
|
||||
private DeviceDomainEnum domain; |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
package com.dji.sample.manage.model.receiver; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author sean |
||||
* @version 1.1 |
||||
* @date 2022/7/6 |
||||
*/ |
||||
@Data |
||||
public class HmsArgsReceiver { |
||||
|
||||
private Long componentIndex; |
||||
|
||||
private Integer sensorIndex; |
||||
|
||||
private Integer alarmId; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue