[+] 信令优化
This commit is contained in:
@@ -8,10 +8,10 @@ const defaultAudioConfig = {
|
|||||||
volume: 0.5,
|
volume: 0.5,
|
||||||
// 延迟大小(单位毫秒):500毫秒以内较好
|
// 延迟大小(单位毫秒):500毫秒以内较好
|
||||||
latency: 0.4,
|
latency: 0.4,
|
||||||
// 采样数:16
|
// 采样数:8|16|32
|
||||||
sampleSize: 16,
|
sampleSize: { min: 8, ideal: 16, max: 32 },
|
||||||
// 采样率:8000|16000|32000|48000
|
// 采样率:8000|16000|32000|48000
|
||||||
sampleRate: 48000,
|
sampleRate: { min: 8000, ideal: 32000, max: 48000 },
|
||||||
// 声道数量:1|2
|
// 声道数量:1|2
|
||||||
channelCount: 1,
|
channelCount: 1,
|
||||||
// 是否开启自动增益:true|false
|
// 是否开启自动增益:true|false
|
||||||
@@ -35,7 +35,7 @@ const defaultVideoConfig = {
|
|||||||
// 高度
|
// 高度
|
||||||
height: { min: 480, ideal: 720, max: 2160 },
|
height: { min: 480, ideal: 720, max: 2160 },
|
||||||
// 帧率
|
// 帧率
|
||||||
frameRate: 24,
|
frameRate: { min: 15, ideal: 24, max: 45 },
|
||||||
// 选摄像头:user|left|right|environment
|
// 选摄像头:user|left|right|environment
|
||||||
facingMode: "environment",
|
facingMode: "environment",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -249,9 +249,11 @@ class Taoyao {
|
|||||||
// 请求回调
|
// 请求回调
|
||||||
callbackMapping = new Map();
|
callbackMapping = new Map();
|
||||||
// 音频媒体配置
|
// 音频媒体配置
|
||||||
audio;
|
audio = defaultAudioConfig;
|
||||||
// 视频媒体配置
|
// 视频媒体配置
|
||||||
video;
|
video = defaultVideoConfig;
|
||||||
|
// 媒体配置
|
||||||
|
media;
|
||||||
// WebRTC配置
|
// WebRTC配置
|
||||||
webrtc;
|
webrtc;
|
||||||
// 信令通道
|
// 信令通道
|
||||||
@@ -473,11 +475,17 @@ class Taoyao {
|
|||||||
* @param {*} message 消息
|
* @param {*} message 消息
|
||||||
*/
|
*/
|
||||||
defaultClientConfig(message) {
|
defaultClientConfig(message) {
|
||||||
const self = this;
|
const me = this;
|
||||||
self.audio = { ...defaultAudioConfig, ...message.body.media.audio };
|
const { media, webrtc } = message.body;
|
||||||
self.video = { ...defaultVideoConfig, ...message.body.media.video };
|
const { audio, video} = media;
|
||||||
self.webrtc = message.body.webrtc;
|
me.audio.sampleSize = { min: media.minSampleSize, ideal: audio.sampleSize, max: media.maxSampleSize };
|
||||||
console.debug("终端配置", self.audio, self.video, self.webrtc);
|
me.audio.sampleRate = { min: media.minSampleRate, ideal: audio.sampleRate, max: media.maxSampleRate };
|
||||||
|
me.video.width = { min: media.minWidth, ideal: video.width, max: media.maxWidth };
|
||||||
|
me.video.height = { min: media.minHeight, ideal: video.height, max: media.maxHeight };
|
||||||
|
me.video.frameRate = { min: media.minFrameRate, ideal: video.frameRate, max: media.maxFrameRate };
|
||||||
|
me.media = media;
|
||||||
|
me.webrtc = webrtc;
|
||||||
|
console.debug("终端配置:", me.audio, me.video, me.media, me.webrtc);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 终端重启默认回调
|
* 终端重启默认回调
|
||||||
@@ -597,12 +605,7 @@ class Taoyao {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* TODO:共享 navigator.mediaDevices.getDisplayMedia();
|
|
||||||
* 生产媒体
|
* 生产媒体
|
||||||
* TODO:验证API试试修改媒体
|
|
||||||
* audioTrack.getSettings
|
|
||||||
* audioTrack.getCapabilities
|
|
||||||
* audioTrack.applyCapabilities
|
|
||||||
*/
|
*/
|
||||||
async produceMedia() {
|
async produceMedia() {
|
||||||
const self = this;
|
const self = this;
|
||||||
@@ -614,12 +617,15 @@ class Taoyao {
|
|||||||
self.checkDevice();
|
self.checkDevice();
|
||||||
// 释放资源
|
// 释放资源
|
||||||
self.closeMedia();
|
self.closeMedia();
|
||||||
// TODO:暂时不知道为什么?
|
/**
|
||||||
|
* 解决浏览器的自动播放策略问题
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||||
const audioTrack = stream.getAudioTracks()[0];
|
stream.getAudioTracks().forEach(audioTrack => {
|
||||||
audioTrack.enabled = false;
|
audioTrack.enabled = false;
|
||||||
setTimeout(() => audioTrack.stop(), 120000);
|
setTimeout(() => audioTrack.stop(), 30000);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (self.produce) {
|
if (self.produce) {
|
||||||
const response = await self.request(
|
const response = await self.request(
|
||||||
@@ -791,15 +797,16 @@ class Taoyao {
|
|||||||
let track;
|
let track;
|
||||||
try {
|
try {
|
||||||
console.debug("打开麦克风");
|
console.debug("打开麦克风");
|
||||||
// TODO:设置配置
|
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
audio: true,
|
audio: self.audio,
|
||||||
});
|
});
|
||||||
const tracks = stream.getAudioTracks();
|
const tracks = stream.getAudioTracks();
|
||||||
if (tracks.length > 1) {
|
if (tracks.length > 1) {
|
||||||
console.log("多个音频轨道");
|
console.log("多个音频轨道");
|
||||||
}
|
}
|
||||||
track = tracks[0];
|
track = tracks[0];
|
||||||
|
// TODO:验证修改API audioTrack.applyCapabilities
|
||||||
|
console.debug("音频信息:", track.getSettings(), track.getCapabilities());
|
||||||
this.audioProducer = await this.sendTransport.produce({
|
this.audioProducer = await this.sendTransport.produce({
|
||||||
track,
|
track,
|
||||||
codecOptions: {
|
codecOptions: {
|
||||||
@@ -905,6 +912,8 @@ class Taoyao {
|
|||||||
video: true,
|
video: true,
|
||||||
});
|
});
|
||||||
track = stream.getVideoTracks()[0];
|
track = stream.getVideoTracks()[0];
|
||||||
|
// TODO:验证修改API videoTrack.applyCapabilities
|
||||||
|
console.debug("视频信息:", track.getSettings(), track.getCapabilities());
|
||||||
} else if (self.videoSource === "screen") {
|
} else if (self.videoSource === "screen") {
|
||||||
const stream = await navigator.mediaDevices.getDisplayMedia({
|
const stream = await navigator.mediaDevices.getDisplayMedia({
|
||||||
// 如果需要共享声音
|
// 如果需要共享声音
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ public @interface Description {
|
|||||||
/**
|
/**
|
||||||
* @return 消息主体
|
* @return 消息主体
|
||||||
*/
|
*/
|
||||||
String[] body() default { "" };
|
String[] body() default { "{}" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 数据流向
|
* @return 数据流向
|
||||||
*/
|
*/
|
||||||
String[] flow() default { "终端=>信令服务->终端" };
|
String[] flow() default { "终端->信令服务->终端" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 描述信息
|
* @return 描述信息
|
||||||
|
|||||||
@@ -83,22 +83,6 @@ public interface Constant {
|
|||||||
* 建议
|
* 建议
|
||||||
*/
|
*/
|
||||||
String IDEAL = "ideal";
|
String IDEAL = "ideal";
|
||||||
/**
|
|
||||||
* 最小宽度
|
|
||||||
*/
|
|
||||||
Integer MIN_WIDTH = 720;
|
|
||||||
/**
|
|
||||||
* 最大宽度
|
|
||||||
*/
|
|
||||||
Integer MAX_WIDTH = 4096;
|
|
||||||
/**
|
|
||||||
* 最小高度
|
|
||||||
*/
|
|
||||||
Integer MIN_HEIGHT = 480;
|
|
||||||
/**
|
|
||||||
* 最大高度
|
|
||||||
*/
|
|
||||||
Integer MAX_HEIGHT = 2160;
|
|
||||||
/**
|
/**
|
||||||
* 脚本
|
* 脚本
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class MediaAudioProperties {
|
|||||||
|
|
||||||
@Schema(title = "格式", description = "格式", example = "G722|PCMA|PCMU|OPUS")
|
@Schema(title = "格式", description = "格式", example = "G722|PCMA|PCMU|OPUS")
|
||||||
private Format format;
|
private Format format;
|
||||||
@Schema(title = "采样数", description = "采样数", example = "16")
|
@Schema(title = "采样数", description = "采样数", example = "8|16|32")
|
||||||
private Integer sampleSize;
|
private Integer sampleSize;
|
||||||
@Schema(title = "采样率", description = "采样率", example = "8000|16000|32000|48000")
|
@Schema(title = "采样率", description = "采样率", example = "8000|16000|32000|48000")
|
||||||
private Integer sampleRate;
|
private Integer sampleRate;
|
||||||
|
|||||||
@@ -17,6 +17,30 @@ import lombok.Setter;
|
|||||||
@ConfigurationProperties(prefix = "taoyao.media")
|
@ConfigurationProperties(prefix = "taoyao.media")
|
||||||
public class MediaProperties {
|
public class MediaProperties {
|
||||||
|
|
||||||
|
@Schema(title = "最小视频宽度", description = "最小视频宽度")
|
||||||
|
private Integer minWidth;
|
||||||
|
@Schema(title = "最大视频宽度", description = "最大视频宽度")
|
||||||
|
private Integer maxWidth;
|
||||||
|
@Schema(title = "最小视频高度", description = "最小视频高度")
|
||||||
|
private Integer minHeight;
|
||||||
|
@Schema(title = "最大视频高度", description = "最大视频高度")
|
||||||
|
private Integer maxHeight;
|
||||||
|
@Schema(title = "最小视频码率", description = "最小视频码率")
|
||||||
|
private Integer minBitrate;
|
||||||
|
@Schema(title = "最大视频码率", description = "最大视频码率")
|
||||||
|
private Integer maxBitrate;
|
||||||
|
@Schema(title = "最小视频帧率", description = "最小视频帧率")
|
||||||
|
private Integer minFrameRate;
|
||||||
|
@Schema(title = "最大视频帧率", description = "最大视频帧率")
|
||||||
|
private Integer maxFrameRate;
|
||||||
|
@Schema(title = "最小音频采样数", description = "最小音频采样数")
|
||||||
|
private Integer minSampleSize;
|
||||||
|
@Schema(title = "最大音频采样数", description = "最大音频采样数")
|
||||||
|
private Integer maxSampleSize;
|
||||||
|
@Schema(title = "最小音频采样率", description = "最小音频采样率")
|
||||||
|
private Integer minSampleRate;
|
||||||
|
@Schema(title = "最大音频采样率", description = "最大音频采样率")
|
||||||
|
private Integer maxSampleRate;
|
||||||
@Schema(title = "音频默认配置", description = "音频默认配置")
|
@Schema(title = "音频默认配置", description = "音频默认配置")
|
||||||
private MediaAudioProperties audio;
|
private MediaAudioProperties audio;
|
||||||
@Schema(title = "视频默认配置", description = "视频默认配置")
|
@Schema(title = "视频默认配置", description = "视频默认配置")
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package com.acgist.taoyao.boot.config;
|
package com.acgist.taoyao.boot.config;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -35,33 +32,27 @@ public class MediaVideoProperties {
|
|||||||
private Format format;
|
private Format format;
|
||||||
@Schema(title = "码率", description = "码率影响画质", example = "600|1200|1500|1800")
|
@Schema(title = "码率", description = "码率影响画质", example = "600|1200|1500|1800")
|
||||||
private Integer bitrate;
|
private Integer bitrate;
|
||||||
@Schema(title = "帧率", description = "帧率影响流畅", example = "20|24|30|60")
|
@Schema(title = "帧率", description = "帧率影响流畅", example = "15|18|20|24|30|45")
|
||||||
private Integer frameRate;
|
private Integer frameRate;
|
||||||
@Schema(title = "分辨率", description = "分辨率影响画面大小", example = "1920*1080|1280*720")
|
@Schema(title = "分辨率", description = "分辨率影响画面大小", example = "4096*2160|2560*1440|1920*1080|1280*720|720*480")
|
||||||
private String resolution;
|
private String resolution;
|
||||||
@Schema(title = "宽度", description = "宽度", example = "{ min: 720, ideal: 1280, max: 4096 }")
|
@Schema(title = "宽度", description = "宽度", example = "4096|2560|1920|1280|720")
|
||||||
private Map<String, Object> width;
|
private Integer width;
|
||||||
@Schema(title = "高度", description = "高度", example = "{ min: 480, ideal: 720, max: 2160 }")
|
@Schema(title = "高度", description = "高度", example = "2160|1440|1080|720|480")
|
||||||
private Map<String, Object> height;
|
private Integer height;
|
||||||
|
|
||||||
public Map<String, Object> getWidth() {
|
public Integer getWidth() {
|
||||||
if (this.width == null) {
|
if (this.width == null) {
|
||||||
final int index = this.resolution.indexOf('*');
|
final int index = this.resolution.indexOf('*');
|
||||||
this.width = new LinkedHashMap<>();
|
return this.width = Integer.valueOf(this.resolution.substring(0, index).strip());
|
||||||
this.width.put(Constant.MIN, Constant.MIN_WIDTH);
|
|
||||||
this.width.put(Constant.IDEAL, Integer.valueOf(this.resolution.substring(0, index).strip()));
|
|
||||||
this.width.put(Constant.MAX, Constant.MAX_WIDTH);
|
|
||||||
}
|
}
|
||||||
return this.width;
|
return this.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getHeight() {
|
public Integer getHeight() {
|
||||||
if (this.height == null) {
|
if (this.height == null) {
|
||||||
final int index = this.resolution.indexOf('*');
|
final int index = this.resolution.indexOf('*');
|
||||||
this.height = new LinkedHashMap<>();
|
return this.height = Integer.valueOf(this.resolution.substring(index + 1).strip());
|
||||||
this.height.put(Constant.MIN, Constant.MIN_HEIGHT);
|
|
||||||
this.height.put(Constant.IDEAL, Integer.valueOf(this.resolution.substring(index + 1).strip()));
|
|
||||||
this.height.put(Constant.MAX, Constant.MAX_HEIGHT);
|
|
||||||
}
|
}
|
||||||
return this.height;
|
return this.height;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,4 +103,20 @@ public final class MapUtils {
|
|||||||
return Boolean.valueOf(object.toString());
|
return Boolean.valueOf(object.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <T> 参数泛型
|
||||||
|
*
|
||||||
|
* @param body 消息主体
|
||||||
|
* @param key 参数名称
|
||||||
|
*
|
||||||
|
* @return 参数值
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static final <T> T remove(Map<?, ?> body, String key) {
|
||||||
|
if(body == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (T) body.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,24 @@ taoyao:
|
|||||||
max-client-index: 99999
|
max-client-index: 99999
|
||||||
# 媒体配置
|
# 媒体配置
|
||||||
media:
|
media:
|
||||||
|
# 宽度
|
||||||
|
min-width: 720
|
||||||
|
max-width: 4096
|
||||||
|
# 高度
|
||||||
|
min-height: 480
|
||||||
|
max-height: 2160
|
||||||
|
# 码率
|
||||||
|
min-bitrate: 800
|
||||||
|
max-bitrate: 1600
|
||||||
|
# 帧率
|
||||||
|
min-frame-rate: 15
|
||||||
|
max-frame-rate: 45
|
||||||
|
# 采样数
|
||||||
|
min-sample-size: 8
|
||||||
|
max-sample-size: 32
|
||||||
|
# 采样率
|
||||||
|
min-sample-rate: 8000
|
||||||
|
max-sample-rate: 48000
|
||||||
# 默认音频
|
# 默认音频
|
||||||
audio:
|
audio:
|
||||||
format: OPUS
|
format: OPUS
|
||||||
@@ -82,7 +100,7 @@ taoyao:
|
|||||||
ud-video:
|
ud-video:
|
||||||
format: H264
|
format: H264
|
||||||
bitrate: 1600
|
bitrate: 1600
|
||||||
frame-rate: 30
|
frame-rate: 45
|
||||||
resolution: 4096*2160
|
resolution: 4096*2160
|
||||||
# 2K:QD=QHD=2K
|
# 2K:QD=QHD=2K
|
||||||
qd-video:
|
qd-video:
|
||||||
@@ -106,7 +124,7 @@ taoyao:
|
|||||||
sd-video:
|
sd-video:
|
||||||
format: H264
|
format: H264
|
||||||
bitrate: 800
|
bitrate: 800
|
||||||
frame-rate: 16
|
frame-rate: 15
|
||||||
resolution: 720*480
|
resolution: 720*480
|
||||||
# Socket信令
|
# Socket信令
|
||||||
socket:
|
socket:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class ProtocolControlAdapter extends ProtocolClientAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
|
||||||
final String to = MapUtils.get(body, Constant.TO);
|
final String to = MapUtils.remove(body, Constant.TO);
|
||||||
final Client targetClient = this.clientManager.clients(to);
|
final Client targetClient = this.clientManager.clients(to);
|
||||||
if(targetClient == null) {
|
if(targetClient == null) {
|
||||||
throw MessageCodeException.of("目标终端无效:" + to);
|
throw MessageCodeException.of("目标终端无效:" + to);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
"alarming": 是否发生告警(true|false),
|
"alarming": 是否发生告警(true|false),
|
||||||
"charging": 是否正在充电(true|false),
|
"charging": 是否正在充电(true|false),
|
||||||
"recording": 是否正在录像(true|false),
|
"recording": 是否正在录像(true|false),
|
||||||
|
"lastHeartbeat": "最后心跳时间",
|
||||||
"status": {更多状态},
|
"status": {更多状态},
|
||||||
"config": {更多配置}
|
"config": {更多配置}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,18 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
memo = "没有选择终端类型时返回所有类型终端状态列表",
|
memo = "没有选择终端类型时返回所有类型终端状态列表",
|
||||||
body = """
|
body = {
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"clientType": "终端类型(可选)"
|
"clientType": "终端类型(可选)"
|
||||||
}
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"ip": "终端IP",
|
"ip": "终端IP",
|
||||||
"name": "终端名称",
|
"name": "终端名称",
|
||||||
"clientId": "终端标识",
|
"clientId": "终端ID",
|
||||||
"clientType": "终端类型",
|
"clientType": "终端类型",
|
||||||
"latitude": 纬度,
|
"latitude": 纬度,
|
||||||
"longitude": 经度,
|
"longitude": 经度,
|
||||||
@@ -40,12 +43,14 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
"alarming": 是否发生告警(true|false),
|
"alarming": 是否发生告警(true|false),
|
||||||
"charging": 是否正在充电(true|false),
|
"charging": 是否正在充电(true|false),
|
||||||
"recording": 是否正在录像(true|false),
|
"recording": 是否正在录像(true|false),
|
||||||
|
"lastHeartbeat": "最后心跳时间",
|
||||||
"status": {更多状态},
|
"status": {更多状态},
|
||||||
"config": {更多配置}
|
"config": {更多配置}
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
]
|
]
|
||||||
""",
|
"""
|
||||||
|
},
|
||||||
flow = "终端->信令服务->终端"
|
flow = "终端->信令服务->终端"
|
||||||
)
|
)
|
||||||
public class ClientListProtocol extends ProtocolClientAdapter {
|
public class ClientListProtocol extends ProtocolClientAdapter {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
@Description(
|
@Description(
|
||||||
body = """
|
body = """
|
||||||
{
|
{
|
||||||
"clientId": "下线终端标识"
|
"clientId": "下线终端ID"
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
flow = "终端-[终端关闭]>信令服务-)终端"
|
flow = "终端-[终端关闭]>信令服务-)终端"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
{
|
{
|
||||||
"ip": "终端IP",
|
"ip": "终端IP",
|
||||||
"name": "终端名称",
|
"name": "终端名称",
|
||||||
"clientId": "终端标识",
|
"clientId": "终端ID",
|
||||||
"clientType": "终端类型",
|
"clientType": "终端类型",
|
||||||
"latitude": 纬度,
|
"latitude": 纬度,
|
||||||
"longitude": 经度,
|
"longitude": 经度,
|
||||||
@@ -31,6 +31,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
"alarming": 是否发生告警(true|false),
|
"alarming": 是否发生告警(true|false),
|
||||||
"charging": 是否正在充电(true|false),
|
"charging": 是否正在充电(true|false),
|
||||||
"recording": 是否正在录像(true|false),
|
"recording": 是否正在录像(true|false),
|
||||||
|
"lastHeartbeat": "最后心跳时间",
|
||||||
"status": {更多状态},
|
"status": {更多状态},
|
||||||
"config": {更多配置}
|
"config": {更多配置}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ClientRebootProtocol extends ProtocolClientAdapter implements Contr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端ID
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public void execute(String clientId) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
this.clientManager.unicast(clientId, this.build());
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
"username": "信令用户",
|
"username": "信令用户",
|
||||||
"password": "信令密码",
|
"password": "信令密码",
|
||||||
"name": "终端名称",
|
"name": "终端名称",
|
||||||
"clientId": "终端标识",
|
"clientId": "终端ID",
|
||||||
"clientType": "终端类型",
|
"clientType": "终端类型",
|
||||||
"latitude": 纬度,
|
"latitude": 纬度,
|
||||||
"longitude": 经度,
|
"longitude": 经度,
|
||||||
@@ -45,6 +45,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
"alarming": 是否发生告警(true|false),
|
"alarming": 是否发生告警(true|false),
|
||||||
"charging": 是否正在充电(true|false),
|
"charging": 是否正在充电(true|false),
|
||||||
"recording": 是否正在录像(true|false),
|
"recording": 是否正在录像(true|false),
|
||||||
|
"lastHeartbeat": "最后心跳时间",
|
||||||
"status": {更多状态},
|
"status": {更多状态},
|
||||||
"config": {更多配置}
|
"config": {更多配置}
|
||||||
}
|
}
|
||||||
@@ -101,7 +102,7 @@ public class ClientRegisterProtocol extends ProtocolClientAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端ID
|
||||||
* @param clientType 终端类型
|
* @param clientType 终端类型
|
||||||
* @param client 终端
|
* @param client 终端
|
||||||
* @param body 消息主体
|
* @param body 消息主体
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ClientShutdownProtocol extends ProtocolClientAdapter implements Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端ID
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public void execute(String clientId) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
this.clientManager.unicast(clientId, this.build());
|
||||||
|
|||||||
@@ -18,21 +18,31 @@ import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
|||||||
*/
|
*/
|
||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
|
memo = "没有指定终端ID返回请求终端状态",
|
||||||
body = {
|
body = {
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"clientId": "终端标识(可选)"
|
"clientId": "终端ID(可选)"
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"clientId": "终端标识",
|
|
||||||
"ip": "终端IP",
|
"ip": "终端IP",
|
||||||
|
"name": "终端名称",
|
||||||
|
"clientId": "终端ID",
|
||||||
|
"clientType": "终端类型",
|
||||||
|
"latitude": 纬度,
|
||||||
|
"longitude": 经度,
|
||||||
|
"humidity": 湿度,
|
||||||
|
"temperature": 温度,
|
||||||
"signal": 信号强度(0~100),
|
"signal": 信号强度(0~100),
|
||||||
"battery": 电池电量(0~100),
|
"battery": 电池电量(0~100),
|
||||||
|
"alarming": 是否发生告警(true|false),
|
||||||
"charging": 是否正在充电(true|false),
|
"charging": 是否正在充电(true|false),
|
||||||
"mediaId": "媒体服务标识",
|
"recording": 是否正在录像(true|false),
|
||||||
"lastHeartbeat": "最后心跳时间"
|
"lastHeartbeat": "最后心跳时间",
|
||||||
|
"status": {更多状态},
|
||||||
|
"config": {更多配置}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,32 +2,35 @@ package com.acgist.taoyao.signal.protocol.client;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.acgist.taoyao.boot.annotation.Description;
|
import com.acgist.taoyao.boot.annotation.Description;
|
||||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||||
import com.acgist.taoyao.boot.config.Constant;
|
import com.acgist.taoyao.boot.config.Constant;
|
||||||
import com.acgist.taoyao.boot.model.Message;
|
import com.acgist.taoyao.boot.model.Message;
|
||||||
|
import com.acgist.taoyao.boot.utils.MapUtils;
|
||||||
import com.acgist.taoyao.signal.client.Client;
|
import com.acgist.taoyao.signal.client.Client;
|
||||||
import com.acgist.taoyao.signal.client.ClientType;
|
import com.acgist.taoyao.signal.client.ClientType;
|
||||||
import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
import com.acgist.taoyao.signal.protocol.ProtocolClientAdapter;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终端单播信令
|
* 终端单播信令
|
||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
body = """
|
body = {
|
||||||
|
"""
|
||||||
{
|
{
|
||||||
"to": "接收终端标识",
|
"to": "接收终端ID",
|
||||||
...自定义的主体
|
...
|
||||||
}
|
}
|
||||||
""",
|
""",
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
},
|
||||||
flow = "终端->信令服务->终端"
|
flow = "终端->信令服务->终端"
|
||||||
)
|
)
|
||||||
public class ClientUnicastProtocol extends ProtocolClientAdapter {
|
public class ClientUnicastProtocol extends ProtocolClientAdapter {
|
||||||
@@ -40,12 +43,8 @@ public class ClientUnicastProtocol extends ProtocolClientAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
|
public void execute(String clientId, ClientType clientType, Client client, Message message, Map<String, Object> body) {
|
||||||
final String to = (String) body.remove(Constant.TO);
|
final String to = MapUtils.remove(body, Constant.TO);
|
||||||
if(StringUtils.isNotEmpty(to)) {
|
|
||||||
this.clientManager.unicast(to, message);
|
this.clientManager.unicast(to, message);
|
||||||
} else {
|
|
||||||
log.warn("终端单播消息没有接收终端标识:{}", to);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class ClientWakeupProtocol extends ProtocolClientAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端ID
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public void execute(String clientId) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
this.clientManager.unicast(clientId, this.build());
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
*/
|
*/
|
||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
|
body = """
|
||||||
|
{
|
||||||
|
"to": "目标终端ID"
|
||||||
|
}
|
||||||
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
"信令服务->终端",
|
"信令服务->终端",
|
||||||
"终端->信令服务->终端"
|
"终端->信令服务->终端"
|
||||||
@@ -35,7 +40,7 @@ public class ControlBellProtocol extends ProtocolControlAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clientId 终端标识
|
* @param clientId 终端ID
|
||||||
*/
|
*/
|
||||||
public void execute(String clientId) {
|
public void execute(String clientId) {
|
||||||
this.clientManager.unicast(clientId, this.build());
|
this.clientManager.unicast(clientId, this.build());
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
*/
|
*/
|
||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
|
body = """
|
||||||
|
{
|
||||||
|
"to": "目标终端ID"
|
||||||
|
}
|
||||||
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
"信令服务->终端",
|
"信令服务->终端",
|
||||||
"终端->信令服务->终端"
|
"终端->信令服务->终端"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
@Description(
|
@Description(
|
||||||
body = """
|
body = """
|
||||||
{
|
{
|
||||||
|
"to": "目标终端ID",
|
||||||
"type": "PTZ类型(PAN|TILT|ZOOM)",
|
"type": "PTZ类型(PAN|TILT|ZOOM)",
|
||||||
"value": PTZ参数
|
"value": PTZ参数
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ import com.acgist.taoyao.signal.protocol.ProtocolControlAdapter;
|
|||||||
@Protocol
|
@Protocol
|
||||||
@Description(
|
@Description(
|
||||||
memo = "状态通过心跳回传",
|
memo = "状态通过心跳回传",
|
||||||
|
body = """
|
||||||
|
{
|
||||||
|
"to": "目标终端ID"
|
||||||
|
}
|
||||||
|
""",
|
||||||
flow = {
|
flow = {
|
||||||
"信令服务->终端",
|
"信令服务->终端",
|
||||||
"终端->信令服务->终端"
|
"终端->信令服务->终端"
|
||||||
|
|||||||
Reference in New Issue
Block a user