Commit b8e2b919 by guoxuejian

feat(psdk): add PSDK UI control and speaker management support

- Add PSDK floating window text model for UI display
- Add PSDK input box text set request for text input control
- Add PSDK method enumeration for widget and speaker operations
- Add PSDK UI resource upload result model for resource management
- Add PSDK widget value set request for widget control
- Add speaker audio play start request and progress tracking
- Add speaker TTS play start request and progress tracking
- Add speaker replay, stop, mode set, and volume set requests
- Add AbstractPsdkService base class for PSDK service implementation
- Add PsdkController and PsdkService for handling PSDK operations
- Add SpeakerPlayDTO for speaker play data transfer
- Update StorageConfigGetModuleEnum to include PSDK_UI_RESOURCE module
- Fix StorageConfigGetModuleEnum.find() method to be static
- Update ChannelName and EventsMethodEnum for PSDK support
- Update BizCodeEnum with new business codes
- Update application.yml configuration for PSDK features
- Update pom.xml dependencies for PSDK functionality
parent 41ed2a1c
...@@ -13,7 +13,9 @@ import java.util.Arrays; ...@@ -13,7 +13,9 @@ import java.util.Arrays;
*/ */
public enum StorageConfigGetModuleEnum { public enum StorageConfigGetModuleEnum {
MEDIA(0); MEDIA(0),
PSDK_UI_RESOURCE(1);
private final int module; private final int module;
...@@ -27,7 +29,7 @@ public enum StorageConfigGetModuleEnum { ...@@ -27,7 +29,7 @@ public enum StorageConfigGetModuleEnum {
} }
@JsonCreator @JsonCreator
public StorageConfigGetModuleEnum find(int module) { public static StorageConfigGetModuleEnum find(int module) {
return Arrays.stream(values()).filter(moduleEnum -> moduleEnum.module == module).findAny() return Arrays.stream(values()).filter(moduleEnum -> moduleEnum.module == module).findAny()
.orElseThrow(() -> new CloudSDKException(StorageConfigGetModuleEnum.class, module)); .orElseThrow(() -> new CloudSDKException(StorageConfigGetModuleEnum.class, module));
} }
......
package com.dji.sdk.cloudapi.psdk;
/**
* PSDK floating window text
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class PsdkFloatingWindowText {
/**
* PSDK payload device index (0-3)
*/
private Integer psdkIndex;
/**
* Floating window content
*/
private String value;
public PsdkFloatingWindowText() {
}
@Override
public String toString() {
return "PsdkFloatingWindowText{" +
"psdkIndex=" + psdkIndex +
", value='" + value + '\'' +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public PsdkFloatingWindowText setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public String getValue() {
return value;
}
public PsdkFloatingWindowText setValue(String value) {
this.value = value;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* PSDK input box text set request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class PsdkInputBoxTextSetRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
/**
* Text content (max 128 bytes)
*/
@NotNull
@Length(max = 128)
private String value;
public PsdkInputBoxTextSetRequest() {
}
@Override
public String toString() {
return "PsdkInputBoxTextSetRequest{" +
"psdkIndex=" + psdkIndex +
", value='" + value + '\'' +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public PsdkInputBoxTextSetRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public String getValue() {
return value;
}
public PsdkInputBoxTextSetRequest setValue(String value) {
this.value = value;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* PSDK method enumeration
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public enum PsdkMethodEnum {
// Widget control
WIDGET_VALUE_SET("psdk_widget_value_set"),
INPUT_BOX_TEXT_SET("psdk_input_box_text_set"),
// Speaker control
SPEAKER_AUDIO_PLAY_START("speaker_audio_play_start"),
SPEAKER_TTS_PLAY_START("speaker_tts_play_start"),
SPEAKER_REPLAY("speaker_replay"),
SPEAKER_PLAY_STOP("speaker_play_stop"),
SPEAKER_PLAY_MODE_SET("speaker_play_mode_set"),
SPEAKER_PLAY_VOLUME_SET("speaker_play_volume_set");
private final String method;
PsdkMethodEnum(String method) {
this.method = method;
}
@JsonValue
public String getMethod() {
return method;
}
}
package com.dji.sdk.cloudapi.psdk;
/**
* PSDK UI resource upload result
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class PsdkUiResourceUploadResult {
/**
* PSDK payload device index (0-3)
*/
private Integer psdkIndex;
/**
* OSS object key
*/
private String objectKey;
/**
* File size in bytes
*/
private Integer size;
/**
* Error code
*/
private Integer result;
public PsdkUiResourceUploadResult() {
}
@Override
public String toString() {
return "PsdkUiResourceUploadResult{" +
"psdkIndex=" + psdkIndex +
", objectKey='" + objectKey + '\'' +
", size=" + size +
", result=" + result +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public PsdkUiResourceUploadResult setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public String getObjectKey() {
return objectKey;
}
public PsdkUiResourceUploadResult setObjectKey(String objectKey) {
this.objectKey = objectKey;
return this;
}
public Integer getSize() {
return size;
}
public PsdkUiResourceUploadResult setSize(Integer size) {
this.size = size;
return this;
}
public Integer getResult() {
return result;
}
public PsdkUiResourceUploadResult setResult(Integer result) {
this.result = result;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* PSDK widget value set request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class PsdkWidgetValueSetRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
/**
* Widget index
*/
@NotNull
@Min(0)
private Integer index;
/**
* Widget value (defined by developer)
*/
@NotNull
private Integer value;
public PsdkWidgetValueSetRequest() {
}
@Override
public String toString() {
return "PsdkWidgetValueSetRequest{" +
"psdkIndex=" + psdkIndex +
", index=" + index +
", value=" + value +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public PsdkWidgetValueSetRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public Integer getIndex() {
return index;
}
public PsdkWidgetValueSetRequest setIndex(Integer index) {
this.index = index;
return this;
}
public Integer getValue() {
return value;
}
public PsdkWidgetValueSetRequest setValue(Integer value) {
this.value = value;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
/**
* Speaker audio play start progress
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerAudioPlayStartProgress {
/**
* Result code
*/
private Integer result;
/**
* Output data
*/
private Output output;
public SpeakerAudioPlayStartProgress() {
}
@Override
public String toString() {
return "SpeakerAudioPlayStartProgress{" +
"result=" + result +
", output=" + output +
'}';
}
public Integer getResult() {
return result;
}
public SpeakerAudioPlayStartProgress setResult(Integer result) {
this.result = result;
return this;
}
public Output getOutput() {
return output;
}
public SpeakerAudioPlayStartProgress setOutput(Output output) {
this.output = output;
return this;
}
public static class Output {
/**
* PSDK payload device index
*/
private Integer psdkIndex;
/**
* Current status (in_progress, ok)
*/
private String status;
/**
* File MD5 checksum
*/
private String md5;
/**
* Progress information
*/
private Progress progress;
public Output() {
}
@Override
public String toString() {
return "Output{" +
"psdkIndex=" + psdkIndex +
", status='" + status + '\'' +
", md5='" + md5 + '\'' +
", progress=" + progress +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public Output setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public String getStatus() {
return status;
}
public Output setStatus(String status) {
this.status = status;
return this;
}
public String getMd5() {
return md5;
}
public Output setMd5(String md5) {
this.md5 = md5;
return this;
}
public Progress getProgress() {
return progress;
}
public Output setProgress(Progress progress) {
this.progress = progress;
return this;
}
}
public static class Progress {
/**
* Progress percentage (0-100)
*/
private Integer percent;
/**
* Current step (change_work_mode, download, encoding, upload, play)
*/
private String stepKey;
public Progress() {
}
@Override
public String toString() {
return "Progress{" +
"percent=" + percent +
", stepKey='" + stepKey + '\'' +
'}';
}
public Integer getPercent() {
return percent;
}
public Progress setPercent(Integer percent) {
this.percent = percent;
return this;
}
public String getStepKey() {
return stepKey;
}
public Progress setStepKey(String stepKey) {
this.stepKey = stepKey;
return this;
}
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker audio play start request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerAudioPlayStartRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
/**
* Audio file information
*/
@NotNull
@Valid
private AudioFile file;
public SpeakerAudioPlayStartRequest() {
}
@Override
public String toString() {
return "SpeakerAudioPlayStartRequest{" +
"psdkIndex=" + psdkIndex +
", file=" + file +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerAudioPlayStartRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public AudioFile getFile() {
return file;
}
public SpeakerAudioPlayStartRequest setFile(AudioFile file) {
this.file = file;
return this;
}
public static class AudioFile {
/**
* File name
*/
@NotNull
private String name;
/**
* File download URL
*/
@NotNull
private String url;
/**
* File MD5 checksum
*/
@NotNull
private String md5;
/**
* Audio format (pcm)
*/
@NotNull
private String format;
public AudioFile() {
}
@Override
public String toString() {
return "AudioFile{" +
"name='" + name + '\'' +
", url='" + url + '\'' +
", md5='" + md5 + '\'' +
", format='" + format + '\'' +
'}';
}
public String getName() {
return name;
}
public AudioFile setName(String name) {
this.name = name;
return this;
}
public String getUrl() {
return url;
}
public AudioFile setUrl(String url) {
this.url = url;
return this;
}
public String getMd5() {
return md5;
}
public AudioFile setMd5(String md5) {
this.md5 = md5;
return this;
}
public String getFormat() {
return format;
}
public AudioFile setFormat(String format) {
this.format = format;
return this;
}
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker play mode set request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerPlayModeSetRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
@Max(3)
private Integer psdkIndex;
/**
* Play mode (0: single play, 1: loop play)
*/
@NotNull
@Min(0)
@Max(1)
private Integer playMode;
public SpeakerPlayModeSetRequest() {
}
@Override
public String toString() {
return "SpeakerPlayModeSetRequest{" +
"psdkIndex=" + psdkIndex +
", playMode=" + playMode +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerPlayModeSetRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public Integer getPlayMode() {
return playMode;
}
public SpeakerPlayModeSetRequest setPlayMode(Integer playMode) {
this.playMode = playMode;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker play stop request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerPlayStopRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
public SpeakerPlayStopRequest() {
}
@Override
public String toString() {
return "SpeakerPlayStopRequest{" +
"psdkIndex=" + psdkIndex +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerPlayStopRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker play volume set request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerPlayVolumeSetRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
@Max(3)
private Integer psdkIndex;
/**
* Play volume (0-100)
*/
@NotNull
@Min(0)
@Max(100)
private Integer playVolume;
public SpeakerPlayVolumeSetRequest() {
}
@Override
public String toString() {
return "SpeakerPlayVolumeSetRequest{" +
"psdkIndex=" + psdkIndex +
", playVolume=" + playVolume +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerPlayVolumeSetRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public Integer getPlayVolume() {
return playVolume;
}
public SpeakerPlayVolumeSetRequest setPlayVolume(Integer playVolume) {
this.playVolume = playVolume;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker replay request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerReplayRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
public SpeakerReplayRequest() {
}
@Override
public String toString() {
return "SpeakerReplayRequest{" +
"psdkIndex=" + psdkIndex +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerReplayRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
}
package com.dji.sdk.cloudapi.psdk;
/**
* Speaker TTS play start progress
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerTtsPlayStartProgress {
/**
* Result code
*/
private Integer result;
/**
* Output data
*/
private Output output;
public SpeakerTtsPlayStartProgress() {
}
@Override
public String toString() {
return "SpeakerTtsPlayStartProgress{" +
"result=" + result +
", output=" + output +
'}';
}
public Integer getResult() {
return result;
}
public SpeakerTtsPlayStartProgress setResult(Integer result) {
this.result = result;
return this;
}
public Output getOutput() {
return output;
}
public SpeakerTtsPlayStartProgress setOutput(Output output) {
this.output = output;
return this;
}
public static class Output {
/**
* PSDK payload device index
*/
private Integer psdkIndex;
/**
* Current status (in_progress, ok)
*/
private String status;
/**
* Content MD5 checksum
*/
private String md5;
/**
* Progress information
*/
private Progress progress;
public Output() {
}
@Override
public String toString() {
return "Output{" +
"psdkIndex=" + psdkIndex +
", status='" + status + '\'' +
", md5='" + md5 + '\'' +
", progress=" + progress +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public Output setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public String getStatus() {
return status;
}
public Output setStatus(String status) {
this.status = status;
return this;
}
public String getMd5() {
return md5;
}
public Output setMd5(String md5) {
this.md5 = md5;
return this;
}
public Progress getProgress() {
return progress;
}
public Output setProgress(Progress progress) {
this.progress = progress;
return this;
}
}
public static class Progress {
/**
* Progress percentage (0-100)
*/
private Integer percent;
/**
* Current step (change_work_mode, upload, play)
*/
private String stepKey;
public Progress() {
}
@Override
public String toString() {
return "Progress{" +
"percent=" + percent +
", stepKey='" + stepKey + '\'' +
'}';
}
public Integer getPercent() {
return percent;
}
public Progress setPercent(Integer percent) {
this.percent = percent;
return this;
}
public String getStepKey() {
return stepKey;
}
public Progress setStepKey(String stepKey) {
this.stepKey = stepKey;
return this;
}
}
}
package com.dji.sdk.cloudapi.psdk;
import com.dji.sdk.common.BaseModel;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* Speaker TTS play start request
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public class SpeakerTtsPlayStartRequest extends BaseModel {
/**
* PSDK payload device index (0-3)
*/
@NotNull
@Min(0)
private Integer psdkIndex;
/**
* TTS content
*/
@NotNull
@Valid
private TtsContent tts;
public SpeakerTtsPlayStartRequest() {
}
@Override
public String toString() {
return "SpeakerTtsPlayStartRequest{" +
"psdkIndex=" + psdkIndex +
", tts=" + tts +
'}';
}
public Integer getPsdkIndex() {
return psdkIndex;
}
public SpeakerTtsPlayStartRequest setPsdkIndex(Integer psdkIndex) {
this.psdkIndex = psdkIndex;
return this;
}
public TtsContent getTts() {
return tts;
}
public SpeakerTtsPlayStartRequest setTts(TtsContent tts) {
this.tts = tts;
return this;
}
public static class TtsContent {
/**
* TTS name
*/
@NotNull
private String name;
/**
* TTS text content
*/
@NotNull
private String text;
/**
* Content MD5 checksum
*/
@NotNull
private String md5;
public TtsContent() {
}
@Override
public String toString() {
return "TtsContent{" +
"name='" + name + '\'' +
", text='" + text + '\'' +
", md5='" + md5 + '\'' +
'}';
}
public String getName() {
return name;
}
public TtsContent setName(String name) {
this.name = name;
return this;
}
public String getText() {
return text;
}
public TtsContent setText(String text) {
this.text = text;
return this;
}
public String getMd5() {
return md5;
}
public TtsContent setMd5(String md5) {
this.md5 = md5;
return this;
}
}
}
package com.dji.sdk.cloudapi.psdk.api;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromPsdk;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionToPsdkRequest;
import com.dji.sdk.cloudapi.interconnection.InterconnectionMethodEnum;
import com.dji.sdk.cloudapi.psdk.*;
import com.dji.sdk.config.version.GatewayManager;
import com.dji.sdk.mqtt.ChannelName;
import com.dji.sdk.mqtt.MqttReply;
import com.dji.sdk.mqtt.events.EventsDataRequest;
import com.dji.sdk.mqtt.events.TopicEventsRequest;
import com.dji.sdk.mqtt.events.TopicEventsResponse;
import com.dji.sdk.mqtt.services.ServicesPublish;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.MessageHeaders;
import javax.annotation.Resource;
/**
* Abstract PSDK service
* Provides PSDK payload control and event handling capabilities
*
* @author sean
* @version 1.7
* @date 2023/10/16
*/
public abstract class AbstractPsdkService {
@Resource
private ServicesPublish servicesPublish;
// ==================== Events (Device to Cloud) ====================
/**
* Event notification of PSDK custom data transmission
* @param request data
* @param headers message headers
* @return events_reply
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK, outputChannel = ChannelName.OUTBOUND_EVENTS)
public TopicEventsResponse<MqttReply> customDataTransmissionFromPsdk(TopicEventsRequest<CustomDataTransmissionFromPsdk> request, MessageHeaders headers) {
throw new UnsupportedOperationException("customDataTransmissionFromPsdk not implemented");
}
/**
* Event notification of PSDK UI resource upload result
* @param request data
* @param headers message headers
* @return events_reply
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_PSDK_UI_RESOURCE_UPLOAD_RESULT, outputChannel = ChannelName.OUTBOUND_EVENTS)
public TopicEventsResponse<MqttReply> psdkUiResourceUploadResult(TopicEventsRequest<PsdkUiResourceUploadResult> request, MessageHeaders headers) {
throw new UnsupportedOperationException("psdkUiResourceUploadResult not implemented");
}
/**
* Event notification of PSDK floating window text
* @param request data
* @param headers message headers
* @return events_reply
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_PSDK_FLOATING_WINDOW_TEXT, outputChannel = ChannelName.OUTBOUND_EVENTS)
public TopicEventsResponse<MqttReply> psdkFloatingWindowText(TopicEventsRequest<PsdkFloatingWindowText> request, MessageHeaders headers) {
throw new UnsupportedOperationException("psdkFloatingWindowText not implemented");
}
/**
* Event notification of speaker audio play progress
* @param request data
* @param headers message headers
* @return events_reply
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_SPEAKER_AUDIO_PLAY_START_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public TopicEventsResponse<MqttReply> speakerAudioPlayStartProgress(TopicEventsRequest<EventsDataRequest<SpeakerAudioPlayStartProgress>> request, MessageHeaders headers) {
throw new UnsupportedOperationException("speakerAudioPlayStartProgress not implemented");
}
/**
* Event notification of speaker TTS play progress
* @param request data
* @param headers message headers
* @return events_reply
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_SPEAKER_TTS_PLAY_START_PROGRESS, outputChannel = ChannelName.OUTBOUND_EVENTS)
public TopicEventsResponse<MqttReply> speakerTtsPlayStartProgress(TopicEventsRequest<EventsDataRequest<SpeakerTtsPlayStartProgress>> request, MessageHeaders headers) {
throw new UnsupportedOperationException("speakerTtsPlayStartProgress not implemented");
}
// ==================== Services (Cloud to Device) ====================
/**
* Send custom data to PSDK payload
* @param gateway gateway manager
* @param request custom data (max 256 bytes)
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> customDataTransmissionToPsdk(GatewayManager gateway, CustomDataTransmissionToPsdkRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
InterconnectionMethodEnum.CUSTOM_DATA_TRANSMISSION_TO_PSDK.getMethod(),
request);
}
/**
* Set PSDK widget value
* @param gateway gateway manager
* @param request widget value set request
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> psdkWidgetValueSet(GatewayManager gateway, PsdkWidgetValueSetRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.WIDGET_VALUE_SET.getMethod(),
request);
}
/**
* Set PSDK input box text
* @param gateway gateway manager
* @param request input box text set request (max 128 bytes)
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> psdkInputBoxTextSet(GatewayManager gateway, PsdkInputBoxTextSetRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.INPUT_BOX_TEXT_SET.getMethod(),
request);
}
/**
* Start playing audio on speaker
* @param gateway gateway manager
* @param request audio play start request
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerAudioPlayStart(GatewayManager gateway, SpeakerAudioPlayStartRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_AUDIO_PLAY_START.getMethod(),
request);
}
/**
* Start playing TTS on speaker
* @param gateway gateway manager
* @param request TTS play start request
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerTtsPlayStart(GatewayManager gateway, SpeakerTtsPlayStartRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_TTS_PLAY_START.getMethod(),
request);
}
/**
* Replay the last audio/TTS on speaker
* @param gateway gateway manager
* @param request replay request
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerReplay(GatewayManager gateway, SpeakerReplayRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_REPLAY.getMethod(),
request);
}
/**
* Stop playing on speaker
* @param gateway gateway manager
* @param request play stop request
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerPlayStop(GatewayManager gateway, SpeakerPlayStopRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_PLAY_STOP.getMethod(),
request);
}
/**
* Set speaker play mode
* @param gateway gateway manager
* @param request play mode set request (0: single, 1: loop)
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerPlayModeSet(GatewayManager gateway, SpeakerPlayModeSetRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_PLAY_MODE_SET.getMethod(),
request);
}
/**
* Set speaker play volume
* @param gateway gateway manager
* @param request play volume set request (0-100)
* @return services_reply
*/
public TopicServicesResponse<ServicesReplyData> speakerPlayVolumeSet(GatewayManager gateway, SpeakerPlayVolumeSetRequest request) {
return servicesPublish.publish(
gateway.getGatewaySn(),
PsdkMethodEnum.SPEAKER_PLAY_VOLUME_SET.getMethod(),
request);
}
}
...@@ -146,6 +146,14 @@ public class ChannelName { ...@@ -146,6 +146,14 @@ public class ChannelName {
public static final String INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK = "inboundEventsCustomDataTransmissionFromPsdk"; public static final String INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK = "inboundEventsCustomDataTransmissionFromPsdk";
public static final String INBOUND_EVENTS_PSDK_UI_RESOURCE_UPLOAD_RESULT = "inboundEventsPsdkUiResourceUploadResult";
public static final String INBOUND_EVENTS_PSDK_FLOATING_WINDOW_TEXT = "inboundEventsPsdkFloatingWindowText";
public static final String INBOUND_EVENTS_SPEAKER_AUDIO_PLAY_START_PROGRESS = "inboundEventsSpeakerAudioPlayStartProgress";
public static final String INBOUND_EVENTS_SPEAKER_TTS_PLAY_START_PROGRESS = "inboundEventsSpeakerTtsPlayStartProgress";
public static final String INBOUND_EVENTS_AIRSENSE_WARNING = "inboundEventsAirsenseWarning"; public static final String INBOUND_EVENTS_AIRSENSE_WARNING = "inboundEventsAirsenseWarning";
public static final String INBOUND_EVENTS_FLIGHT_AREAS_SYNC_PROGRESS = "inboundEventsFlightAreasSyncProgress"; public static final String INBOUND_EVENTS_FLIGHT_AREAS_SYNC_PROGRESS = "inboundEventsFlightAreasSyncProgress";
......
...@@ -9,6 +9,10 @@ import com.dji.sdk.cloudapi.flightarea.FlightAreasSyncProgress; ...@@ -9,6 +9,10 @@ import com.dji.sdk.cloudapi.flightarea.FlightAreasSyncProgress;
import com.dji.sdk.cloudapi.hms.Hms; import com.dji.sdk.cloudapi.hms.Hms;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromEsdk; import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromEsdk;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromPsdk; import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromPsdk;
import com.dji.sdk.cloudapi.psdk.PsdkFloatingWindowText;
import com.dji.sdk.cloudapi.psdk.PsdkUiResourceUploadResult;
import com.dji.sdk.cloudapi.psdk.SpeakerAudioPlayStartProgress;
import com.dji.sdk.cloudapi.psdk.SpeakerTtsPlayStartProgress;
import com.dji.sdk.cloudapi.log.FileUploadProgress; import com.dji.sdk.cloudapi.log.FileUploadProgress;
import com.dji.sdk.cloudapi.map.OfflineMapSyncProgress; import com.dji.sdk.cloudapi.map.OfflineMapSyncProgress;
import com.dji.sdk.cloudapi.media.FileUploadCallback; import com.dji.sdk.cloudapi.media.FileUploadCallback;
...@@ -89,6 +93,14 @@ public enum EventsMethodEnum { ...@@ -89,6 +93,14 @@ public enum EventsMethodEnum {
CUSTOM_DATA_TRANSMISSION_FROM_PSDK("custom_data_transmission_from_psdk", ChannelName.INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK, new TypeReference<CustomDataTransmissionFromPsdk>() {}), CUSTOM_DATA_TRANSMISSION_FROM_PSDK("custom_data_transmission_from_psdk", ChannelName.INBOUND_EVENTS_CUSTOM_DATA_TRANSMISSION_FROM_PSDK, new TypeReference<CustomDataTransmissionFromPsdk>() {}),
PSDK_UI_RESOURCE_UPLOAD_RESULT("psdk_ui_resource_upload_result", ChannelName.INBOUND_EVENTS_PSDK_UI_RESOURCE_UPLOAD_RESULT, new TypeReference<PsdkUiResourceUploadResult>() {}),
PSDK_FLOATING_WINDOW_TEXT("psdk_floating_window_text", ChannelName.INBOUND_EVENTS_PSDK_FLOATING_WINDOW_TEXT, new TypeReference<PsdkFloatingWindowText>() {}),
SPEAKER_AUDIO_PLAY_START_PROGRESS("speaker_audio_play_start_progress", ChannelName.INBOUND_EVENTS_SPEAKER_AUDIO_PLAY_START_PROGRESS, new TypeReference<EventsDataRequest<SpeakerAudioPlayStartProgress>>() {}),
SPEAKER_TTS_PLAY_START_PROGRESS("speaker_tts_play_start_progress", ChannelName.INBOUND_EVENTS_SPEAKER_TTS_PLAY_START_PROGRESS, new TypeReference<EventsDataRequest<SpeakerTtsPlayStartProgress>>() {}),
AIRSENSE_WARNING("airsense_warning", ChannelName.INBOUND_EVENTS_AIRSENSE_WARNING, new TypeReference<List<AirsenseWarning>>() {}), AIRSENSE_WARNING("airsense_warning", ChannelName.INBOUND_EVENTS_AIRSENSE_WARNING, new TypeReference<List<AirsenseWarning>>() {}),
FLIGHT_AREAS_SYNC_PROGRESS("flight_areas_sync_progress", ChannelName.INBOUND_EVENTS_FLIGHT_AREAS_SYNC_PROGRESS, new TypeReference<FlightAreasSyncProgress>() {}), FLIGHT_AREAS_SYNC_PROGRESS("flight_areas_sync_progress", ChannelName.INBOUND_EVENTS_FLIGHT_AREAS_SYNC_PROGRESS, new TypeReference<FlightAreasSyncProgress>() {}),
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
<java.version>11</java.version> <java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<javax-activation.version>1.1.1</javax-activation.version> <javax-activation.version>1.1.1</javax-activation.version>
<mqtt.version>5.5.5</mqtt.version> <mqtt.version>5.5.5</mqtt.version>
</properties> </properties>
......
...@@ -79,6 +79,14 @@ public enum BizCodeEnum { ...@@ -79,6 +79,14 @@ public enum BizCodeEnum {
FLIGHT_AREAS_UPDATE("flight_areas_update"), FLIGHT_AREAS_UPDATE("flight_areas_update"),
PSDK_CUSTOM_DATA("psdk_custom_data"),
PSDK_UI_RESOURCE("psdk_ui_resource"),
PSDK_FLOATING_WINDOW("psdk_floating_window"),
PSDK_SPEAKER_PROGRESS("psdk_speaker_progress"),
; ;
private String code; private String code;
......
package com.dji.sample.psdk.controller;
import com.dji.sample.psdk.model.dto.SpeakerPlayDTO;
import com.dji.sample.psdk.service.IPsdkService;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* PSDK controller
*
* @author GeoFly Team
* @version 1.0
* @date 2026-02-03
*/
@Slf4j
@RestController
@RequestMapping("${url.psdk.prefix}${url.psdk.version}")
public class PsdkController {
@Autowired
private IPsdkService psdkService;
/**
* Send custom data to PSDK
*/
@PostMapping("/devices/{device_sn}/psdk/custom-data")
public HttpResultResponse<ServicesReplyData> sendCustomData(
@PathVariable("device_sn") String deviceSn,
@RequestParam(value = "psdk_index", required = false, defaultValue = "2") Integer psdkIndex,
@RequestBody String data) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.sendCustomDataToPsdk(deviceSn, psdkIndex, data);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to send custom data: " + response.getData().getResult().getCode());
}
}
/**
* Set PSDK widget value
*/
@PostMapping("/devices/{device_sn}/psdk/widget")
public HttpResultResponse<ServicesReplyData> setWidgetValue(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex,
@RequestParam("widget_index") Integer widgetIndex,
@RequestParam("value") Integer value) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.setWidgetValue(deviceSn, psdkIndex, widgetIndex, value);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to set widget value: " + response.getData().getResult().getCode());
}
}
/**
* Set PSDK input box text
*/
@PostMapping("/devices/{device_sn}/psdk/input-box")
public HttpResultResponse<ServicesReplyData> setInputBoxText(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex,
@RequestBody String text) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.setInputBoxText(deviceSn, psdkIndex, text);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to set input box text: " + response.getData().getResult().getCode());
}
}
/**
* Play audio on speaker
*/
@PostMapping("/devices/{device_sn}/speaker/audio/play")
public HttpResultResponse<ServicesReplyData> playAudio(
@PathVariable("device_sn") String deviceSn,
@Valid @RequestBody SpeakerPlayDTO playDTO) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.playAudio(deviceSn, playDTO);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to play audio: " + response.getData().getResult().getCode());
}
}
/**
* Play TTS on speaker
*/
@PostMapping("/devices/{device_sn}/speaker/tts/play")
public HttpResultResponse<ServicesReplyData> playTts(
@PathVariable("device_sn") String deviceSn,
@Valid @RequestBody SpeakerPlayDTO playDTO) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.playTts(deviceSn, playDTO);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to play TTS: " + response.getData().getResult().getCode());
}
}
/**
* Replay on speaker
*/
@PostMapping("/devices/{device_sn}/speaker/replay")
public HttpResultResponse<ServicesReplyData> replay(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.replay(deviceSn, psdkIndex);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to replay: " + response.getData().getResult().getCode());
}
}
/**
* Stop playing on speaker
*/
@PostMapping("/devices/{device_sn}/speaker/stop")
public HttpResultResponse<ServicesReplyData> stopPlay(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.stopPlay(deviceSn, psdkIndex);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to stop play: " + response.getData().getResult().getCode());
}
}
/**
* Set speaker play mode
*/
@PostMapping("/devices/{device_sn}/speaker/mode")
public HttpResultResponse<ServicesReplyData> setPlayMode(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex,
@RequestParam("play_mode") Integer playMode) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.setPlayMode(deviceSn, psdkIndex, playMode);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to set play mode: " + response.getData().getResult().getCode());
}
}
/**
* Set speaker volume
*/
@PostMapping("/devices/{device_sn}/speaker/volume")
public HttpResultResponse<ServicesReplyData> setVolume(
@PathVariable("device_sn") String deviceSn,
@RequestParam("psdk_index") Integer psdkIndex,
@RequestParam("volume") Integer volume) {
TopicServicesResponse<ServicesReplyData> response =
psdkService.setVolume(deviceSn, psdkIndex, volume);
if (response.getData().getResult().isSuccess()) {
return HttpResultResponse.success(response.getData());
} else {
return HttpResultResponse.error("Failed to set volume: " + response.getData().getResult().getCode());
}
}
}
package com.dji.sample.psdk.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Speaker play DTO
*
* @author GeoFly Team
* @version 1.0
* @date 2026-02-03
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SpeakerPlayDTO {
/**
* PSDK index (0-3)
*/
private Integer psdkIndex;
/**
* File name
*/
private String name;
/**
* File URL (for audio)
*/
private String url;
/**
* File MD5
*/
private String md5;
/**
* File format (pcm)
*/
private String format;
/**
* TTS text (for TTS)
*/
private String text;
}
package com.dji.sample.psdk.service;
import com.dji.sample.psdk.model.dto.SpeakerPlayDTO;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
/**
* PSDK service interface
*
* @author GeoFly Team
* @version 1.0
* @date 2026-02-03
*/
public interface IPsdkService {
/**
* Send custom data to PSDK payload
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @param data custom data (max 256 bytes)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> sendCustomDataToPsdk(String deviceSn, Integer psdkIndex, String data);
/**
* Set PSDK widget value
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @param widgetIndex widget index
* @param value widget value
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> setWidgetValue(String deviceSn, Integer psdkIndex, Integer widgetIndex, Integer value);
/**
* Set PSDK input box text
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @param text input text (max 128 bytes)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> setInputBoxText(String deviceSn, Integer psdkIndex, String text);
/**
* Play audio on speaker
* @param deviceSn device serial number
* @param playDTO speaker play parameters
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> playAudio(String deviceSn, SpeakerPlayDTO playDTO);
/**
* Play TTS on speaker
* @param deviceSn device serial number
* @param playDTO speaker play parameters
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> playTts(String deviceSn, SpeakerPlayDTO playDTO);
/**
* Replay on speaker
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> replay(String deviceSn, Integer psdkIndex);
/**
* Stop playing on speaker
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> stopPlay(String deviceSn, Integer psdkIndex);
/**
* Set speaker play mode
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @param playMode play mode (0: single, 1: loop)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> setPlayMode(String deviceSn, Integer psdkIndex, Integer playMode);
/**
* Set speaker volume
* @param deviceSn device serial number
* @param psdkIndex PSDK index (0-3)
* @param volume volume (0-100)
* @return service reply
*/
TopicServicesResponse<ServicesReplyData> setVolume(String deviceSn, Integer psdkIndex, Integer volume);
}
package com.dji.sample.psdk.service.impl;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.service.IWebSocketMessageService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.service.IDeviceRedisService;
import com.dji.sample.psdk.model.dto.SpeakerPlayDTO;
import com.dji.sample.psdk.service.IPsdkService;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionFromPsdk;
import com.dji.sdk.cloudapi.interconnection.CustomDataTransmissionToPsdkRequest;
import com.dji.sdk.cloudapi.interconnection.InterconnectionMethodEnum;
import com.dji.sdk.cloudapi.psdk.*;
import com.dji.sdk.cloudapi.psdk.api.AbstractPsdkService;
import com.dji.sdk.mqtt.MqttReply;
import com.dji.sdk.mqtt.events.EventsDataRequest;
import com.dji.sdk.mqtt.events.TopicEventsRequest;
import com.dji.sdk.mqtt.events.TopicEventsResponse;
import com.dji.sdk.mqtt.services.ServicesPublish;
import com.dji.sdk.mqtt.services.ServicesReplyData;
import com.dji.sdk.mqtt.services.TopicServicesResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* PSDK service implementation
*
* @author GeoFly Team
* @version 1.0
* @date 2026-02-03
*/
@Slf4j
@Service
public class PsdkServiceImpl extends AbstractPsdkService implements IPsdkService {
@Autowired
private IDeviceRedisService deviceRedisService;
@Autowired
private IWebSocketMessageService webSocketMessageService;
// ==================== Event Handlers (Device to Cloud) ====================
@Override
public TopicEventsResponse<MqttReply> customDataTransmissionFromPsdk(
TopicEventsRequest<CustomDataTransmissionFromPsdk> request, MessageHeaders headers) {
String deviceSn = request.getGateway();
CustomDataTransmissionFromPsdk data = request.getData();
log.info("Received PSDK custom data - Device: {}, Data: {}", deviceSn, data.getValue());
try {
String workspaceId = getWorkspaceId(deviceSn);
// 直接通过 WebSocket 推送给订阅者
webSocketMessageService.sendBatch(workspaceId, BizCodeEnum.PSDK_CUSTOM_DATA.getCode(), data);
} catch (Exception e) {
log.error("Failed to handle PSDK custom data", e);
}
return new TopicEventsResponse<MqttReply>()
.setData(MqttReply.success());
}
@Override
public TopicEventsResponse<MqttReply> psdkUiResourceUploadResult(
TopicEventsRequest<PsdkUiResourceUploadResult> request, MessageHeaders headers) {
String deviceSn = request.getGateway();
PsdkUiResourceUploadResult result = request.getData();
log.info("Received PSDK UI resource upload result - Device: {}, PSDK Index: {}, Result: {}",
deviceSn, result.getPsdkIndex(), result.getResult());
try {
String workspaceId = getWorkspaceId(deviceSn);
// 直接通过 WebSocket 推送给订阅者
webSocketMessageService.sendBatch(workspaceId, BizCodeEnum.PSDK_UI_RESOURCE.getCode(), result);
} catch (Exception e) {
log.error("Failed to handle PSDK UI resource upload result", e);
}
return new TopicEventsResponse<MqttReply>()
.setData(MqttReply.success());
}
@Override
public TopicEventsResponse<MqttReply> psdkFloatingWindowText(
TopicEventsRequest<PsdkFloatingWindowText> request, MessageHeaders headers) {
String deviceSn = request.getGateway();
PsdkFloatingWindowText floatingWindow = request.getData();
log.info("Received PSDK floating window text - Device: {}, PSDK Index: {}, Text: {}",
deviceSn, floatingWindow.getPsdkIndex(), floatingWindow.getValue());
try {
String workspaceId = getWorkspaceId(deviceSn);
// 直接通过 WebSocket 推送给订阅者
webSocketMessageService.sendBatch(workspaceId, BizCodeEnum.PSDK_FLOATING_WINDOW.getCode(), floatingWindow);
} catch (Exception e) {
log.error("Failed to handle PSDK floating window text", e);
}
return new TopicEventsResponse<MqttReply>()
.setData(MqttReply.success());
}
@Override
public TopicEventsResponse<MqttReply> speakerAudioPlayStartProgress(
TopicEventsRequest<EventsDataRequest<SpeakerAudioPlayStartProgress>> request, MessageHeaders headers) {
String deviceSn = request.getGateway();
SpeakerAudioPlayStartProgress progress = request.getData().getOutput();
if (progress.getOutput() != null && progress.getOutput().getProgress() != null) {
log.info("Received speaker audio play progress - Device: {}, PSDK Index: {}, Step: {}, Percent: {}%",
deviceSn,
progress.getOutput().getPsdkIndex(),
progress.getOutput().getProgress().getStepKey(),
progress.getOutput().getProgress().getPercent());
}
try {
String workspaceId = getWorkspaceId(deviceSn);
// 直接通过 WebSocket 推送给订阅者
webSocketMessageService.sendBatch(workspaceId, BizCodeEnum.PSDK_SPEAKER_PROGRESS.getCode(), progress);
} catch (Exception e) {
log.error("Failed to handle speaker audio play progress", e);
}
return new TopicEventsResponse<MqttReply>()
.setData(MqttReply.success());
}
@Override
public TopicEventsResponse<MqttReply> speakerTtsPlayStartProgress(
TopicEventsRequest<EventsDataRequest<SpeakerTtsPlayStartProgress>> request, MessageHeaders headers) {
String deviceSn = request.getGateway();
SpeakerTtsPlayStartProgress progress = request.getData().getOutput();
if (progress.getOutput() != null && progress.getOutput().getProgress() != null) {
log.info("Received speaker TTS play progress - Device: {}, PSDK Index: {}, Step: {}, Percent: {}%",
deviceSn,
progress.getOutput().getPsdkIndex(),
progress.getOutput().getProgress().getStepKey(),
progress.getOutput().getProgress().getPercent());
}
try {
String workspaceId = getWorkspaceId(deviceSn);
// 直接通过 WebSocket 推送给订阅者
webSocketMessageService.sendBatch(workspaceId, BizCodeEnum.PSDK_SPEAKER_PROGRESS.getCode(), progress);
} catch (Exception e) {
log.error("Failed to handle speaker TTS play progress", e);
}
return new TopicEventsResponse<MqttReply>()
.setData(MqttReply.success());
}
// ==================== Service Methods (Cloud to Device) ====================
@Autowired
private ServicesPublish servicesPublish;
@Override
public TopicServicesResponse<ServicesReplyData> sendCustomDataToPsdk(String deviceSn, Integer psdkIndex, String data) {
CustomDataTransmissionToPsdkRequest request = new CustomDataTransmissionToPsdkRequest()
.setValue(data);
log.info("Sending custom data to PSDK - Device: {}, Data: {}", deviceSn, data);
return servicesPublish.publish(deviceSn,
InterconnectionMethodEnum.CUSTOM_DATA_TRANSMISSION_TO_PSDK.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> setWidgetValue(String deviceSn, Integer psdkIndex, Integer widgetIndex, Integer value) {
PsdkWidgetValueSetRequest request = new PsdkWidgetValueSetRequest()
.setPsdkIndex(psdkIndex)
.setIndex(widgetIndex)
.setValue(value);
log.info("Setting PSDK widget value - Device: {}, PSDK Index: {}, Widget: {}, Value: {}",
deviceSn, psdkIndex, widgetIndex, value);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.WIDGET_VALUE_SET.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> setInputBoxText(String deviceSn, Integer psdkIndex, String text) {
PsdkInputBoxTextSetRequest request = new PsdkInputBoxTextSetRequest()
.setPsdkIndex(psdkIndex)
.setValue(text);
log.info("Setting PSDK input box text - Device: {}, PSDK Index: {}, Text: {}",
deviceSn, psdkIndex, text);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.INPUT_BOX_TEXT_SET.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> playAudio(String deviceSn, SpeakerPlayDTO playDTO) {
SpeakerAudioPlayStartRequest request = new SpeakerAudioPlayStartRequest()
.setPsdkIndex(playDTO.getPsdkIndex())
.setFile(new SpeakerAudioPlayStartRequest.AudioFile()
.setName(playDTO.getName())
.setUrl(playDTO.getUrl())
.setMd5(playDTO.getMd5())
.setFormat(playDTO.getFormat()));
log.info("Playing audio on speaker - Device: {}, PSDK Index: {}, File: {}",
deviceSn, playDTO.getPsdkIndex(), playDTO.getName());
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_AUDIO_PLAY_START.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> playTts(String deviceSn, SpeakerPlayDTO playDTO) {
SpeakerTtsPlayStartRequest request = new SpeakerTtsPlayStartRequest()
.setPsdkIndex(playDTO.getPsdkIndex())
.setTts(new SpeakerTtsPlayStartRequest.TtsContent()
.setName(playDTO.getName())
.setText(playDTO.getText())
.setMd5(playDTO.getMd5()));
log.info("Playing TTS on speaker - Device: {}, PSDK Index: {}, Text: {}",
deviceSn, playDTO.getPsdkIndex(), playDTO.getText());
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_TTS_PLAY_START.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> replay(String deviceSn, Integer psdkIndex) {
SpeakerReplayRequest request = new SpeakerReplayRequest()
.setPsdkIndex(psdkIndex);
log.info("Replaying on speaker - Device: {}, PSDK Index: {}", deviceSn, psdkIndex);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_REPLAY.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> stopPlay(String deviceSn, Integer psdkIndex) {
SpeakerPlayStopRequest request = new SpeakerPlayStopRequest()
.setPsdkIndex(psdkIndex);
log.info("Stopping play on speaker - Device: {}, PSDK Index: {}", deviceSn, psdkIndex);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_PLAY_STOP.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> setPlayMode(String deviceSn, Integer psdkIndex, Integer playMode) {
SpeakerPlayModeSetRequest request = new SpeakerPlayModeSetRequest()
.setPsdkIndex(psdkIndex)
.setPlayMode(playMode);
log.info("Setting speaker play mode - Device: {}, PSDK Index: {}, Mode: {}",
deviceSn, psdkIndex, playMode);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_PLAY_MODE_SET.getMethod(),
request);
}
@Override
public TopicServicesResponse<ServicesReplyData> setVolume(String deviceSn, Integer psdkIndex, Integer volume) {
SpeakerPlayVolumeSetRequest request = new SpeakerPlayVolumeSetRequest()
.setPsdkIndex(psdkIndex)
.setPlayVolume(volume);
log.info("Setting speaker volume - Device: {}, PSDK Index: {}, Volume: {}",
deviceSn, psdkIndex, volume);
return servicesPublish.publish(deviceSn,
PsdkMethodEnum.SPEAKER_PLAY_VOLUME_SET.getMethod(),
request);
}
// ==================== Helper Methods ====================
private String getWorkspaceId(String deviceSn) {
Optional<DeviceDTO> deviceOnline = deviceRedisService.getDeviceOnline(deviceSn);
return deviceOnline.map(DeviceDTO::getWorkspaceId).orElse(null);
}
}
...@@ -133,6 +133,9 @@ url: ...@@ -133,6 +133,9 @@ url:
control: control:
prefix: control prefix: control
version: /api/v1 version: /api/v1
psdk:
prefix: psdk
version: /api/v1
# Tutorial: https://www.alibabacloud.com/help/en/object-storage-service/latest/use-a-temporary-credential-provided-by-sts-to-access-oss # Tutorial: https://www.alibabacloud.com/help/en/object-storage-service/latest/use-a-temporary-credential-provided-by-sts-to-access-oss
#oss: #oss:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment