Compare commits
9 Commits
dyf-device
...
dbb7076b50
| Author | SHA1 | Date | |
|---|---|---|---|
| dbb7076b50 | |||
| 15c85d4c62 | |||
| e036ef05ce | |||
| 03f453f901 | |||
| e23c5267ee | |||
| 552bf0af0a | |||
| efad1f5a4b | |||
| f3551be093 | |||
| 855714106e |
@ -146,12 +146,6 @@
|
||||
<version>3.3.1</version>
|
||||
</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>ws.schild</groupId>
|
||||
<artifactId>jave-all-deps</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- skywalking 整合 logback -->
|
||||
<!-- <dependency>-->
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package com.fuyuanshen.app.controller;
|
||||
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.app.service.AppFileService;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package com.fuyuanshen.app.controller;
|
||||
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.app.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.equipment.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
|
||||
@ -55,6 +55,31 @@ public class AppDeviceHBY100JController extends BaseController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报
|
||||
*
|
||||
*/
|
||||
@PostMapping("/voiceBroadcast")
|
||||
public R<Void> voiceBroadcast(@RequestBody HBY100JVoiceBroadcastDto params) {
|
||||
deviceHBY100JBizService.voiceBroadcast(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@Data
|
||||
public static class HBY100JVoiceBroadcastDto {
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
Long deviceId;
|
||||
/**
|
||||
* 0 关闭, 1开启
|
||||
*/
|
||||
private Integer voiceBroadcast;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 爆闪模式
|
||||
*/
|
||||
@ -112,7 +137,7 @@ public class AppDeviceHBY100JController extends BaseController {
|
||||
*/
|
||||
private Integer voiceStrobeAlarm;
|
||||
/**
|
||||
* 0 公安,1消防,2应急,3交警,4 市政,5 铁路,6 医疗,7部队,8 水利,9 语音
|
||||
* 0 公安,1消防,2应急,3交警,4 市政,5 铁路,6 医疗,7语音
|
||||
*/
|
||||
private Integer mode;
|
||||
|
||||
|
||||
@ -47,22 +47,25 @@ public class HttpTtsClient {
|
||||
/**
|
||||
* 使用HTTP POST方式调用阿里云TTS服务生成MP3格式语音
|
||||
*/
|
||||
public byte[] synthesizeTextToMp3(String text) throws IOException {
|
||||
public byte[] synthesizeTextToMp3(String text,String fileSuffix) throws IOException {
|
||||
String endpoint = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
|
||||
|
||||
// 构建请求体
|
||||
// String requestBody = String.format(
|
||||
// "{\"appkey\":\"%s\",\"text\":\"%s\",\"voice\":\"zhifeng\",\"format\":\"MP3\",\"sample_rate\":24000,\"volume\":50,\"speech_rate\":0,\"pitch_rate\":0}",
|
||||
// appKey,
|
||||
// text.replace("\"", "\\\"")
|
||||
// text.replace("\"", "\\\"")zhide
|
||||
// );
|
||||
|
||||
String token = refreshAccessToken();
|
||||
String requestBody = " {\n" +
|
||||
" \"appkey\":\""+appKey+"\",\n" +
|
||||
" \"voice\":\"zhide\",\n" +
|
||||
" \"text\":\""+text+"\",\n" +
|
||||
" \"token\":\""+token+"\",\n" +
|
||||
" \"format\":\"mp3\"\n" +
|
||||
" \"volume\": 100,\n" +
|
||||
" \"pitch_rate\": 0,\n" +
|
||||
" \"format\":\""+fileSuffix+"\"\n" +
|
||||
" }";
|
||||
|
||||
URL url = new URL(endpoint);
|
||||
@ -119,7 +122,7 @@ public class HttpTtsClient {
|
||||
* 保存MP3到文件
|
||||
*/
|
||||
public String saveMp3ToFile(String text, String outputPath) throws IOException {
|
||||
byte[] mp3Data = synthesizeTextToMp3(text);
|
||||
byte[] mp3Data = synthesizeTextToMp3(text,"mp3");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
||||
fos.write(mp3Data);
|
||||
|
||||
@ -19,8 +19,8 @@ public class HttpTtsExample {
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(accessKeyId, accessKeySecret, appKey);
|
||||
|
||||
String text = "大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。";
|
||||
String outputPath = "D:\\http_output9.mp3";
|
||||
String text = "前方拥堵,请绕道而行。";
|
||||
String outputPath = "D:\\http_output11.mp3";
|
||||
|
||||
String resultFile = httpClient.saveMp3ToFile(text, outputPath);
|
||||
System.out.println("MP3音频已保存至: " + resultFile);
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.oss.core.OssClient;
|
||||
import com.fuyuanshen.common.oss.factory.OssFactory;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.equipment.utils.FileHashUtil;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.service.ISysOssService;
|
||||
|
||||
@ -10,14 +10,18 @@ import com.fuyuanshen.app.http.HttpTtsClient;
|
||||
import com.fuyuanshen.app.mapper.AppBusinessFileMapper;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.common.satoken.utils.LoginHelper;
|
||||
import com.fuyuanshen.equipment.utils.AlibabaTTSUtil;
|
||||
import com.fuyuanshen.equipment.utils.AudioProcessUtil;
|
||||
import com.fuyuanshen.equipment.utils.FileHashUtil;
|
||||
import com.fuyuanshen.equipment.utils.Mp3Duration;
|
||||
import com.fuyuanshen.global.mqtt.utils.FfmpegVolumeUtil;
|
||||
import com.fuyuanshen.global.mqtt.utils.FfmpegVolumeUtil3;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.service.ISysOssService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@ -30,7 +34,6 @@ import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
@ -62,6 +65,16 @@ public class AudioProcessService {
|
||||
private final IAppBusinessFileService appBusinessFileService;
|
||||
private final AppBusinessFileMapper appBusinessFileMapper;
|
||||
|
||||
// String accessKeyId = "LTAI5t66moCkhNC32TDJ5ReP";
|
||||
// String accessKeySecret = "2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH";
|
||||
// String appKey = "lbGuq5K5bEH4uxmT";
|
||||
@Value("${alibaba.tts.appKey}")
|
||||
private String appKey;
|
||||
@Value("${alibaba.tts.akId}")
|
||||
private String accessKeyId;
|
||||
@Value("${alibaba.tts.akSecret}")
|
||||
private String accessKeySecret;
|
||||
|
||||
/**
|
||||
* 处理上传的音频文件
|
||||
*/
|
||||
@ -181,7 +194,7 @@ public class AudioProcessService {
|
||||
|
||||
private String saveByteArrayToFile(byte[] data, String filename) throws IOException {
|
||||
// 确定保存路径(可以是临时目录或指定目录)
|
||||
String directory = System.getProperty("java.io.tmpdir"); // 使用系统临时目录
|
||||
String directory = System.getProperty("java.io.tmpdir");// 使用系统临时目录
|
||||
File dir = new File(directory);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
@ -195,6 +208,7 @@ public class AudioProcessService {
|
||||
fos.write(data);
|
||||
}
|
||||
|
||||
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
@ -446,37 +460,45 @@ public class AudioProcessService {
|
||||
if (!contains) {
|
||||
throw new IllegalArgumentException("不支持的音频格式");
|
||||
}
|
||||
String accessKeyId = "LTAI5t66moCkhNC32TDJ5ReP";
|
||||
String accessKeySecret = "2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH";
|
||||
String appKey = "lbGuq5K5bEH4uxmT";
|
||||
// String accessKeyId = "LTAI5t66moCkhNC32TDJ5ReP";
|
||||
// String accessKeySecret = "2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH";
|
||||
// String appKey = "lbGuq5K5bEH4uxmT";
|
||||
String savedPath = null;
|
||||
String savedMp3VolumePath = null;
|
||||
try {
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(accessKeyId, accessKeySecret, appKey);
|
||||
//
|
||||
byte[] mp3Data = httpClient.synthesizeTextToMp3(text);
|
||||
// byte[] mp3Data = alibabaTTSUtil.synthesizeTextToMp3(text);
|
||||
byte[] mp3Data = httpClient.synthesizeTextToMp3(text,fileSuffix);
|
||||
// byte[] mp3Data = alibabaTTSUtil.synthesizeTextToMp3(text,fileSuffix);
|
||||
|
||||
SysOssVo upload = ossService.upload(mp3Data, generateRandomFileName(fileSuffix));
|
||||
|
||||
AppBusinessFileBo appBusinessFileBo = new AppBusinessFileBo();
|
||||
|
||||
savedPath = saveByteArrayToFile(mp3Data, generateRandomFileName(fileSuffix));
|
||||
|
||||
Integer mp3Duration = getMp3Duration2(savedPath);
|
||||
appBusinessFileBo.setDuration(mp3Duration);
|
||||
|
||||
String directory = System.getProperty("java.io.tmpdir"); // 使用系统临时目录
|
||||
String fileName = generateRandomFileName(fileSuffix);
|
||||
savedMp3VolumePath = directory + "/" + fileName;
|
||||
log.info("保存MP3文件: {}", savedMp3VolumePath);
|
||||
FfmpegVolumeUtil.increaseMp3Volume(savedPath, savedMp3VolumePath, 12);
|
||||
|
||||
File file = new File(savedMp3VolumePath);
|
||||
String fileHash = fileHashUtil.getFileHash(file,"SHA-256");
|
||||
SysOssVo upload = ossService.updateHash(file, fileHash);
|
||||
|
||||
// 强制将HTTP替换为HTTPS
|
||||
if (upload.getUrl() != null && upload.getUrl().startsWith("http://")) {
|
||||
upload.setUrl(upload.getUrl().replaceFirst("^http://", "https://"));
|
||||
}
|
||||
|
||||
|
||||
AppBusinessFileBo appBusinessFileBo = new AppBusinessFileBo();
|
||||
appBusinessFileBo.setFileId(upload.getOssId());
|
||||
appBusinessFileBo.setBusinessId(deviceId);
|
||||
appBusinessFileBo.setFileType(3L);
|
||||
appBusinessFileBo.setCreateBy(AppLoginHelper.getUserId());
|
||||
savedPath = saveByteArrayToFile(mp3Data, generateRandomFileName(fileSuffix));
|
||||
if (savedPath != null) {
|
||||
log.info("MP3文件已保存: {}", savedPath);
|
||||
Integer mp3Duration = Mp3Duration.getMp3Duration(savedPath);
|
||||
log.info("MP3文件时长: {} 秒", mp3Duration);
|
||||
appBusinessFileBo.setDuration(mp3Duration);
|
||||
}
|
||||
appBusinessFileService.insertByBo(appBusinessFileBo);
|
||||
if (upload != null) {
|
||||
return upload.getUrl();
|
||||
@ -484,14 +506,28 @@ public class AudioProcessService {
|
||||
} catch (Exception e){
|
||||
log.error("上传音频文件失败", e);
|
||||
} finally {
|
||||
log.info("删除临时文件: {}", savedPath);
|
||||
log.info("删除savedPath临时文件: {}", savedPath);
|
||||
if(savedPath != null){
|
||||
deleteTempFile(new File(savedPath));
|
||||
}
|
||||
if(savedMp3VolumePath != null){
|
||||
log.info("删除savedMp3VolumePath临时文件: {}", savedMp3VolumePath);
|
||||
deleteTempFile(new File(savedMp3VolumePath));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer getMp3Duration2(String savedPath) {
|
||||
if (savedPath != null) {
|
||||
log.info("MP3文件已保存: {}", savedPath);
|
||||
Integer mp3Duration = Mp3Duration.getMp3Duration(savedPath);
|
||||
log.info("MP3文件时长: {} 秒", mp3Duration);
|
||||
return mp3Duration;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final DateTimeFormatter formatter =
|
||||
DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
@ -514,11 +550,12 @@ public class AudioProcessService {
|
||||
if(deviceId == null){
|
||||
return null;
|
||||
}
|
||||
Long userId = LoginHelper.getUserId();
|
||||
AppBusinessFileBo bo = new AppBusinessFileBo();
|
||||
bo.setBusinessId(deviceId);
|
||||
bo.setCreateBy(userId);
|
||||
bo.setFileType(3L);
|
||||
List<AppFileVo> appFileVos = appBusinessFileService.queryAppFileList(bo);
|
||||
return appFileVos;
|
||||
return appBusinessFileService.queryAppFileList(bo);
|
||||
}
|
||||
|
||||
public R<Void> deleteAudioFile(Long fileId,Long deviceId) {
|
||||
|
||||
@ -6,10 +6,7 @@ import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
|
||||
import com.fuyuanshen.global.mqtt.base.MqttRuleEngine;
|
||||
import com.fuyuanshen.global.mqtt.base.MqttXinghanCommandType;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import com.fuyuanshen.global.mqtt.base.*;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.queue.MqttMessageQueueConstants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -35,6 +32,9 @@ public class ReceiverMessageHandler implements MessageHandler {
|
||||
@Autowired
|
||||
private MqttRuleEngine ruleEngine;
|
||||
|
||||
@Autowired
|
||||
private NewMqttRuleEngine newRuleEngine;
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
Object payload = message.getPayload();
|
||||
@ -50,9 +50,18 @@ public class ReceiverMessageHandler implements MessageHandler {
|
||||
if (receivedTopic == null || payloadDict == null) {
|
||||
return;
|
||||
}
|
||||
String[] subStr = receivedTopic.split("/");
|
||||
String deviceImei = subStr[1];
|
||||
|
||||
// 模版格式匹配
|
||||
boolean flag = checkTemplateFormatMatching(payloadDict);
|
||||
|
||||
|
||||
String[] subStr = receivedTopic.split("/");
|
||||
String deviceImei = null;
|
||||
if(flag){
|
||||
deviceImei = payloadDict.getStr("imei");
|
||||
} else {
|
||||
deviceImei = subStr[1];
|
||||
}
|
||||
|
||||
RedissonClient client = RedisUtils.getClient();
|
||||
String lockKey = "mqtt:consumer:lock:";
|
||||
@ -74,7 +83,22 @@ public class ReceiverMessageHandler implements MessageHandler {
|
||||
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(360));
|
||||
}
|
||||
|
||||
// 新的通信协议
|
||||
if(flag){
|
||||
String[] topicArr = receivedTopic.split("/");
|
||||
String funcType = payloadDict.getStr("funcType");
|
||||
NewMqttRuleContext context = new NewMqttRuleContext();
|
||||
context.setCommandType(topicArr[2]+"_"+funcType);
|
||||
context.setDeviceImei(deviceImei);
|
||||
context.setPayloadDict(payloadDict);
|
||||
|
||||
boolean ruleExecuted = newRuleEngine.executeRule(context);
|
||||
|
||||
if (!ruleExecuted) {
|
||||
log.warn("未找到匹配的规则来处理命令类型: {}", topicArr[2] + " : " +funcType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (convertArr.length > 0) {
|
||||
Byte val1 = (Byte) convertArr[0];
|
||||
@ -89,6 +113,7 @@ public class ReceiverMessageHandler implements MessageHandler {
|
||||
if (!ruleExecuted) {
|
||||
log.warn("未找到匹配的规则来处理命令类型: {}", val1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ===== 追加:根据报文内容识别格式并统一解析 ===== */
|
||||
@ -117,4 +142,18 @@ public class ReceiverMessageHandler implements MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkTemplateFormatMatching(Dict payloadDict) {
|
||||
// 检查是否包含指定的 key
|
||||
boolean hasImei = payloadDict.containsKey("imei");
|
||||
boolean hasFuncType = payloadDict.containsKey("funcType");
|
||||
boolean hasStatus = payloadDict.containsKey("status");
|
||||
boolean hasTimestamp = payloadDict.containsKey("timestamp");
|
||||
boolean hasData = payloadDict.containsKey("data");
|
||||
|
||||
// 输出检查结果
|
||||
log.info("包含 imei: {}, funcType: {}, status: {}, timestamp: {}, data: {}",
|
||||
hasImei, hasFuncType, hasStatus, hasTimestamp, hasData);
|
||||
return hasImei && hasFuncType && hasStatus && hasTimestamp && hasData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -29,13 +29,13 @@ public class FuncType10StrobeMode implements NewMqttMessageRule {
|
||||
log.info("HBY100J爆闪模式开启/关闭,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":strobeMode";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":strobeMode";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J爆闪模式开启/关闭失败", e);
|
||||
}
|
||||
|
||||
@ -29,13 +29,13 @@ public class FuncType11Frequency implements NewMqttMessageRule {
|
||||
log.info("HBY100J修改警示灯爆闪频率,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":frequency";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":frequency";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J修改警示灯爆闪频率失败", e);
|
||||
}
|
||||
|
||||
@ -30,14 +30,14 @@ public class FuncType12ForceAudio implements NewMqttMessageRule {
|
||||
|
||||
try {
|
||||
// 构建强制声光报警开关的Redis键
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":forceAudio";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// // 存储强制声光报警开关状态到Redis
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":forceAudio";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
// 存储强制声光报警开关状态到Redis
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J强制声光报警开启/关闭失败", e);
|
||||
}
|
||||
|
||||
@ -29,13 +29,13 @@ public class FuncType13Brightness implements NewMqttMessageRule {
|
||||
log.info("HBY100J警示灯LED亮度调节,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":brightness";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":brightness";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J警示灯LED亮度调节失败", e);
|
||||
}
|
||||
|
||||
@ -2,15 +2,23 @@ package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.equipment.utils.map.GetAddressFromLatUtil;
|
||||
import com.fuyuanshen.equipment.utils.map.LngLonUtil;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.mqtt.rule.hby100j.domin.FunctionType3LocationReport;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 获取设备位置信息(设备下发返回响应数据、设备定时主动上报)
|
||||
@ -34,10 +42,167 @@ public class FuncType3Location implements NewMqttMessageRule {
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
String jsonString = JSONObject.toJSONString(payloadDict);
|
||||
FunctionType3LocationReport data = JSONObject.parseObject(jsonString, FunctionType3LocationReport.class);
|
||||
FunctionType3LocationReport.Data data1 = data.getData();
|
||||
if (data1 != null) {
|
||||
Double latitude = data1.getLatitude();
|
||||
Double longitude = data1.getLongitude();
|
||||
asyncSendLocationToRedisWithFuture(context.getDeviceImei(), latitude.toString(), longitude.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J获取设备位置信息失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** 位置未发生明显变化的距离阈值(米),可通过配置中心动态调整 */
|
||||
private final double MOVEMENT_THRESHOLD_METER = 10.0;
|
||||
|
||||
/**
|
||||
* 异步发送位置信息到Redis(使用CompletableFuture)
|
||||
*
|
||||
* @param deviceImei 设备IMEI
|
||||
* @param latitude 纬度
|
||||
* @param longitude 经度
|
||||
*/
|
||||
public void asyncSendLocationToRedisWithFuture(String deviceImei, String latitude, String longitude) {
|
||||
try {
|
||||
if (latitude == null || longitude == null) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isAnyBlank(deviceImei, latitude, longitude)) {
|
||||
log.warn("位置上报参数为空,deviceImei={}", deviceImei);
|
||||
return;
|
||||
}
|
||||
//log.info("位置上报,deviceImei={}, lat={}, lon={}", deviceImei, latitude, longitude);
|
||||
// 1. 解析当前上报的经纬度
|
||||
Double curLat = parseDoubleSafe(latitude.trim());
|
||||
Double curLon = parseDoubleSafe(longitude.trim());
|
||||
if (curLat == null || curLon == null) {
|
||||
log.warn("经纬度格式错误,直接更新,deviceImei={}, lat={}, lon={}", deviceImei, latitude, longitude);
|
||||
// doSaveLocation(deviceImei, latitude, longitude);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 读取 Redis 中缓存的上一次位置
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DEVICE_LOCATION_KEY_PREFIX;
|
||||
String cachedJson = RedisUtils.getCacheObject(redisKey);
|
||||
|
||||
if (StringUtils.isNotBlank(cachedJson)) {
|
||||
com.alibaba.fastjson2.JSONObject cachedObj = com.alibaba.fastjson2.JSONObject.parseObject(cachedJson);
|
||||
String cachedWgs84Lat = cachedObj.getString("wgs84_latitude");
|
||||
String cachedWgs84Lon = cachedObj.getString("wgs84_longitude");
|
||||
|
||||
Double oldLat = parseDoubleSafe(cachedWgs84Lat);
|
||||
Double oldLon = parseDoubleSafe(cachedWgs84Lon);
|
||||
|
||||
if (oldLat != null && oldLon != null) {
|
||||
double distance = haversine(oldLat, oldLon, curLat, curLon);
|
||||
if (distance <= MOVEMENT_THRESHOLD_METER) {
|
||||
log.info("位置未发生明显变化({}米 <= {}米),不更新 Redis,deviceImei={}, lat={}, lon={}",
|
||||
distance, MOVEMENT_THRESHOLD_METER, deviceImei, latitude, longitude);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// String[] latArr = latitude.split("\\.");
|
||||
// String[] lonArr = longitude.split("\\.");
|
||||
// // 将位置信息存储到Redis中
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DEVICE_LOCATION_KEY_PREFIX;
|
||||
// String redisObj = RedisUtils.getCacheObject(redisKey);
|
||||
// JSONObject jsonOBj = JSONObject.parseObject(redisObj);
|
||||
// if(jsonOBj != null){
|
||||
// String str1 = latArr[0] +"."+ latArr[1].substring(0,4);
|
||||
// String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4);
|
||||
//
|
||||
// String cacheLatitude = jsonOBj.getString("wgs84_latitude");
|
||||
// String cacheLongitude = jsonOBj.getString("wgs84_longitude");
|
||||
// String[] latArr1 = cacheLatitude.split("\\.");
|
||||
// String[] lonArr1 = cacheLongitude.split("\\.");
|
||||
//
|
||||
// String cacheStr1 = latArr1[0] +"."+ latArr1[1].substring(0,4);
|
||||
// String cacheStr2 = lonArr1[0] +"."+ lonArr1[1].substring(0,4);
|
||||
// if(str1.equals(cacheStr1) && str2.equals(cacheStr2)){
|
||||
// log.info("位置信息未发生变化: device={}, lat={}, lon={}", deviceImei, latitude, longitude);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 构造位置信息对象
|
||||
Map<String, Object> locationInfo = new LinkedHashMap<>();
|
||||
double[] doubles = LngLonUtil.gps84_To_Gcj02(Double.parseDouble(latitude), Double.parseDouble(longitude));
|
||||
locationInfo.put("deviceImei", deviceImei);
|
||||
locationInfo.put("latitude", doubles[0]);
|
||||
locationInfo.put("longitude", doubles[1]);
|
||||
locationInfo.put("wgs84_latitude", latitude);
|
||||
locationInfo.put("wgs84_longitude", longitude);
|
||||
|
||||
|
||||
String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0]));
|
||||
locationInfo.put("address", address);
|
||||
locationInfo.put("timestamp", System.currentTimeMillis());
|
||||
|
||||
|
||||
String locationJson = JsonUtils.toJsonString(locationInfo);
|
||||
|
||||
// 存储到Redis
|
||||
RedisUtils.setCacheObject(redisKey, locationJson);
|
||||
|
||||
// 存储到一个列表中,保留历史位置信息
|
||||
// String locationHistoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei;
|
||||
// RedisUtils.addCacheList(locationHistoryKey, locationJson);
|
||||
// RedisUtils.expire(locationHistoryKey, Duration.ofDays(90));
|
||||
storeDeviceTrajectoryWithSortedSet(deviceImei, locationJson);
|
||||
log.info("位置信息已异步发送到Redis: device={}, lat={}, lon={}", deviceImei, latitude, longitude);
|
||||
} catch (Exception e) {
|
||||
log.error("异步发送位置信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
/** 安全解析 double,解析失败返回 null */
|
||||
private Double parseDoubleSafe(String str) {
|
||||
if (StringUtils.isBlank(str)) return null;
|
||||
try {
|
||||
return Double.parseDouble(str.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/** Haversine 公式计算两点球面距离(米) */
|
||||
private double haversine(double lat1, double lon1, double lat2, double lon2) {
|
||||
double dLat = Math.toRadians(lat2 - lat1);
|
||||
double dLon = Math.toRadians(lon2 - lon1);
|
||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
|
||||
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
/** 地球平均半径(米) */
|
||||
double EARTH_RADIUS = 6371_393.0;
|
||||
return EARTH_RADIUS * c;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储设备30天历史轨迹到Redis (使用Sorted Set)
|
||||
*/
|
||||
public void storeDeviceTrajectoryWithSortedSet(String deviceImei, String locationJson) {
|
||||
try {
|
||||
String trajectoryKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX;
|
||||
// String trajectoryKey = "device:trajectory:zset:" + deviceImei;
|
||||
// String locationJson = JsonUtils.toJsonString(locationInfo);
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
// 添加到Sorted Set,使用时间戳作为score
|
||||
RedisUtils.zAdd(trajectoryKey, locationJson, timestamp);
|
||||
|
||||
// // 设置30天过期时间
|
||||
// RedisUtils.expire(trajectoryKey, Duration.ofDays(30));
|
||||
|
||||
// 清理30天前的数据(冗余保护)
|
||||
long thirtyDaysAgo = System.currentTimeMillis() - (7L * 24 * 60 * 60 * 1000);
|
||||
RedisUtils.zRemoveRangeByScore(trajectoryKey, 0, thirtyDaysAgo);
|
||||
} catch (Exception e) {
|
||||
log.error("存储设备轨迹到Redis(ZSet)失败: device={}, error={}", deviceImei, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,21 @@ package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.mqtt.rule.hby100j.domin.FunctionType4PowerStatusReport;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 获取设备电源状态(设备下发返回响应数据、设备定时主动上报)
|
||||
@ -29,12 +35,32 @@ public class FuncType4PowerStatus implements NewMqttMessageRule {
|
||||
log.info("HBY100J获取设备电源状态,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":powerStatus";
|
||||
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX);
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":powerStatus";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
|
||||
String str = JSONObject.toJSONString(payloadDict);
|
||||
FunctionType4PowerStatusReport powerStatusReport =JSONObject.parseObject(str,FunctionType4PowerStatusReport.class);
|
||||
|
||||
FunctionType4PowerStatusReport.Data data = powerStatusReport.getData();
|
||||
if(data != null){
|
||||
// 构造设备状态信息对象
|
||||
Map<String, Object> deviceInfo = new LinkedHashMap<>();
|
||||
deviceInfo.put("batteryPercentage", data.getLevel());
|
||||
deviceInfo.put("chargeState", data.getCharge());
|
||||
deviceInfo.put("batteryRemainingTime", data.getBatteryRemainingTime());
|
||||
|
||||
// 将设备状态信息存储到Redis中
|
||||
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX;
|
||||
String deviceInfoJson = JsonUtils.toJsonString(deviceInfo);
|
||||
|
||||
// 存储到Redis
|
||||
RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J获取设备电源状态失败", e);
|
||||
|
||||
@ -21,7 +21,7 @@ public class FuncType6VoicePlay implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_9";
|
||||
return "HBY100_6";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -29,13 +29,13 @@ public class FuncType9UpdateVolume implements NewMqttMessageRule {
|
||||
log.info("HBY100J修改音量,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":updateVolume";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":updateVolume";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J修改音量失败", e);
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ public class FuncType12ForceAudioRequest {
|
||||
/**
|
||||
* 语音报警0关闭,1开启
|
||||
*/
|
||||
@JsonProperty("voice_strobe_alarm")
|
||||
private Integer voiceStrobeAlarm;
|
||||
//语音模式0公安,1消防,2应急,3交警,4市政,5铁路,6医疗,7部队,8水利
|
||||
private Integer mode;
|
||||
|
||||
@ -49,12 +49,14 @@ public class FuncType5UpdateVoiceRequest {
|
||||
* 2 - 紧急语音
|
||||
* (具体含义需依据设备协议定义)
|
||||
*/
|
||||
@JsonProperty("voice_type")
|
||||
private Integer voiceType;
|
||||
|
||||
/**
|
||||
* 语音资源URL(MP3等音频文件地址)
|
||||
* 示例:http://8.129.5.250:10001/voice/01.mp3
|
||||
*/
|
||||
@JsonProperty("voice_resource")
|
||||
private String voiceResource;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ public class FuncType6VoicePlayRequest {
|
||||
/**
|
||||
* 语音报警0关闭,1开启
|
||||
*/
|
||||
@JsonProperty("voice_broadcast")
|
||||
private Integer voiceBroadcast;
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,5 +70,8 @@ public class FunctionType4PowerStatusReport {
|
||||
*/
|
||||
@JsonProperty("12v_power")
|
||||
private Integer twelveVPower;
|
||||
|
||||
@JsonProperty("battery_remaining_time")
|
||||
private Integer batteryRemainingTime;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
package com.fuyuanshen.global.mqtt.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class FfmpegVolumeUtil {
|
||||
|
||||
/**
|
||||
* 使用FFmpeg增加MP3文件的音量
|
||||
*
|
||||
* @param inputFilePath 输入MP3文件路径
|
||||
* @param outputFilePath 输出MP3文件路径
|
||||
* @param volumeGain 音量增益(例如:1.5表示增加50%音量,2.0表示翻倍)
|
||||
*/
|
||||
public static void increaseMp3Volume(String inputFilePath, String outputFilePath, int volumeGain) {
|
||||
boolean ffmpegAvailable = isFfmpegAvailable();
|
||||
if (!ffmpegAvailable) {
|
||||
System.err.println("FFmpeg未安装或未找到!请安装FFmpeg并确保在系统路径中。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查输入文件
|
||||
File inputFile = new File(inputFilePath);
|
||||
if (!inputFile.exists()) {
|
||||
System.err.println("输入文件不存在:" + inputFilePath);
|
||||
return;
|
||||
}
|
||||
if (!inputFile.canRead()) {
|
||||
System.err.println("输入文件不可读:" + inputFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建输出目录
|
||||
File outputFile = new File(outputFilePath);
|
||||
File parentDir = outputFile.getParentFile();
|
||||
if (parentDir != null) {
|
||||
parentDir.mkdirs();
|
||||
if (!parentDir.canWrite()) {
|
||||
System.err.println("输出目录不可写:" + parentDir.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Process process = null;
|
||||
try {
|
||||
String command = String.format(
|
||||
"ffmpeg -y -i \"%s\" -af \"volume=%sdB\" \"%s\"",
|
||||
inputFilePath,
|
||||
volumeGain,
|
||||
outputFilePath
|
||||
);
|
||||
|
||||
System.out.println("执行命令: " + command);
|
||||
|
||||
// 使用 ProcessBuilder 提供更好的控制
|
||||
ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-y",
|
||||
"-i", inputFilePath, "-af", "volume=" + volumeGain + "dB", outputFilePath);
|
||||
processBuilder.redirectErrorStream(false);
|
||||
process = processBuilder.start();
|
||||
|
||||
// 同时读取标准输出和错误输出
|
||||
Process finalProcess = process;
|
||||
Thread stdOutThread = new Thread(() -> {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(finalProcess.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println("[FFmpeg STDOUT] " + line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取标准输出时出错: " + e.getMessage());
|
||||
}finally {
|
||||
finalProcess.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
Process finalProcess1 = process;
|
||||
Thread stdErrThread = new Thread(() -> {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(finalProcess1.getErrorStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.err.println("[FFmpeg STDERR] " + line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取错误输出时出错: " + e.getMessage());
|
||||
}finally {
|
||||
finalProcess1.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
stdOutThread.start();
|
||||
stdErrThread.start();
|
||||
|
||||
int exitCode = process.waitFor();
|
||||
stdOutThread.join();
|
||||
stdErrThread.join();
|
||||
|
||||
if (exitCode == 0) {
|
||||
System.out.println("音量调整成功!输出文件:" + outputFilePath);
|
||||
} else {
|
||||
System.err.println("FFmpeg命令执行失败,退出码:" + exitCode);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println("执行FFmpeg命令时发生错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (process != null) {
|
||||
System.out.println("已销毁进程");
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// 示例用法
|
||||
String inputPath = "/app/input.mp3";
|
||||
String outputPath = "/app/output17.mp3";
|
||||
int volumeGain = 12;
|
||||
|
||||
increaseMp3Volume(inputPath, outputPath, volumeGain);
|
||||
}
|
||||
|
||||
private static boolean isFfmpegAvailable() {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("ffmpeg -version");
|
||||
int exitCode = process.waitFor();
|
||||
return exitCode == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
package com.fuyuanshen.global.mqtt.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class FfmpegVolumeUtil3 {
|
||||
|
||||
/**
|
||||
* 使用FFmpeg增加MP3文件的音量
|
||||
*
|
||||
* @param inputFilePath 输入MP3文件路径
|
||||
* @param outputFilePath 输出MP3文件路径
|
||||
* @param volumeGain 音量增益(例如:1.5表示增加50%音量,2.0表示翻倍)
|
||||
*/
|
||||
public static void increaseMp3Volume(String inputFilePath, String outputFilePath, int volumeGain) {
|
||||
boolean ffmpegAvailable = isFfmpegAvailable();
|
||||
if (!ffmpegAvailable) {
|
||||
System.err.println("FFmpeg未安装或未找到!请安装FFmpeg并确保在系统路径中。");
|
||||
return;
|
||||
}
|
||||
// 创建输出文件的父目录
|
||||
File outputFile = new File(outputFilePath);
|
||||
File parentDir = outputFile.getParentFile();
|
||||
if (parentDir != null && !parentDir.exists()) {
|
||||
boolean created = parentDir.mkdirs();
|
||||
if (!created) {
|
||||
System.err.println("无法创建输出目录:" + parentDir.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
Process process = null;
|
||||
try {
|
||||
// 构建FFmpeg命令
|
||||
String command = String.format(
|
||||
"ffmpeg -y -i \"%s\" -af \"volume=%sdB\" \"%s\"",
|
||||
inputFilePath,
|
||||
volumeGain,
|
||||
outputFilePath
|
||||
);
|
||||
|
||||
System.out.println("执行命令: " + command);
|
||||
|
||||
// 执行FFmpeg命令
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// 读取命令执行结果
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
|
||||
// 等待命令执行完成
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode == 0) {
|
||||
System.out.println("音量调整成功!输出文件:" + outputFilePath);
|
||||
} else {
|
||||
System.err.println("FFmpeg命令执行失败,退出码:" + exitCode);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// 示例用法
|
||||
String inputPath = "/app/input.mp3";
|
||||
String outputPath = "/app/output18.mp3";
|
||||
int volumeGain = 12;
|
||||
|
||||
increaseMp3Volume(inputPath, outputPath, volumeGain);
|
||||
}
|
||||
|
||||
private static boolean isFfmpegAvailable() {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("ffmpeg -version");
|
||||
int exitCode = process.waitFor();
|
||||
return exitCode == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
package com.fuyuanshen.web.controller.device;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileDto;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.log.annotation.Log;
|
||||
import com.fuyuanshen.common.log.enums.BusinessType;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.WebDeviceVo;
|
||||
import com.fuyuanshen.web.domain.Dto.DeviceDebugEditDto;
|
||||
import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto;
|
||||
@ -28,8 +24,6 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 联调中心
|
||||
@ -125,7 +119,7 @@ public class DeviceDebugController extends BaseController {
|
||||
}
|
||||
deviceDebugService.delFile(bo.getFileIds());
|
||||
// 修改操作视频
|
||||
if (bo.getVideoUrl().isEmpty()) {
|
||||
if (!bo.getVideoUrl().isEmpty()) {
|
||||
AppOperationVideoBo appOperationVideoBo = new AppOperationVideoBo();
|
||||
appOperationVideoBo.setDeviceIds(new Long[]{ bo.getDeviceId() });
|
||||
appOperationVideoBo.setVideoUrl(bo.getVideoUrl());
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
package com.fuyuanshen.web.domain.vo;
|
||||
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.equipment.domain.Device;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppDeviceVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -97,6 +97,7 @@ public class DeviceBizService {
|
||||
} else {
|
||||
item.setOnlineStatus(0);
|
||||
}
|
||||
|
||||
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX);
|
||||
// 获取电量
|
||||
if (StringUtils.isNotBlank(deviceStatus)) {
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package com.fuyuanshen.web.service.device;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileDto;
|
||||
import com.fuyuanshen.app.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.app.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.equipment.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.equipment.service.DeviceService;
|
||||
|
||||
@ -130,44 +130,115 @@ public class DeviceHBY100JBizService {
|
||||
} else {
|
||||
vo.setOnlineStatus(0);
|
||||
}
|
||||
|
||||
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX);
|
||||
// 获取电量
|
||||
if (StringUtils.isNotBlank(deviceStatus)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(deviceStatus);
|
||||
vo.setBatteryPercentage(jsonObject.getString("batteryPercentage"));
|
||||
vo.setChargeState(jsonObject.getString("chargeState"));
|
||||
vo.setBatteryPercentage(jsonObject.getInteger("batteryPercentage"));
|
||||
vo.setChargeState(jsonObject.getInteger("chargeState"));
|
||||
vo.setBatteryRemainingTime(jsonObject.getInteger("batteryRemainingTime"));
|
||||
} else {
|
||||
vo.setBatteryPercentage("0");
|
||||
vo.setBatteryPercentage(0);
|
||||
vo.setBatteryRemainingTime(0);
|
||||
}
|
||||
|
||||
String lightModeStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LIGHT_MODE_KEY_PREFIX);
|
||||
|
||||
|
||||
String lightBrightnessStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX);
|
||||
if (StringUtils.isNotBlank(lightBrightnessStatus)) {
|
||||
vo.setLightBrightness(lightBrightnessStatus);
|
||||
String reportStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + ":report");
|
||||
if (StringUtils.isNotBlank(reportStatus)) {
|
||||
FuncType14StatusReport report = JSONObject.parseObject(reportStatus,FuncType14StatusReport.class);
|
||||
FuncType14StatusReport.Data data = report.getData();
|
||||
FuncType14StatusReport.Brightness brightness = data.getBrightness();
|
||||
if(brightness != null){
|
||||
vo.setLightBrightness(brightness.getRed());
|
||||
}
|
||||
|
||||
vo.setVolume(data.getVolume());
|
||||
FuncType14StatusReport.LedStrobe ledStrobe = data.getLedStrobe();
|
||||
if(ledStrobe != null){
|
||||
vo.setStrobeFrequency(ledStrobe.getFrequency());
|
||||
vo.setStrobeMode(ledStrobe.getMode());
|
||||
vo.setStrobeEnable(ledStrobe.getEnable());
|
||||
}
|
||||
|
||||
|
||||
Integer voiceBroadcast = data.getVoiceBroadcast();
|
||||
if(voiceBroadcast != null){
|
||||
vo.setVoiceBroadcast(voiceBroadcast);
|
||||
}
|
||||
FuncType14StatusReport.SirenAlarm sirenAlarm = data.getSirenAlarm();
|
||||
if(sirenAlarm != null){
|
||||
vo.setVoiceStrobeAlarm(sirenAlarm.getEnable());
|
||||
vo.setAlarmMode(sirenAlarm.getMode());
|
||||
}
|
||||
}
|
||||
String strobeModeRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
device.getDeviceImei() + ":strobeMode";
|
||||
String strobeModeStatus = RedisUtils.getCacheObject(strobeModeRedisKey);
|
||||
if(StringUtils.isNotBlank(strobeModeStatus)){
|
||||
FuncType10StrobeModeRequest strobeModeRequest = JSONObject.parseObject(strobeModeStatus, FuncType10StrobeModeRequest.class);
|
||||
FuncType10StrobeModeRequest.Data data = strobeModeRequest.getData();
|
||||
if(data != null){
|
||||
vo.setStrobeMode(strobeModeRequest.getData().getMode());
|
||||
vo.setStrobeEnable(strobeModeRequest.getData().getEnable());
|
||||
}
|
||||
}
|
||||
|
||||
String updateVolumeRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
device.getDeviceImei() + ":updateVolume";
|
||||
String updateVolumeStatus = RedisUtils.getCacheObject(updateVolumeRedisKey);
|
||||
if(StringUtils.isNotBlank(updateVolumeStatus)){
|
||||
FuncType9UpdateVolumeRequest updateVolumeRequest = JSONObject.parseObject(updateVolumeStatus, FuncType9UpdateVolumeRequest.class);
|
||||
if(updateVolumeRequest.getData() != null){
|
||||
vo.setVolume(updateVolumeRequest.getData().getVolume());
|
||||
}
|
||||
}
|
||||
|
||||
String frequencyRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
device.getDeviceImei() + ":frequency";
|
||||
String frequencyStatus = RedisUtils.getCacheObject(frequencyRedisKey);
|
||||
if(StringUtils.isNotBlank(frequencyStatus)){
|
||||
FuncType11FrequencyRequest frequencyRequest = JSONObject.parseObject(frequencyStatus, FuncType11FrequencyRequest.class);
|
||||
if(frequencyRequest.getData() != null){
|
||||
vo.setStrobeFrequency(frequencyRequest.getData().getFrequency());
|
||||
}
|
||||
}
|
||||
|
||||
String forceAudioRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
device.getDeviceImei() + ":forceAudio";
|
||||
String forceAudioStatus = RedisUtils.getCacheObject(forceAudioRedisKey);
|
||||
if(StringUtils.isNotBlank(forceAudioStatus)){
|
||||
FuncType12ForceAudioRequest forceAudioRequest = JSONObject.parseObject(forceAudioStatus, FuncType12ForceAudioRequest.class);
|
||||
if(forceAudioRequest.getData() != null){
|
||||
vo.setVoiceStrobeAlarm(forceAudioRequest.getData().getVoiceStrobeAlarm());
|
||||
vo.setAlarmMode(forceAudioRequest.getData().getMode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取经度纬度
|
||||
String locationKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;
|
||||
String locationInfo = RedisUtils.getCacheObject(locationKey);
|
||||
// if (StringUtils.isNotBlank(locationInfo)) {
|
||||
// JSONObject jsonObject = JSONObject.parseObject(locationInfo);
|
||||
// vo.setLongitude(jsonObject.get("longitude").toString());
|
||||
// vo.setLatitude(jsonObject.get("latitude").toString());
|
||||
// vo.setAddress((String) jsonObject.get("address"));
|
||||
// }
|
||||
|
||||
String alarmStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX);
|
||||
if (StringUtils.isNotBlank(alarmStatus)) {
|
||||
vo.setVoiceStrobeAlarm(alarmStatus);
|
||||
String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LOCATION_KEY_PREFIX);
|
||||
if (StringUtils.isNotBlank(location)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(location);
|
||||
vo.setLatitude(jsonObject.getString("latitude"));
|
||||
vo.setLongitude(jsonObject.getString("longitude"));
|
||||
vo.setAddress(jsonObject.getString("address"));
|
||||
}
|
||||
|
||||
String lightBrightness = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX);
|
||||
if (StringUtils.isNotBlank(lightBrightness)) {
|
||||
vo.setLightBrightness(lightBrightness);
|
||||
QueryWrapper<AppBusinessFile> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("business_id", device.getId());
|
||||
queryWrapper.eq("file_type", 3);
|
||||
queryWrapper.eq("use_status", 1);
|
||||
List<AppBusinessFile> appBusinessFiles = appBusinessFileMapper.selectList(queryWrapper);
|
||||
if(appBusinessFiles != null && appBusinessFiles.size() > 0){
|
||||
AppBusinessFile appBusinessFile = appBusinessFiles.get(0);
|
||||
SysOssVo sysOssVo = sysOssMapper.selectVoById(appBusinessFile.getFileId());
|
||||
if(sysOssVo != null){
|
||||
vo.setVoiceResource(sysOssVo.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ -186,36 +257,22 @@ public class DeviceHBY100JBizService {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
bo.getDeviceIds().forEach(deviceId -> {
|
||||
Device deviceObj = deviceMapper.selectById(deviceId);
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
|
||||
// 语音播报
|
||||
if(bo.getMode() == 9){
|
||||
FuncType6VoicePlayRequest request = new FuncType6VoicePlayRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("6");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType6VoicePlayRequest.Data data = new FuncType6VoicePlayRequest.Data();
|
||||
data.setVoiceBroadcast(bo.getVoiceStrobeAlarm());
|
||||
request.setData(data);
|
||||
log.info("HBY100J更新语音,参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}else{
|
||||
FuncType12ForceAudioRequest request = new FuncType12ForceAudioRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("12");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType12ForceAudioRequest.Data data = new FuncType12ForceAudioRequest.Data();
|
||||
data.setVoiceStrobeAlarm(bo.getVoiceStrobeAlarm());
|
||||
data.setMode(bo.getMode());
|
||||
request.setData(data);
|
||||
log.info("HBY100J更新语音,参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
|
||||
FuncType12ForceAudioRequest request = new FuncType12ForceAudioRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("12");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType12ForceAudioRequest.Data data = new FuncType12ForceAudioRequest.Data();
|
||||
data.setVoiceStrobeAlarm(bo.getVoiceStrobeAlarm());
|
||||
data.setMode(bo.getMode());
|
||||
request.setData(data);
|
||||
log.info("HBY100J强制报警,下发设备参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
|
||||
|
||||
// recordDeviceLog(deviceId, deviceObj.getDeviceName(), "强制报警激活", "强制报警激活", loginUser.getUserId());
|
||||
});
|
||||
@ -228,9 +285,9 @@ public class DeviceHBY100JBizService {
|
||||
throw new ServiceException("文件不存在");
|
||||
}
|
||||
Device deviceObj = deviceMapper.selectById(appBusinessFileVo.getBusinessId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
SysOssVo sysOssVo = sysOssMapper.selectVoById(appBusinessFileVo.getFileId());
|
||||
@ -264,11 +321,10 @@ public class DeviceHBY100JBizService {
|
||||
}
|
||||
|
||||
public void strobeMode(AppDeviceHBY100JController.HBY100JStrobeModeDto params) {
|
||||
log.info("HBY100J爆闪模式开启/关闭,请求参数:{}", params);
|
||||
Device deviceObj = deviceMapper.selectById(params.getDeviceId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
FuncType10StrobeModeRequest request = new FuncType10StrobeModeRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
@ -285,9 +341,12 @@ public class DeviceHBY100JBizService {
|
||||
public void lightAdjustment(AppDeviceHBY100JController.HBY100JLightAdjustmentDto params) {
|
||||
log.info("HBY100J灯光调节,请求参数:{}", params);
|
||||
Device deviceObj = deviceMapper.selectById(params.getDeviceId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
if (deviceObj == null) {
|
||||
throw new ServiceException("设备不存在");
|
||||
}
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
FuncType13BrightnessRequest request = new FuncType13BrightnessRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
@ -303,11 +362,13 @@ public class DeviceHBY100JBizService {
|
||||
}
|
||||
|
||||
public void strobeFrequency(AppDeviceHBY100JController.HBY100JStrobeFrequencyDto params) {
|
||||
log.info("HBY100J爆闪频率,请求参数:{}", params);
|
||||
Device deviceObj = deviceMapper.selectById(params.getDeviceId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
if (deviceObj == null) {
|
||||
throw new ServiceException("设备不存在");
|
||||
}
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
FuncType11FrequencyRequest request = new FuncType11FrequencyRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
@ -316,16 +377,18 @@ public class DeviceHBY100JBizService {
|
||||
FuncType11FrequencyRequest.Data data = new FuncType11FrequencyRequest.Data();
|
||||
data.setFrequency(params.getFrequency());
|
||||
request.setData(data);
|
||||
log.info("HBY100J灯光调节,下发设备参数:{}", request);
|
||||
log.info("HBY100J爆闪频率,下发设备参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
|
||||
public void updateVolume(AppDeviceHBY100JController.HBY100JUpdateVolumeDto params) {
|
||||
log.info("HBY100J更新音量,请求参数:{}", params);
|
||||
Device deviceObj = deviceMapper.selectById(params.getDeviceId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
if (deviceObj == null) {
|
||||
throw new ServiceException("设备不存在");
|
||||
}
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
FuncType9UpdateVolumeRequest request = new FuncType9UpdateVolumeRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
@ -337,4 +400,24 @@ public class DeviceHBY100JBizService {
|
||||
log.info("HBY100J更新音量,下发设备参数:{}", JSON.toJSONString(request));
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
|
||||
public void voiceBroadcast(AppDeviceHBY100JController.HBY100JVoiceBroadcastDto params) {
|
||||
Device deviceObj = deviceMapper.selectById(params.getDeviceId());
|
||||
if (deviceObj == null) {
|
||||
throw new ServiceException("设备不存在");
|
||||
}
|
||||
if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
}
|
||||
FuncType6VoicePlayRequest request = new FuncType6VoicePlayRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("6");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType6VoicePlayRequest.Data data = new FuncType6VoicePlayRequest.Data();
|
||||
data.setVoiceBroadcast(params.getVoiceBroadcast());
|
||||
request.setData(data);
|
||||
log.info("HBY100J语音播报,下发设备参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package com.fuyuanshen.web.service.device;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
@ -15,20 +15,17 @@ import com.fuyuanshen.app.domain.AppPersonnelInfo;
|
||||
import com.fuyuanshen.app.domain.AppPersonnelInfoRecords;
|
||||
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
|
||||
import com.fuyuanshen.app.domain.dto.DeviceInstructDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
|
||||
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.equipment.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
|
||||
import com.fuyuanshen.common.core.domain.model.LoginUser;
|
||||
import com.fuyuanshen.common.core.exception.BadRequestException;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
|
||||
import com.fuyuanshen.common.core.utils.MapstructUtils;
|
||||
import com.fuyuanshen.common.core.utils.ObjectUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
@ -40,7 +37,6 @@ import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
|
||||
import com.fuyuanshen.equipment.domain.form.DeviceForm;
|
||||
import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria;
|
||||
import com.fuyuanshen.equipment.enums.DeviceActiveStatusEnum;
|
||||
import com.fuyuanshen.equipment.enums.LightModeEnum;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper;
|
||||
@ -51,8 +47,6 @@ import com.fuyuanshen.global.mqtt.base.MqttXinghanJson;
|
||||
import com.fuyuanshen.global.mqtt.config.MqttGateway;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.domain.vo.SysRoleVo;
|
||||
import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto;
|
||||
import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto;
|
||||
import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo;
|
||||
@ -64,15 +58,12 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
|
||||
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
|
||||
@ -93,6 +84,8 @@ public class DeviceXinghanBizService {
|
||||
private final IDeviceAlarmService deviceAlarmService;
|
||||
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
|
||||
private final DeviceAssignmentsService deviceAssignmentsService;
|
||||
private final IAppBusinessFileService appBusinessFileService;
|
||||
private final IAppOperationVideoService appOperationVideoService;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
private final AliyunVoiceUtil voiceUtil;
|
||||
@ -721,20 +714,31 @@ public class DeviceXinghanBizService {
|
||||
return deviceTypeMapper.findAll(criteria);
|
||||
}
|
||||
|
||||
// @Log("新增设备")
|
||||
public void addDevice(DeviceForm deviceForm) {
|
||||
if (deviceForm.getDeviceMac() != null && deviceForm.getBluetoothName() == null) {
|
||||
/**
|
||||
* 校验唯一性约束
|
||||
*/
|
||||
private void validateDeviceUnique(DeviceForm form) {
|
||||
if (form.getDeviceMac() != null && form.getBluetoothName() == null) {
|
||||
throw new BadRequestException("请填写蓝牙名称!!!");
|
||||
}
|
||||
|
||||
Device device1 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_mac", deviceForm.getDeviceMac()));
|
||||
if (device1 != null) {
|
||||
// 使用 QueryWrapper 替代 lambdaQuery()
|
||||
Long macCount = deviceMapper.selectCount(new LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getDeviceMac, form.getDeviceMac()));
|
||||
if (macCount > 0) {
|
||||
throw new BadRequestException("设备MAC已存在!!!");
|
||||
}
|
||||
Device device2 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_imei", deviceForm.getDeviceImei()));
|
||||
if (device2 != null) {
|
||||
|
||||
Long imeiCount = deviceMapper.selectCount(new LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getDeviceImei, form.getDeviceImei()));
|
||||
if (imeiCount > 0) {
|
||||
throw new BadRequestException("设备IMEI已存在!!!");
|
||||
}
|
||||
}
|
||||
|
||||
// @Log("新增设备")
|
||||
public void addDevice(DeviceForm deviceForm) {
|
||||
validateDeviceUnique(deviceForm);
|
||||
|
||||
DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria();
|
||||
queryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
|
||||
@ -768,6 +772,14 @@ public class DeviceXinghanBizService {
|
||||
device.setBindingStatus(0);
|
||||
deviceMapper.insert(device);
|
||||
|
||||
Long deviceId = device.getDeviceId();
|
||||
|
||||
// 查询设备类型的文件列表
|
||||
// 4. 核心优化:同步设备类型的文件列表 (一行代码)
|
||||
appBusinessFileService.cloneFiles(deviceTypes.getId(), device.getId());
|
||||
//同步设备类型的视频列表
|
||||
appOperationVideoService.cloneFiles(deviceTypes.getId(), device.getId());
|
||||
|
||||
// 新增设备类型记录
|
||||
DeviceAssignments assignments = new DeviceAssignments();
|
||||
assignments.setDeviceId(device.getId());
|
||||
|
||||
@ -17,9 +17,9 @@ import com.fuyuanshen.common.core.validate.AddGroup;
|
||||
import com.fuyuanshen.common.core.validate.EditGroup;
|
||||
import com.fuyuanshen.common.log.enums.BusinessType;
|
||||
import com.fuyuanshen.common.excel.utils.ExcelUtil;
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
|
||||
@ -17,9 +17,9 @@ import com.fuyuanshen.common.core.validate.AddGroup;
|
||||
import com.fuyuanshen.common.core.validate.EditGroup;
|
||||
import com.fuyuanshen.common.log.enums.BusinessType;
|
||||
import com.fuyuanshen.common.excel.utils.ExcelUtil;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.equipment.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
|
||||
@ -54,10 +54,16 @@ public class AppDeviceHBY100JDetailVo implements Serializable {
|
||||
private String bluetoothName;
|
||||
|
||||
//电量百分比
|
||||
private String batteryPercentage;
|
||||
/**
|
||||
* 电量百分比
|
||||
*/
|
||||
private Integer batteryPercentage;
|
||||
|
||||
//充电状态(0没有充电,1正在充电,2为已充满)
|
||||
private String chargeState;
|
||||
/**
|
||||
* 充电状态(0没有充电,1正在充电,2为已充满)
|
||||
*/
|
||||
private Integer chargeState;
|
||||
|
||||
/**
|
||||
* 在线状态(0离线,1在线)
|
||||
@ -65,18 +71,33 @@ public class AppDeviceHBY100JDetailVo implements Serializable {
|
||||
private Integer onlineStatus;
|
||||
|
||||
// 经度
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private String longitude;
|
||||
|
||||
// 纬度
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private String latitude;
|
||||
|
||||
// 逆解析地址
|
||||
/**
|
||||
* 逆解析地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
// 亮度
|
||||
private String lightBrightness;
|
||||
/**
|
||||
* 亮度
|
||||
*/
|
||||
private Integer lightBrightness;
|
||||
|
||||
// 音量
|
||||
/**
|
||||
* 音量
|
||||
*/
|
||||
private Integer volume;
|
||||
|
||||
|
||||
@ -85,20 +106,40 @@ public class AppDeviceHBY100JDetailVo implements Serializable {
|
||||
*/
|
||||
private String voiceResource;
|
||||
|
||||
// 报警模式 0公安,1 消防,2应急,3交警,4 市政,5 铁路,6 医疗,7 部队,8 水利,9 语音
|
||||
private String alarmMode;
|
||||
// 报警模式 0公安,1 消防,2应急,3交警,4 市政,5 铁路,6 医疗,7 自定义语音
|
||||
/**
|
||||
* 报警模式 0公安,1 消防,2应急,3交警,4 市政,5 铁路,6 医疗,7 自定义语音
|
||||
*/
|
||||
private Integer alarmMode;
|
||||
|
||||
// 强制报警开关: 0 关闭, 1开启
|
||||
private String voiceStrobeAlarm;
|
||||
/**
|
||||
* 强制报警开关: 0 关闭, 1开启
|
||||
*/
|
||||
private Integer voiceStrobeAlarm;
|
||||
|
||||
/**
|
||||
* 0 红色爆闪,1 蓝色爆闪,2 黄色爆闪,3,红色顺时针旋转爆闪,4黄色顺时针旋转爆闪,5,红蓝顺时针旋转爆闪,6 红蓝交替爆闪
|
||||
*/
|
||||
private Integer strobeMode;
|
||||
|
||||
/**
|
||||
* "enable": 0爆闪关闭, 1爆闪开启
|
||||
*/
|
||||
private Integer strobeEnable;
|
||||
|
||||
/**
|
||||
* 爆闪频率
|
||||
*/
|
||||
private Integer strobeFrequency;
|
||||
|
||||
/**
|
||||
* 语音播报0 关闭, 1开启
|
||||
*/
|
||||
private Integer voiceBroadcast;
|
||||
|
||||
/**
|
||||
* 续航时间(分钟)
|
||||
*/
|
||||
private Integer batteryRemainingTime;
|
||||
}
|
||||
|
||||
@ -317,8 +317,7 @@ public class DeviceController extends BaseController {
|
||||
// 定义必需的表头
|
||||
Set<String> requiredHeaders = new HashSet<>(Arrays.asList(
|
||||
"设备名称", "设备类型名称", "设备图片", "设备MAC", "蓝牙名称", "设备IMEI",
|
||||
"备注", "是否支持蓝牙", "定位方式", "通讯方式",
|
||||
"型号字典用于APP页面跳转", "型号字典用于PC页面跳转"
|
||||
"备注"
|
||||
));
|
||||
|
||||
// 检查必需的表头是否都存在
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.fuyuanshen.app.domain;
|
||||
package com.fuyuanshen.equipment.domain;
|
||||
|
||||
import com.fuyuanshen.common.tenant.core.TenantEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
@ -1,4 +1,4 @@
|
||||
package com.fuyuanshen.app.domain;
|
||||
package com.fuyuanshen.equipment.domain;
|
||||
|
||||
import com.fuyuanshen.common.tenant.core.TenantEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
@ -1,6 +1,6 @@
|
||||
package com.fuyuanshen.app.domain.bo;
|
||||
package com.fuyuanshen.equipment.domain.bo;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.common.core.validate.EditGroup;
|
||||
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
@ -56,4 +56,6 @@ public class AppBusinessFileBo extends BaseEntity {
|
||||
* 是否使用语音播报(0-否,1-是)
|
||||
*/
|
||||
private Integer useStatus;
|
||||
|
||||
private Long createBy;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package com.fuyuanshen.app.domain.bo;
|
||||
package com.fuyuanshen.equipment.domain.bo;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.common.core.validate.EditGroup;
|
||||
import com.fuyuanshen.common.mybatis.core.domain.BaseEntity;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
@ -1,17 +1,13 @@
|
||||
package com.fuyuanshen.app.domain.vo;
|
||||
package com.fuyuanshen.equipment.domain.vo;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
|
||||
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -1,4 +1,4 @@
|
||||
package com.fuyuanshen.app.domain.vo;
|
||||
package com.fuyuanshen.equipment.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
package com.fuyuanshen.app.domain.vo;
|
||||
package com.fuyuanshen.equipment.domain.vo;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.fuyuanshen.common.excel.annotation.ExcelDictFormat;
|
||||
import com.fuyuanshen.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -1,10 +1,10 @@
|
||||
package com.fuyuanshen.app.mapper;
|
||||
package com.fuyuanshen.equipment.mapper;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package com.fuyuanshen.app.mapper;
|
||||
package com.fuyuanshen.equipment.mapper;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
@ -1,11 +1,11 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
package com.fuyuanshen.equipment.service;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -57,7 +57,9 @@ public interface IAppBusinessFileService {
|
||||
* @param bo 批量新增app业务文件
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertBatch(Collection<AppBusinessFile> bo,Boolean isBatch);
|
||||
Boolean insertBatch(Collection<AppBusinessFile> bo, Boolean isBatch);
|
||||
|
||||
void cloneFiles(Long sourceId, Long targetId);
|
||||
|
||||
/**
|
||||
* 修改app业务文件
|
||||
@ -1,11 +1,10 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
package com.fuyuanshen.equipment.service;
|
||||
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -59,6 +58,8 @@ public interface IAppOperationVideoService {
|
||||
*/
|
||||
Boolean insertBatch(Collection<AppOperationVideo> bo);
|
||||
|
||||
void cloneFiles(Long sourceId, Long targetId);
|
||||
|
||||
/**
|
||||
* 修改操作视频
|
||||
*
|
||||
@ -1,27 +1,29 @@
|
||||
package com.fuyuanshen.app.service.impl;
|
||||
package com.fuyuanshen.equipment.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.common.core.utils.MapstructUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.fuyuanshen.equipment.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.equipment.mapper.AppBusinessFileMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.mapper.AppBusinessFileMapper;
|
||||
import com.fuyuanshen.app.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.equipment.service.IAppBusinessFileService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* app业务文件Service业务层处理
|
||||
@ -117,6 +119,38 @@ public class AppBusinessFileServiceImpl implements IAppBusinessFileService {
|
||||
return baseMapper.insertBatch(bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆业务文件列表到新业务ID
|
||||
* @param sourceId 源业务ID(如设备类型ID)
|
||||
* @param targetId 目标业务ID(如新设备ID)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void cloneFiles(Long sourceId, Long targetId) {
|
||||
// 1. 使用 Wrappers 替代 this.lambdaQuery()
|
||||
List<AppBusinessFile> sourceFiles = baseMapper.selectList(
|
||||
Wrappers.<AppBusinessFile>lambdaQuery().eq(AppBusinessFile::getBusinessId, sourceId)
|
||||
);
|
||||
|
||||
if (CollUtil.isEmpty(sourceFiles)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 批量转换并重置ID
|
||||
List<AppBusinessFile> newFiles = sourceFiles.stream().map(file -> {
|
||||
AppBusinessFile entity = new AppBusinessFile();
|
||||
// 建议使用你代码中已有的 MapstructUtils 或 BeanUtil
|
||||
BeanUtil.copyProperties(file, entity);
|
||||
entity.setId(null); // 确保主键自增
|
||||
entity.setBusinessId(targetId); // 绑定到新设备ID
|
||||
return entity;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 3. 使用你已有的 insertBatch 替代 saveBatch
|
||||
// 注意:这里第二个参数传 false,因为是新设备,不需要执行你 insertBatch 里的删除逻辑
|
||||
this.insertBatch(newFiles, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改app业务文件
|
||||
*
|
||||
@ -1,7 +1,8 @@
|
||||
package com.fuyuanshen.app.service.impl;
|
||||
package com.fuyuanshen.equipment.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.common.core.utils.MapstructUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
@ -9,18 +10,20 @@ import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.fuyuanshen.equipment.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.equipment.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.equipment.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.equipment.mapper.AppOperationVideoMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.fuyuanshen.app.domain.bo.AppOperationVideoBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppOperationVideoVo;
|
||||
import com.fuyuanshen.app.domain.AppOperationVideo;
|
||||
import com.fuyuanshen.app.mapper.AppOperationVideoMapper;
|
||||
import com.fuyuanshen.app.service.IAppOperationVideoService;
|
||||
import com.fuyuanshen.equipment.service.IAppOperationVideoService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 操作视频Service业务层处理
|
||||
@ -125,6 +128,37 @@ public class AppOperationVideoServiceImpl implements IAppOperationVideoService {
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆业务文件列表到新业务ID
|
||||
* @param sourceId 源业务ID(如设备类型ID)
|
||||
* @param targetId 目标业务ID(如新设备ID)
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void cloneFiles(Long sourceId, Long targetId) {
|
||||
// 1. 使用 Wrappers 替代 this.lambdaQuery()
|
||||
List<AppOperationVideo> sourceFiles = baseMapper.selectList(
|
||||
Wrappers.<AppOperationVideo>lambdaQuery().eq(AppOperationVideo::getDeviceId, sourceId)
|
||||
);
|
||||
|
||||
if (CollUtil.isEmpty(sourceFiles)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 批量转换并重置ID
|
||||
List<AppOperationVideo> newFiles = sourceFiles.stream().map(file -> {
|
||||
AppOperationVideo entity = new AppOperationVideo();
|
||||
// 建议使用你代码中已有的 MapstructUtils 或 BeanUtil
|
||||
BeanUtil.copyProperties(file, entity);
|
||||
entity.setId(null); // 确保主键自增
|
||||
entity.setDeviceId(targetId); // 绑定到新设备ID
|
||||
return entity;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
// 3. 使用你已有的 insertBatch 替代 saveBatch
|
||||
this.insertBatch(newFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
@ -30,10 +30,7 @@ import com.fuyuanshen.equipment.enums.BindingStatusEnum;
|
||||
import com.fuyuanshen.equipment.enums.CommunicationModeEnum;
|
||||
import com.fuyuanshen.equipment.enums.DeviceActiveStatusEnum;
|
||||
import com.fuyuanshen.equipment.mapper.*;
|
||||
import com.fuyuanshen.equipment.service.DeviceAssignmentsService;
|
||||
import com.fuyuanshen.equipment.service.DeviceService;
|
||||
import com.fuyuanshen.equipment.service.DeviceTypeGrantsService;
|
||||
import com.fuyuanshen.equipment.service.IDeviceGeoFenceService;
|
||||
import com.fuyuanshen.equipment.service.*;
|
||||
import com.fuyuanshen.equipment.utils.FileHashUtil;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.domain.vo.SysRoleVo;
|
||||
@ -77,6 +74,8 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
|
||||
|
||||
private final DeviceFenceAccessRecordMapper deviceFenceAccessRecordMapper;
|
||||
private final FileHashUtil fileHashUtil;
|
||||
private final IAppBusinessFileService appBusinessFileService;
|
||||
private final IAppOperationVideoService appOperationVideoService;
|
||||
|
||||
|
||||
/**
|
||||
@ -334,6 +333,12 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
|
||||
device.setBindingStatus(0);
|
||||
deviceMapper.insert(device);
|
||||
|
||||
// 查询设备类型的文件列表
|
||||
// 4. 核心优化:同步设备类型的文件列表 (一行代码)
|
||||
appBusinessFileService.cloneFiles(deviceType.getId(), device.getId());
|
||||
//同步设备类型的视频列表
|
||||
appOperationVideoService.cloneFiles(deviceType.getId(), device.getId());
|
||||
|
||||
// 新增设备类型记录
|
||||
DeviceAssignments assignments = new DeviceAssignments();
|
||||
assignments.setDeviceId(device.getId());
|
||||
|
||||
@ -113,14 +113,14 @@ public class AlibabaTTSUtil {
|
||||
DEFAULT_VOLUME, DEFAULT_SPEECH_RATE, DEFAULT_PITCH_RATE);
|
||||
}
|
||||
|
||||
public byte[] synthesizeTextToMp3(String text){
|
||||
public byte[] synthesizeTextToMp3(String text,String fileSuffix){
|
||||
try {
|
||||
// 获取访问令牌
|
||||
String token = getValidAccessToken();
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(appkey,token);
|
||||
|
||||
return httpClient.synthesizeTextToMp3(text);
|
||||
return httpClient.synthesizeTextToMp3(text,fileSuffix);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
@ -67,4 +69,32 @@ public class FileHashUtil {
|
||||
throw new IllegalStateException("算法 " + ALGORITHM + " 不可用", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的哈希值
|
||||
* // 或者使用特定算法
|
||||
* String md5Hash = getFileHash(audioFile, "MD5");
|
||||
* String sha256Hash = getFileHash(audioFile, "SHA-256");
|
||||
* @param file 文件
|
||||
* @param algorithm 哈希算法
|
||||
* @return 文件的哈希值
|
||||
* @throws Exception 获取文件哈希值时发生的异常
|
||||
*/
|
||||
public String getFileHash(File file, String algorithm) throws Exception {
|
||||
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
md.update(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
byte[] hashBytes = md.digest();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : hashBytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,7 +9,9 @@ import java.net.URL;
|
||||
import static cn.dev33.satoken.SaManager.log;
|
||||
|
||||
public class HttpTtsClient {
|
||||
|
||||
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String appKey;
|
||||
private String token;
|
||||
/**
|
||||
@ -17,36 +19,57 @@ public class HttpTtsClient {
|
||||
*/
|
||||
private static final String BASE_URL = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
|
||||
|
||||
public HttpTtsClient(String appKey, String token) {
|
||||
this.appKey = appKey;
|
||||
public HttpTtsClient(String accessKeyId, String token) {
|
||||
this.accessKeyId = accessKeyId;
|
||||
this.token = token;
|
||||
// this.accessKeySecret = accessKeySecret;
|
||||
// this.appKey = appKey;
|
||||
}
|
||||
// private String refreshAccessToken() {
|
||||
// try {
|
||||
// // 调用阿里云API获取访问令牌
|
||||
// AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
|
||||
// accessToken.apply();
|
||||
// String token = accessToken.getToken();
|
||||
// log.info("访问令牌刷新成功");
|
||||
//
|
||||
// return token;
|
||||
// } catch (Exception e) {
|
||||
// log.error("刷新访问令牌失败: {}", e.getMessage(), e);
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* 使用HTTP POST方式调用阿里云TTS服务生成MP3格式语音
|
||||
*/
|
||||
public byte[] synthesizeTextToMp3(String text) throws IOException {
|
||||
String endpoint = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
|
||||
public byte[] synthesizeTextToMp3(String text,String fileSuffix) throws IOException {
|
||||
// String endpoint = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
|
||||
|
||||
// 构建请求体
|
||||
// String requestBody = String.format(
|
||||
// "{\"appkey\":\"%s\",\"text\":\"%s\",\"voice\":\"zhifeng\",\"format\":\"MP3\",\"sample_rate\":24000,\"volume\":50,\"speech_rate\":0,\"pitch_rate\":0}",
|
||||
// appKey,
|
||||
// text.replace("\"", "\\\"")
|
||||
// text.replace("\"", "\\\"")zhide
|
||||
// );
|
||||
|
||||
// String token = refreshAccessToken();
|
||||
String requestBody = " {\n" +
|
||||
" \"appkey\":\""+appKey+"\",\n" +
|
||||
" \"voice\":\"zhifeng\",\n" +
|
||||
" \"text\":\""+text+"\",\n" +
|
||||
" \"token\":\""+token+"\",\n" +
|
||||
" \"format\":\"mp3\"\n" +
|
||||
" \"volume\": 100,\n" +
|
||||
" \"pitch_rate\": 0,\n" +
|
||||
" \"format\":\""+fileSuffix+"\"\n" +
|
||||
" }";
|
||||
|
||||
URL url = new URL(endpoint);
|
||||
URL url = new URL(BASE_URL);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
|
||||
// 设置请求方法和头部
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
// conn.setRequestProperty("Authorization", buildAuthorization());
|
||||
conn.setRequestProperty("Authorization", buildAuthorization());
|
||||
conn.setRequestProperty("Content-Length", String.valueOf(requestBody.getBytes().length));
|
||||
conn.setDoOutput(true);
|
||||
|
||||
@ -72,13 +95,29 @@ public class HttpTtsClient {
|
||||
throw new IOException("HTTP请求失败,状态码: " + responseCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建授权头部
|
||||
*/
|
||||
private String buildAuthorization() {
|
||||
// 实际实现需要根据阿里云API规范构建签名
|
||||
// 这里是简化示例
|
||||
return "Bearer " + generateAccessToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成访问令牌
|
||||
*/
|
||||
private String generateAccessToken() {
|
||||
// 实际实现需要调用阿里云获取token的API
|
||||
return "your-access-token";
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存MP3到文件
|
||||
*/
|
||||
public String saveMp3ToFile(String text, String outputPath) throws IOException {
|
||||
byte[] mp3Data = synthesizeTextToMp3(text);
|
||||
byte[] mp3Data = synthesizeTextToMp3(text,"mp3");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
||||
fos.write(mp3Data);
|
||||
|
||||
@ -4,7 +4,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.fuyuanshen.app.mapper.AppBusinessFileMapper">
|
||||
|
||||
<select id="queryAppFileList" resultType="com.fuyuanshen.app.domain.vo.AppFileVo">
|
||||
<select id="queryAppFileList" resultType="com.fuyuanshen.equipment.domain.vo.AppFileVo">
|
||||
select a.id,a.business_id,a.file_id,a.file_type,b.file_name,b.url fileUrl,a.duration,
|
||||
CASE
|
||||
WHEN a.re_name IS NULL THEN
|
||||
@ -2,6 +2,6 @@
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.fuyuanshen.app.mapper.AppOperationVideoMapper">
|
||||
<mapper namespace="com.fuyuanshen.equipment.mapper.AppOperationVideoMapper">
|
||||
|
||||
</mapper>
|
||||
@ -68,6 +68,13 @@ public interface ISysOssService {
|
||||
*/
|
||||
SysOssVo updateHash(MultipartFile file, String hash);
|
||||
|
||||
/**
|
||||
* 更新文件 hash 值
|
||||
*
|
||||
* @param file 文件对象
|
||||
* @return 匹配的 SysOssVo 列表
|
||||
*/
|
||||
SysOssVo updateHash(File file, String hash);
|
||||
/**
|
||||
* 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库
|
||||
*
|
||||
|
||||
@ -226,6 +226,22 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
|
||||
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysOssVo updateHash(File file, String hash) {
|
||||
// 2. 先根据 hash 查库(秒传)
|
||||
SysOssVo exist = baseMapper.selectByHash(hash);
|
||||
if (exist != null) {
|
||||
return exist;
|
||||
}
|
||||
|
||||
String originalfileName = file.getName();
|
||||
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
|
||||
OssClient storage = OssFactory.instance();
|
||||
UploadResult uploadResult = storage.uploadSuffix(file, suffix);
|
||||
// 保存文件信息
|
||||
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, hash);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库
|
||||
|
||||
Reference in New Issue
Block a user