[*] 电池信号

This commit is contained in:
acgist
2023-03-22 21:03:06 +08:00
parent fb31f5c0a9
commit d635b5a2a3
34 changed files with 812 additions and 832 deletions

View File

@@ -60,3 +60,6 @@ Android还在学习之中...
* 优化JS错误回调 -> platform::error
* 反复测试推流拉流、拉人踢人、音频视频控制
* 24小时不关闭媒体/一秒一次推拉流十分钟测试/三十秒推拉流一小时测试
* AI、美颜、水印、滤镜
* 混音、降噪、回音消除、声音特效

View File

@@ -6,4 +6,4 @@ local.properties
**/build
mediasoup/deps
media/deps

View File

@@ -11,7 +11,6 @@ android {
versionCode 100
versionName "1.0.0"
consumerProguardFiles "consumer-rules.pro"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
@@ -29,6 +28,4 @@ dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@@ -14,211 +14,203 @@ import com.fasterxml.jackson.annotation.JsonIncludeProperties;
*
* @author acgist
*/
@JsonIncludeProperties(value = { "code", "message", "header", "body" })
@JsonIncludeProperties(value = {"code", "message", "header", "body"})
public class Message implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/**
* 状态编码
*/
private String code;
/**
* 状态描述
*/
private String message;
/**
* 消息头部
*/
private Header header;
/**
* 消息主体
*/
private Object body;
/**
* 状态编码
*/
private String code;
/**
* 状态描述
*/
private String message;
/**
* 消息头部
*/
private Header header;
/**
* 消息主体
*/
private Object body;
/**
* @param code 状态编码
*/
public void setCode(String code) {
this.code = code;
}
/**
* @param code 状态编码
*/
public void setCode(String code) {
this.code = code;
}
/**
* @param code 状态编码
*/
public void setCode(MessageCode code) {
this.setCode(code, null);
}
/**
* @param code 状态编码
*/
public void setCode(MessageCode code) {
this.setCode(code, null);
}
/**
* @param code 状态编码
* @param message 状态描述
*
* @return this
*/
public Message setCode(MessageCode code, String message) {
this.code = code.getCode();
this.message = message == null || message.isEmpty() ? code.getMessage() : message;
return this;
}
/**
* @param code 状态编码
* @param message 状态描述
* @return this
*/
public Message setCode(MessageCode code, String message) {
this.code = code.getCode();
this.message = message == null || message.isEmpty() ? code.getMessage() : message;
return this;
}
/**
* @return 成功消息
*/
public static final Message success() {
return success(null);
}
/**
* @return 成功消息
*/
public static final Message success() {
return success(null);
}
/**
* @param body 消息主体
*
* @return 成功消息
*/
public static final Message success(Object body) {
final Message message = new Message();
message.setCode(MessageCode.CODE_0000, null);
message.body = body;
return message;
}
/**
* @param body 消息主体
* @return 成功消息
*/
public static final Message success(Object body) {
final Message message = new Message();
message.setCode(MessageCode.CODE_0000, null);
message.body = body;
return message;
}
/**
* @return 失败消息
*/
public static final Message fail() {
return fail(null, null, null);
}
/**
* @return 失败消息
*/
public static final Message fail() {
return fail(null, null, null);
}
/**
* @param code 状态编码
*
* @return 失败消息
*/
public static final Message fail(MessageCode code) {
return fail(code, null, null);
}
/**
* @param code 状态编码
* @return 失败消息
*/
public static final Message fail(MessageCode code) {
return fail(code, null, null);
}
/**
* @param code 状态编码
* @param body 消息主体
*
* @return 失败消息
*/
public static final Message fail(MessageCode code, Object body) {
return fail(code, null, body);
}
/**
* @param code 状态编码
* @param body 消息主体
* @return 失败消息
*/
public static final Message fail(MessageCode code, Object body) {
return fail(code, null, body);
}
/**
* @param message 状态描述
*
* @return 失败消息
*/
public static final Message fail(String message) {
return fail(null, message, null);
}
/**
* @param message 状态描述
* @return 失败消息
*/
public static final Message fail(String message) {
return fail(null, message, null);
}
/**
* @param message 状态描述
* @param body 消息主体
*
* @return 失败消息
*/
public static final Message fail(String message, Object body) {
return fail(null, message, body);
}
/**
* @param message 状态描述
* @param body 消息主体
* @return 失败消息
*/
public static final Message fail(String message, Object body) {
return fail(null, message, body);
}
/**
* @param code 状态编码
* @param message 状态描述
*
* @return 失败消息
*/
public static final Message fail(MessageCode code, String message) {
return fail(code, message, null);
}
/**
* @param code 状态编码
* @param message 状态描述
* @return 失败消息
*/
public static final Message fail(MessageCode code, String message) {
return fail(code, message, null);
}
/**
* @param code 状态编码
* @param message 状态描述
* @param body 消息主体
*
* @return 失败消息
*/
public static final Message fail(MessageCode code, String message, Object body) {
final Message failMessage = new Message();
failMessage.setCode(code == null ? MessageCode.CODE_9999 : code, message);
failMessage.body = body;
return failMessage;
}
/**
* @param code 状态编码
* @param message 状态描述
* @param body 消息主体
* @return 失败消息
*/
public static final Message fail(MessageCode code, String message, Object body) {
final Message failMessage = new Message();
failMessage.setCode(code == null ? MessageCode.CODE_9999 : code, message);
failMessage.body = body;
return failMessage;
}
@Override
public Message clone() {
return new Message(this.code, this.message, this.header.clone(), this.body);
}
@Override
public Message clone() {
return new Message(this.code, this.message, this.header.clone(), this.body);
}
/**
* 克隆消息排除消息主体
*
* @return 克隆消息
*/
public Message cloneWithoutBody() {
return new Message(this.code, this.message, this.header.clone(), null);
}
/**
* 克隆消息排除消息主体
*
* @return 克隆消息
*/
public Message cloneWithoutBody() {
return new Message(this.code, this.message, this.header.clone(), null);
}
/**
* @return Map消息主体
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
/**
* @return Map消息主体
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public Map<String, Object> body() {
if(this.body instanceof Map) {
if (this.body instanceof Map) {
return (Map<String, Object>) this.body;
} else if(this.body == null) {
} else if (this.body == null) {
return new HashMap<>();
} else {
throw MessageCodeException.of("信令主体类型错误:" + this.body);
}
}
}
@Override
public String toString() {
return JSONUtils.toJSON(this);
}
@Override
public String toString() {
return JSONUtils.toJSON(this);
}
public Message() {
}
public Message() {
}
public Message(String code, String message, Header header, Object body) {
this.code = code;
this.message = message;
this.header = header;
this.body = body;
}
public Message(String code, String message, Header header, Object body) {
this.code = code;
this.message = message;
this.header = header;
this.body = body;
}
public String getCode() {
return code;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setMessage(String message) {
this.message = message;
}
public Header getHeader() {
return header;
}
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
public void setHeader(Header header) {
this.header = header;
}
public Object getBody() {
return body;
}
public Object getBody() {
return body;
}
public void setBody(Object body) {
this.body = body;
}
public void setBody(Object body) {
this.body = body;
}
}

View File

@@ -2,7 +2,7 @@ package com.acgist.taoyao.boot.model;
/**
* 状态编码
*
* <p>
* 1xxx = 前置错误
* 2xxx = 内部错误
* 3xxx = 请求错误
@@ -12,88 +12,86 @@ package com.acgist.taoyao.boot.model;
*/
public enum MessageCode {
// 成功
CODE_0000("0000", 200, "成功"),
// 1xxx
CODE_1000("1000", 404, "未知接口"),
CODE_1001("1001", 400, "上次请求没有完成"),
CODE_1002("1002", 400, "数据格式错误"),
CODE_1003("1003", 400, "验签失败"),
// 2xxx
CODE_2000("2000", 500, "服务错误"),
CODE_2001("2001", 504, "服务超时"),
// 3xxx
CODE_3400("3400", 400, "请求错误"),
CODE_3401("3401", 401, "没有授权"),
CODE_3403("3403", 403, "请求拒绝"),
CODE_3404("3404", 404, "资源失效"),
CODE_3405("3405", 405, "请求方法错误"),
CODE_3406("3406", 406, "请求不可接受"),
CODE_3415("3415", 415, "请求资源类型错误"),
CODE_3500("3500", 500, "系统异常"),
CODE_3502("3502", 502, "服务无效"),
CODE_3503("3503", 503, "服务正在维护"),
CODE_3504("3504", 504, "服务超时"),
// 9999
CODE_9999("9999", 500, "未知错误");
// 成功
CODE_0000("0000", 200, "成功"),
// 1xxx
CODE_1000("1000", 404, "未知接口"),
CODE_1001("1001", 400, "上次请求没有完成"),
CODE_1002("1002", 400, "数据格式错误"),
CODE_1003("1003", 400, "验签失败"),
// 2xxx
CODE_2000("2000", 500, "服务错误"),
CODE_2001("2001", 504, "服务超时"),
// 3xxx
CODE_3400("3400", 400, "请求错误"),
CODE_3401("3401", 401, "没有授权"),
CODE_3403("3403", 403, "请求拒绝"),
CODE_3404("3404", 404, "资源失效"),
CODE_3405("3405", 405, "请求方法错误"),
CODE_3406("3406", 406, "请求不可接受"),
CODE_3415("3415", 415, "请求资源类型错误"),
CODE_3500("3500", 500, "系统异常"),
CODE_3502("3502", 502, "服务无效"),
CODE_3503("3503", 503, "服务正在维护"),
CODE_3504("3504", 504, "服务超时"),
// 9999
CODE_9999("9999", 500, "未知错误");
/**
* HTTP状态编码前缀
*/
private static final String HTTP_STATUS = "3";
/**
* HTTP状态编码前缀
*/
private static final String HTTP_STATUS = "3";
/**
* 状态编码
*/
private final String code;
/**
* 状态数值
*/
private final Integer status;
/**
* 状态描述
*/
private final String message;
/**
* 状态编码
*/
private final String code;
/**
* 状态数值
*/
private final Integer status;
/**
* 状态描述
*/
private final String message;
private MessageCode(String code, Integer status, String message) {
this.code = code;
this.status = status;
this.message = message;
}
private MessageCode(String code, Integer status, String message) {
this.code = code;
this.status = status;
this.message = message;
}
/**
* @param code 状态编码
*
* @return 状态编码
*/
public static final MessageCode of(String code) {
final MessageCode[] values = MessageCode.values();
for (MessageCode value : values) {
if (value.code.equals(code)) {
return value;
}
}
return CODE_9999;
}
/**
* @param code 状态编码
* @return 状态编码
*/
public static final MessageCode of(String code) {
final MessageCode[] values = MessageCode.values();
for (MessageCode value : values) {
if (value.code.equals(code)) {
return value;
}
}
return CODE_9999;
}
/**
* @param status HTTP Status
*
* @return 状态编码
*/
public static final MessageCode of(Integer status) {
return of(HTTP_STATUS + status);
}
/**
* @param status HTTP Status
* @return 状态编码
*/
public static final MessageCode of(Integer status) {
return of(HTTP_STATUS + status);
}
public String getCode() {
return code;
}
public String getCode() {
return code;
}
public Integer getStatus() {
return status;
}
public Integer getStatus() {
return status;
}
public String getMessage() {
return message;
}
public String getMessage() {
return message;
}
}

View File

@@ -9,67 +9,63 @@ import java.util.Objects;
*/
public class MessageCodeException extends RuntimeException {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/**
* 状态编码
*/
private final MessageCode code;
/**
* 状态编码
*/
private final MessageCode code;
/**
* @param message 异常消息
*
* @return 状态编码异常
*/
public static final MessageCodeException of(String message) {
return of(null, null, message);
}
/**
* @param message 异常消息
* @return 状态编码异常
*/
public static final MessageCodeException of(String message) {
return of(null, null, message);
}
/**
* @param t 异常
* @param message 异常消息
*
* @return 状态编码异常
*/
public static final MessageCodeException of(Throwable t, String message) {
return of(t, null, message);
}
/**
* @param t 异常
* @param message 异常消息
* @return 状态编码异常
*/
public static final MessageCodeException of(Throwable t, String message) {
return of(t, null, message);
}
/**
* @param code 状态编码
* @param message 异常消息
*
* @return 状态编码异常
*/
public static final MessageCodeException of(MessageCode code, String message) {
return of(null, code, message);
}
/**
* @param code 状态编码
* @param message 异常消息
* @return 状态编码异常
*/
public static final MessageCodeException of(MessageCode code, String message) {
return of(null, code, message);
}
/**
* @param t 异常
* @param code 状态编码
* @param message 异常消息
*
* @return 状态编码异常
*/
public static final MessageCodeException of(Throwable t, MessageCode code, String message) {
if(code == null) {
code = MessageCode.CODE_9999;
}
if(message == null || message.isEmpty()) {
message = Objects.isNull(t) ? code.getMessage() : t.getMessage();
}
return new MessageCodeException(t, code, message);
}
/**
* @param t 异常
* @param code 状态编码
* @param message 异常消息
* @return 状态编码异常
*/
public static final MessageCodeException of(Throwable t, MessageCode code, String message) {
if (code == null) {
code = MessageCode.CODE_9999;
}
if (message == null || message.isEmpty()) {
message = Objects.isNull(t) ? code.getMessage() : t.getMessage();
}
return new MessageCodeException(t, code, message);
}
/**
* @param t 异常
* @param code 状态编码
* @param message 异常消息
*/
public MessageCodeException(Throwable t, MessageCode code, String message) {
super(message, t);
this.code = code;
}
/**
* @param t 异常
* @param code 状态编码
* @param message 异常消息
*/
public MessageCodeException(Throwable t, MessageCode code, String message) {
super(message, t);
this.code = code;
}
}

View File

@@ -9,37 +9,37 @@ import java.io.Closeable;
*/
public final class CloseableUtils {
private CloseableUtils() {
}
private CloseableUtils() {
}
/**
* 关闭资源
*
* @param closeable 资源
*/
public static final void close(Closeable closeable) {
try {
if(closeable != null) {
closeable.close();
}
} catch (Exception e) {
// TODO日志
}
}
/**
* 关闭资源
*
* @param closeable 资源
*/
public static final void close(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
// TODO日志
}
}
/**
* 关闭资源
*
* @param closeable 资源
*/
public static final void close(AutoCloseable closeable) {
try {
if(closeable != null) {
closeable.close();
}
} catch (Exception e) {
// TODO日志
}
}
/**
* 关闭资源
*
* @param closeable 资源
*/
public static final void close(AutoCloseable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
// TODO日志
}
}
}

View File

@@ -15,8 +15,8 @@ import java.util.Objects;
*/
public final class DateUtils {
private DateUtils() {
}
private DateUtils() {
}
/**
* 日期
@@ -44,52 +44,53 @@ public final class DateUtils {
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
public String getFormat() {
return this.format;
}
public String getFormat() {
return this.format;
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
}
/**
* 时间
*
* @author acgist
*/
public static enum TimeStyle {
/**
* 时间
*
* @author acgist
*/
public static enum TimeStyle {
HH24("HH"),
HH24MM("HHmm"),
HH24_MM("HH:mm"),
HH24MMSS("HHmmss"),
HH24_MM_SS("HH:mm:ss"),
HH24MMSSSSS("HHmmssSSS"),
HH24_MM_SS_SSS("HH:mm:ss.SSS");
HH24("HH"),
HH24MM("HHmm"),
HH24_MM("HH:mm"),
HH24MMSS("HHmmss"),
HH24_MM_SS("HH:mm:ss"),
HH24MMSSSSS("HHmmssSSS"),
HH24_MM_SS_SSS("HH:mm:ss.SSS");
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private TimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
public String getFormat() {
return this.format;
}
private TimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
public String getFormat() {
return this.format;
}
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
}
/**
* 日期时间
@@ -140,119 +141,111 @@ public final class DateUtils {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
public String getFormat() {
return this.format;
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
public String getFormat() {
return this.format;
}
public DateTimeFormatter getDateTimeFormatter() {
return this.dateTimeFormatter;
}
}
/**
* 生成时间戳
*
* @return 时间戳
*
* @see #buildTime(LocalDateTime)
*/
public static final String buildTime() {
return buildTime(LocalDateTime.now());
}
/**
* 生成时间戳
*
* @return 时间戳
* @see #buildTime(LocalDateTime)
*/
public static final String buildTime() {
return buildTime(LocalDateTime.now());
}
/**
* 生成时间戳
*
* @param localDateTime 日期时间
*
* @return 时间戳
*/
public static final String buildTime(LocalDateTime localDateTime) {
if (Objects.isNull(localDateTime)) {
return buildTime();
}
return DateTimeStyle.YYYYMMDDHH24MMSS.getDateTimeFormatter().format(localDateTime);
}
/**
* 生成时间戳
*
* @param localDateTime 日期时间
* @return 时间戳
*/
public static final String buildTime(LocalDateTime localDateTime) {
if (Objects.isNull(localDateTime)) {
return buildTime();
}
return DateTimeStyle.YYYYMMDDHH24MMSS.getDateTimeFormatter().format(localDateTime);
}
/**
* 日期转化
*
* @param date Date
*
* @return LocalDate
*/
public static final LocalDate toLocalDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* 日期转化
*
* @param date Date
* @return LocalDate
*/
public static final LocalDate toLocalDate(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* 日期转化
*
* @param date Date
*
* @return LocalTime
*/
public static final LocalTime toLocalTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
}
/**
* 日期转化
*
* @param date Date
* @return LocalTime
*/
public static final LocalTime toLocalTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
}
/**
* 日期转化
*
* @param date Date
*
* @return LocalDateTime
*/
public static final LocalDateTime toLocalDateTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* 日期转化
*
* @param date Date
* @return LocalDateTime
*/
public static final LocalDateTime toLocalDateTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* 转换毫秒
*
* @param localDateTime LocalDateTime
*
* @return 毫秒
*/
public static final long toMilli(LocalDateTime localDateTime) {
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* 转换毫秒
*
* @param localDateTime LocalDateTime
* @return 毫秒
*/
public static final long toMilli(LocalDateTime localDateTime) {
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* 格式化日期
*
* @param localDate LocalDate
* @param format 格式
*
* @return 日期字符串
*/
public static String format(LocalDate localDate, DateStyle format) {
return localDate != null && format != null ? format.getDateTimeFormatter().format(localDate) : null;
}
/**
* 格式化日期
*
* @param localDate LocalDate
* @param format 格式
* @return 日期字符串
*/
public static String format(LocalDate localDate, DateStyle format) {
return localDate != null && format != null ? format.getDateTimeFormatter().format(localDate) : null;
}
/**
* 格式化时间
*
* @param localTime LocalTime
* @param format 格式
*
* @return 时间字符串
*/
public static String format(LocalTime localTime, TimeStyle format) {
return localTime != null && format != null ? format.getDateTimeFormatter().format(localTime) : null;
}
/**
* 格式化时间
*
* @param localTime LocalTime
* @param format 格式
* @return 时间字符串
*/
public static String format(LocalTime localTime, TimeStyle format) {
return localTime != null && format != null ? format.getDateTimeFormatter().format(localTime) : null;
}
/**
* 格式化日期时间
*
* @param localDateTime LocalDateTime
* @param format 格式
*
* @return 日期时间字符串
*/
public static String format(LocalDateTime localDateTime, DateTimeStyle format) {
return localDateTime != null && format != null ? format.getDateTimeFormatter().format(localDateTime) : null;
}
/**
* 格式化日期时间
*
* @param localDateTime LocalDateTime
* @param format 格式
* @return 日期时间字符串
*/
public static String format(LocalDateTime localDateTime, DateTimeStyle format) {
return localDateTime != null && format != null ? format.getDateTimeFormatter().format(localDateTime) : null;
}
}

View File

@@ -30,196 +30,183 @@ import java.util.*;
*/
public final class JSONUtils {
private JSONUtils() {
}
private JSONUtils() {
}
/**
* Mapper线程安全
*/
private static final ObjectMapper MAPPER = buildMapper();
/**
* Mapper线程安全
*/
private static final ObjectMapper MAPPER = buildMapper();
/**
* Java转JSON
*
* @param object Java
*
* @return JSON
*/
public static final String toJSON(Object object) {
if (Objects.isNull(object)) {
return null;
}
try {
return MAPPER.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException("Java转JSON失败" + object, e);
}
}
/**
* Java转JSON
*
* @param object Java
* @return JSON
*/
public static final String toJSON(Object object) {
if (Objects.isNull(object)) {
return null;
}
try {
return MAPPER.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException("Java转JSON失败" + object, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
*
* @param json JSON
*
* @return Java
*/
public static final <T> T toJava(String json) {
if (Objects.isNull(json)) {
return null;
}
try {
return MAPPER.readValue(json, new TypeReference<T>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
* @param json JSON
* @return Java
*/
public static final <T> T toJava(String json) {
if (Objects.isNull(json)) {
return null;
}
try {
return MAPPER.readValue(json, new TypeReference<T>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
*
* @param json JSON
* @param clazz Java类型
*
* @return Java
*/
public static final <T> T toJava(String json, Class<T> clazz) {
if (Objects.isNull(json) || Objects.isNull(clazz)) {
return null;
}
try {
return MAPPER.readValue(json, clazz);
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
* @param json JSON
* @param clazz Java类型
* @return Java
*/
public static final <T> T toJava(String json, Class<T> clazz) {
if (Objects.isNull(json) || Objects.isNull(clazz)) {
return null;
}
try {
return MAPPER.readValue(json, clazz);
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
*
* @param json JSON
* @param type Java类型
*
* @return Java
*/
public static final <T> T toJava(String json, TypeReference<T> type) {
if (Objects.isNull(json) || Objects.isNull(type)) {
return null;
}
try {
return MAPPER.readValue(json, type);
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Java
*
* @param <T> Java类型
* @param json JSON
* @param type Java类型
* @return Java
*/
public static final <T> T toJava(String json, TypeReference<T> type) {
if (Objects.isNull(json) || Objects.isNull(type)) {
return null;
}
try {
return MAPPER.readValue(json, type);
} catch (IOException e) {
throw new RuntimeException("JSON转Java失败" + json, e);
}
}
/**
* JSON转Map
*
* @param <K> K类型
* @param <V> V类型
*
* @param json JSON
*
* @return Map
*/
public static final <K, V> Map<K, V> toMap(String json) {
if (Objects.isNull(json)) {
return new HashMap<>();
}
try {
return MAPPER.readValue(json, new TypeReference<Map<K, V>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转Map失败" + json, e);
}
}
/**
* JSON转Map
*
* @param <K> K类型
* @param <V> V类型
* @param json JSON
* @return Map
*/
public static final <K, V> Map<K, V> toMap(String json) {
if (Objects.isNull(json)) {
return new HashMap<>();
}
try {
return MAPPER.readValue(json, new TypeReference<Map<K, V>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转Map失败" + json, e);
}
}
/**
* JSON转List
*
* @param <T> 元素类型
*
* @param json JSON
*
* @return List
*/
public static final <T> List<T> toList(String json) {
if (Objects.isNull(json)) {
return new ArrayList<>();
}
try {
return MAPPER.readValue(json, new TypeReference<List<T>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转List失败" + json, e);
}
}
/**
* JSON转List
*
* @param <T> 元素类型
* @param json JSON
* @return List
*/
public static final <T> List<T> toList(String json) {
if (Objects.isNull(json)) {
return new ArrayList<>();
}
try {
return MAPPER.readValue(json, new TypeReference<List<T>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转List失败" + json, e);
}
}
/**
* JSON转List
*
* @param <T> 元素类型
*
* @param json JSON
* @param clazz 类型
*
* @return List
*/
public static final <T> List<T> toList(String json, Class<T> clazz) {
if (Objects.isNull(json)) {
return new ArrayList<>();
}
try {
return MAPPER.readValue(json, new TypeReference<List<T>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转List失败" + json, e);
}
}
/**
* JSON转List
*
* @param <T> 元素类型
* @param json JSON
* @param clazz 类型
* @return List
*/
public static final <T> List<T> toList(String json, Class<T> clazz) {
if (Objects.isNull(json)) {
return new ArrayList<>();
}
try {
return MAPPER.readValue(json, new TypeReference<List<T>>() {
});
} catch (IOException e) {
throw new RuntimeException("JSON转List失败" + json, e);
}
}
/**
* @return Mapper
*/
public static final ObjectMapper buildMapper() {
final ObjectMapper mapper = new ObjectMapper();
return mapper
.setTimeZone(TimeZone.getDefault())
.setDateFormat(new SimpleDateFormat(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getFormat()))
.registerModules(buildCustomModule(), buildJavaTimeModule())
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.setSerializationInclusion(Include.NON_NULL);
}
/**
* @return Mapper
*/
public static final ObjectMapper buildMapper() {
final ObjectMapper mapper = new ObjectMapper();
return mapper
.setTimeZone(TimeZone.getDefault())
.setDateFormat(new SimpleDateFormat(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getFormat()))
.registerModules(buildCustomModule(), buildJavaTimeModule())
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.setSerializationInclusion(Include.NON_NULL);
}
/**
* @return Java类型转换模块
*/
private static final Module buildCustomModule() {
final SimpleModule customModule = new SimpleModule("CustomModule");
// 注意不能转换Long类型数据请求数据类型变化
/**
* @return Java类型转换模块
*/
private static final Module buildCustomModule() {
final SimpleModule customModule = new SimpleModule("CustomModule");
// 注意不能转换Long类型数据请求数据类型变化
// customModule.addSerializer(Long.class, ToStringSerializer.instance);
return customModule;
}
return customModule;
}
/**
* @return Java时间类型模块
*/
private static final JavaTimeModule buildJavaTimeModule() {
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateUtils.TimeStyle.HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateUtils.DateStyle.YYYY_MM_DD.getDateTimeFormatter()));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateUtils.TimeStyle.HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateUtils.DateStyle.YYYY_MM_DD.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getDateTimeFormatter()));
return javaTimeModule;
}
/**
* @return Java时间类型模块
*/
private static final JavaTimeModule buildJavaTimeModule() {
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateUtils.TimeStyle.HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateUtils.DateStyle.YYYY_MM_DD.getDateTimeFormatter()));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateUtils.TimeStyle.HH24_MM_SS.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateUtils.DateStyle.YYYY_MM_DD.getDateTimeFormatter()));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateUtils.DateTimeStyle.YYYY_MM_DD_HH24_MM_SS.getDateTimeFormatter()));
return javaTimeModule;
}
}

View File

@@ -30,13 +30,11 @@ android {
dependencies {
implementation project(path: ':boot')
implementation project(path: ':mediasoup')
implementation project(path: ':media')
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"

View File

@@ -3,5 +3,5 @@ package com.acgist.taoyao.client.media;
/**
* 终端
*/
public class MediaClient {
public class Client {
}

View File

@@ -0,0 +1,4 @@
package com.acgist.taoyao.client.media;
public class Room {
}

View File

@@ -1,15 +1,13 @@
package com.acgist.taoyao.client.signal;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import com.acgist.taoyao.boot.model.Header;
import com.acgist.taoyao.boot.model.Message;
import com.acgist.taoyao.boot.utils.CloseableUtils;
import com.acgist.taoyao.boot.utils.JSONUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
@@ -24,6 +22,12 @@ import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
/**
* 桃夭信令
*
@@ -38,19 +42,21 @@ public class Taoyao {
/**
* 端口
*/
private int port;
private final int port;
/**
* 地址
*/
private String host;
private final String host;
private final String clientId;
private final String name;
private final String username;
private final String password;
/**
* Socket
*/
private Socket socket;
private InputStream input;
private OutputStream output;
private String username;
private String password;
private boolean close;
/**
* 是否连接
@@ -58,13 +64,18 @@ public class Taoyao {
private boolean connect;
private final Cipher encrypt;
private final Cipher decrypt;
private final WifiManager wifiManager;
private final BatteryManager batteryManager;
public Taoyao(int port, String host, String algo, String secret) {
public Taoyao(
int port, String host, String algo, String secret, String clientId, String name, String username, String password,
WifiManager wifiManager, BatteryManager batteryManager
) {
this.port = port;
this.host = host;
this.close = false;
this.connect = false;
if(algo == null || algo.isEmpty() || algo.equals("PLAINTEXT")) {
if (algo == null || algo.isEmpty() || algo.equals("PLAINTEXT")) {
// 明文
this.encrypt = null;
this.decrypt = null;
@@ -72,6 +83,12 @@ public class Taoyao {
this.encrypt = this.buildCipher(Cipher.ENCRYPT_MODE, algo, secret);
this.decrypt = this.buildCipher(Cipher.DECRYPT_MODE, algo, secret);
}
this.clientId = clientId;
this.name = name;
this.username = username;
this.password = password;
this.wifiManager = wifiManager;
this.batteryManager = batteryManager;
EXECUTOR.submit(this::read);
}
@@ -95,9 +112,9 @@ public class Taoyao {
// HiLog.debug(this.label, "连接信令:%s:%d", this.host, this.port);
this.socket = new Socket();
try {
// socket.setSoTimeout(5000);
// socket.setSoTimeout(5000);
this.socket.connect(new InetSocketAddress(this.host, this.port), 5000);
if(this.socket.isConnected()) {
if (this.socket.isConnected()) {
this.input = this.socket.getInputStream();
this.output = this.socket.getOutputStream();
this.register();
@@ -116,9 +133,9 @@ public class Taoyao {
short messageLength = 0;
final byte[] bytes = new byte[1024];
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while(!this.close) {
while (!this.close) {
try {
while(this.input == null) {
while (this.input == null) {
this.connect();
synchronized (this) {
this.wait(5000);
@@ -168,12 +185,11 @@ public class Taoyao {
/**
* @param message 消息
*
* @return 加密消息
*/
private byte[] encrypt(Message message) {
final byte[] bytes = message.toString().getBytes();
if(this.encrypt != null) {
if (this.encrypt != null) {
try {
// 加密
final byte[] encryptBytes = this.encrypt.doFinal(bytes);
@@ -194,7 +210,7 @@ public class Taoyao {
}
public void push(Message message) {
if(this.output == null) {
if (this.output == null) {
return;
}
try {
@@ -211,15 +227,22 @@ public class Taoyao {
private void register() {
final Header header = new Header();
this.push(this.buildMessage(
"client::register",
"clientId", "harmony",
"name", "harmony",
"clientType", "camera",
"username", "taoyao",
"password","taoyao"
"client::register",
"clientId", this.clientId,
"name", this.name,
"clientType", "camera",
"username", this.username,
"password", this.password,
"signal", this.wifiManager.getMaxSignalLevel(),
"batter", this.batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY),
"charging", this.batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS)
));
}
private void heartbeat() {
}
private void close() {
this.connect = false;
CloseableUtils.close(this.input);
@@ -258,19 +281,19 @@ public class Taoyao {
final LocalDateTime time = LocalDateTime.now();
return
100000000000000L * time.getDayOfMonth() +
1000000000000L * time.getHour() +
10000000000L * time.getMinute() +
100000000L * time.getSecond() +
1000000L * this.clientIndex +
index;
1000000000000L * time.getHour() +
10000000000L * time.getMinute() +
100000000L * time.getSecond() +
1000000L * this.clientIndex +
index;
}
private String version;
public Message buildMessage(String signal, Object ... args) {
public Message buildMessage(String signal, Object... args) {
final Map<Object, Object> map = new HashMap<>();
if(args != null) {
for (int index = 0; index < args.length; index+=2) {
if (args != null) {
for (int index = 0; index < args.length; index += 2) {
map.put(args[index], args[index + 1]);
}
}
@@ -293,11 +316,11 @@ public class Taoyao {
// log.debug("收到消息:{}", new String(this.decrypt.doFinal(message)));
System.out.println(content);
final Message message = JSONUtils.toJava(content, Message.class);
if(message == null) {
if (message == null) {
return;
}
final Header header = message.getHeader();
if(header == null) {
if (header == null) {
return;
}
final Map<String, Object> body = message.body();

View File

@@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.22.1)
project(taoyao VERSION 1.0.0 LANGUAGES C CXX)
# Debug | Release
#-DCMAKE_BUILD_TYPE=Debug
#set(CMAKE_BUILD_TYPE Debug)
# C编译选项
set(CMAKE_C_STANDARD 17)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c17 -O3")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c17 -O0 -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=c17 -O3")
# C++编译选项
set(CMAKE_CXX_STANDARD 17)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++17 -O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++17 -O3")
set(
SOURCE_DIR
src/main/cpp/
)
set(
SOURCE_FILES
${SOURCE_DIR}/main.hpp
${SOURCE_DIR}/main.cpp
)
set(LIBWEBRTC_BINARY_PATH ${LIBWEBRTC_BINARY_PATH}/${ANDROID_ABI} CACHE STRING "libwebrtc binary path" FORCE)
if (${MEDIASOUPCLIENT_LOG_TRACE})
target_compile_definitions(
${PROJECT_NAME} PRIVATE MSC_LOG_TRACE=1
)
endif ()
if (${MEDIASOUPCLIENT_LOG_DEV})
target_compile_definitions(
${PROJECT_NAME} PRIVATE MSC_LOG_DEV=1
)
endif ()
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
add_subdirectory("deps/libmediasoupclient")
set_source_files_properties(
${SOURCE_FILES} PROPERTIES COMPILE_FLAGS -Wall -Wextra -Wpedantic
)
target_include_directories(
${PROJECT_NAME} PUBLIC
"${SOURCE_DIR}/include"
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/include"
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/deps/libsdptransform/include"
)
target_link_libraries(
${PROJECT_NAME} PUBLIC
log
android
OpenSLES
mediasoupclient
)

View File

@@ -14,7 +14,6 @@ android {
versionCode 100
versionName "1.0.0"
consumerProguardFiles "consumer-rules.pro"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cFlags '-std=c17'
@@ -22,10 +21,10 @@ android {
// CPU架构x86_64x86arm64-v8aarmeabi-v7a
abiFilters 'arm64-v8a'
arguments "-DLIBWEBRTC_INCLUDE_PATH=" + WEBRTC_INC_PATH,
"-DLIBWEBRTC_BINARY_PATH=" + WEBRTC_LIB_PATH,
"-DMEDIASOUPCLIENT_BUILD_TESTS=OFF",
"-DMEDIASOUPCLIENT_LOG_TRACE=OFF",
"-DMEDIASOUPCLIENT_LOG_DEV=OFF"
"-DLIBWEBRTC_BINARY_PATH=" + WEBRTC_LIB_PATH,
"-DMEDIASOUPCLIENT_BUILD_TESTS=OFF",
"-DMEDIASOUPCLIENT_LOG_TRACE=OFF",
"-DMEDIASOUPCLIENT_LOG_DEV=OFF"
}
}
}
@@ -48,11 +47,8 @@ android {
}
dependencies {
api fileTree(dir: WEBRTC_LIB_PATH, include: ['libwebrtc.jar'])
implementation fileTree(dir: 'libs', include: ['*.a', '*.so', '*.jar'])
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@@ -5,10 +5,11 @@
extern "C" JNIEXPORT jstring JNICALL
Java_com_acgist_taoyao_client_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
JNIEnv *env,
jobject /* this */
) {
mediasoupclient::Device device;
if(device.IsLoaded()) {
if (device.IsLoaded()) {
std::string hello = "Hello from C++ true";
return env->NewStringUTF(hello.c_str());
} else {

View File

@@ -1,76 +0,0 @@
cmake_minimum_required(VERSION 3.22.1)
project(taoyao VERSION 1.0.0 LANGUAGES C CXX)
# Debug | Release
# -DCMAKE_BUILD_TYPE=Debug
# set(CMAKE_BUILD_TYPE Debug)
# C编译选项
#set(CMAKE_C_STANDARD 17)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c17 -O3")
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c17 -O0 -g")
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=c17 -O3")
# C++编译选项
#set(CMAKE_CXX_STANDARD 17)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")
#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++17 -O0 -g")
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++17 -O3")
set(
SOURCE_DIR
src/main/cpp/
)
set(
SOURCE_FILES
${SOURCE_DIR}/main.hpp
${SOURCE_DIR}/main.cpp
)
set(LIBWEBRTC_BINARY_PATH ${LIBWEBRTC_BINARY_PATH}/${ANDROID_ABI} CACHE STRING "libwebrtc binary path" FORCE)
if (${MEDIASOUPCLIENT_LOG_TRACE})
target_compile_definitions(
${PROJECT_NAME} PRIVATE MSC_LOG_TRACE=1
)
endif ()
if (${MEDIASOUPCLIENT_LOG_DEV})
target_compile_definitions(
${PROJECT_NAME} PRIVATE MSC_LOG_DEV=1
)
endif ()
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
add_subdirectory("deps/libmediasoupclient")
set_source_files_properties(
${SOURCE_FILES} PROPERTIES COMPILE_FLAGS -Wall -Wextra -Wpedantic
)
target_include_directories(
${PROJECT_NAME} PUBLIC
"${SOURCE_DIR}/include"
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/include"
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/deps/libsdptransform/include"
)
target_compile_definitions(
${PROJECT_NAME} PUBLIC
$<$<NOT:$<PLATFORM_ID:Windows>>:WEBRTC_POSIX>
$<$<PLATFORM_ID:Darwin>:WEBRTC_MAC>
$<$<PLATFORM_ID:Windows>:NOMINMAX>
$<$<PLATFORM_ID:Windows>:WEBRTC_WIN>
$<$<PLATFORM_ID:Windows>:WIN32_LEAN_AND_MEAN>
)
target_link_libraries(
${PROJECT_NAME} PUBLIC
log
android
OpenSLES
mediasoupclient
)

View File

@@ -14,5 +14,5 @@ dependencyResolutionManagement {
}
rootProject.name = "taoyao"
include ':boot'
include ':media'
include ':client'
include ':mediasoup'

View File

@@ -12,4 +12,3 @@
## 信令格式
[信令格式](https://localhost:8888/protocol/list)