Compare commits
10 Commits
e80830e76c
...
04cb699081
| Author | SHA1 | Date | |
|---|---|---|---|
| 04cb699081 | |||
| 0f0dd4c6b1 | |||
| 2db37a75d2 | |||
| 696bbb4aa4 | |||
| ee445dc0d2 | |||
| 897561ba89 | |||
| 2e575f78b1 | |||
| 6fd7f8ca94 | |||
| 9936a5ad13 | |||
| c267fe0c14 |
@ -133,6 +133,25 @@
|
||||
<version>1.5.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Java音频转换库 -->
|
||||
<dependency>
|
||||
<groupId>ws.schild</groupId>
|
||||
<artifactId>jave-core</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>
|
||||
<groupId>ws.schild</groupId>
|
||||
<artifactId>jave-nativebin-all</artifactId>
|
||||
<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>-->
|
||||
|
||||
81
fys-admin/src/main/java/com/fuyuanshen/SimpleQR.java
Normal file
81
fys-admin/src/main/java/com/fuyuanshen/SimpleQR.java
Normal file
@ -0,0 +1,81 @@
|
||||
package com.fuyuanshen;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
|
||||
public class SimpleQR {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String text = "HELLO";
|
||||
int size = 21; // 版本1的大小
|
||||
boolean[][] qr = new boolean[size][size];
|
||||
|
||||
// 1. 三个定位标记
|
||||
for (int i = 0; i < 7; i++)
|
||||
for (int j = 0; j < 7; j++) {
|
||||
boolean black = i == 0 || i == 6 || j == 0 || j == 6 || (i > 1 && i < 5 && j > 1 && j < 5);
|
||||
qr[i][j] = qr[i][size - 1 - j] = qr[size - 1 - i][j] = black;
|
||||
}
|
||||
|
||||
// 2. 定时图案(简化)
|
||||
for (int i = 8; i < 13; i++) qr[i][6] = qr[6][i] = (i % 2 == 0);
|
||||
|
||||
// 3. 编码数据(极简编码)
|
||||
byte[] data = text.getBytes();
|
||||
int x = 20, y = 20, up = 1; // 从右下角开始
|
||||
for (byte b : data)
|
||||
for (int bit = 7; bit >= 0; bit--) {
|
||||
while (qr[x][y] || (x == 6 && y < 9) || (y == 6 && x < 9) || (x < 9 && y < 9) ||
|
||||
(x < 9 && y > size - 10) || (y < 9 && x > size - 10)) {
|
||||
if (up > 0) {
|
||||
if (--y < 0) {
|
||||
y = 0;
|
||||
x -= 2;
|
||||
up = -1;
|
||||
}
|
||||
} else {
|
||||
if (++y >= size) {
|
||||
y = size - 1;
|
||||
x -= 2;
|
||||
up = 1;
|
||||
}
|
||||
}
|
||||
if (x == 6) x--;
|
||||
}
|
||||
qr[x][y] = ((b >> bit) & 1) == 1;
|
||||
if (up > 0) {
|
||||
if (--y < 0) {
|
||||
y = 0;
|
||||
x -= 2;
|
||||
up = -1;
|
||||
}
|
||||
} else {
|
||||
if (++y >= size) {
|
||||
y = size - 1;
|
||||
x -= 2;
|
||||
up = 1;
|
||||
}
|
||||
}
|
||||
if (x == 6) x--;
|
||||
}
|
||||
|
||||
// 4. 保存图像
|
||||
int scale = 10, margin = 4;
|
||||
BufferedImage img = new BufferedImage(
|
||||
size * scale + margin * 2, size * scale + margin * 2, BufferedImage.TYPE_INT_RGB);
|
||||
for (int i = 0; i < img.getWidth(); i++)
|
||||
for (int j = 0; j < img.getHeight(); j++)
|
||||
img.setRGB(i, j, 0xFFFFFF); // 白色背景
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
for (int j = 0; j < size; j++)
|
||||
if (qr[i][j])
|
||||
for (int di = 0; di < scale; di++)
|
||||
for (int dj = 0; dj < scale; dj++)
|
||||
img.setRGB(margin + i * scale + di, margin + j * scale + dj, 0x000000);
|
||||
|
||||
ImageIO.write(img, "PNG", new File("qr.png"));
|
||||
System.out.println("二维码已生成");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,12 @@
|
||||
package com.fuyuanshen.app.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppAudioFileDto;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileDto;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileRenameDto;
|
||||
import com.fuyuanshen.app.domain.dto.TextToSpeechRequest;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
import com.fuyuanshen.app.service.AudioProcessService;
|
||||
import com.fuyuanshen.app.service.VideoProcessService;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
@ -8,6 +14,7 @@ import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -56,6 +63,7 @@ public class AppVideoController extends BaseController {
|
||||
return R.ok(audioProcessService.generateStandardPcmData(text));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提取文本内容(只支持txt/docx)
|
||||
*/
|
||||
@ -65,4 +73,68 @@ public class AppVideoController extends BaseController {
|
||||
return R.ok("Success",audioProcessService.extract(file));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传音频文件进行处理
|
||||
* 支持MP3、WAV、PCM格式
|
||||
*/
|
||||
@PostMapping("/uploadAudioToOss")
|
||||
public R<String> uploadAudioToOss(@ModelAttribute AppAudioFileDto bo) {
|
||||
try {
|
||||
String result = audioProcessService.uploadAudioToOss(bo);
|
||||
return R.ok(result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return R.fail("文件格式错误: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
|
||||
return R.fail("上传处理失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本转语音
|
||||
* 支持MP3、WAV、PCM格式
|
||||
*/
|
||||
@PostMapping("/ttsToOss")
|
||||
public R<String> textToSpeech(@RequestBody TextToSpeechRequest request) {
|
||||
try {
|
||||
if (request.getDeviceId() == null) {
|
||||
return R.fail("设备ID不能为空");
|
||||
}
|
||||
|
||||
String result = audioProcessService.textToSpeech(
|
||||
request.getDeviceId(),
|
||||
request.getText(),
|
||||
request.getFileSuffix()
|
||||
);
|
||||
return R.ok(result);
|
||||
} catch (Exception e) {
|
||||
return R.fail("文本转语音失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询语音文件列表
|
||||
*/
|
||||
@GetMapping("/queryAudioFileList")
|
||||
public R<List<AppFileVo>> queryAudioFileList(Long deviceId) {
|
||||
return R.ok(audioProcessService.queryAudioFileList(deviceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除语音文件
|
||||
*/
|
||||
@GetMapping("/deleteAudioFile")
|
||||
public R<Void> deleteAudioFile(Long fileId,Long deviceId) {
|
||||
return audioProcessService.deleteAudioFile(fileId,deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件重命名
|
||||
*/
|
||||
@PostMapping("/renameAudioFile")
|
||||
public R<Void> renameAudioFile(@RequestBody AppFileRenameDto bo) {
|
||||
return audioProcessService.renameAudioFile(bo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,191 @@
|
||||
package com.fuyuanshen.app.controller.device.bjq;
|
||||
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceHBY100JDetailVo;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
import com.fuyuanshen.web.service.device.DeviceHBY100JBizService;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* HBY100J设备控制类
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/app/hby100j/device")
|
||||
public class AppDeviceHBY100JController extends BaseController {
|
||||
|
||||
private final DeviceHBY100JBizService deviceHBY100JBizService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取设备详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public R<AppDeviceHBY100JDetailVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(deviceHBY100JBizService.getInfo(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新语音
|
||||
*/
|
||||
@PostMapping("/updateVoice")
|
||||
public R<Void> updateVoice(@RequestBody HBY100JUpdateVoiceDto dto) {
|
||||
deviceHBY100JBizService.updateVoice(dto);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制报警
|
||||
*
|
||||
*/
|
||||
|
||||
@PostMapping("/forceAlarmActivation")
|
||||
public R<Void> forceAlarmActivation(@RequestBody HBY100JForceAlarmActivationDto bo) {
|
||||
deviceHBY100JBizService.forceAlarmActivation(bo);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 爆闪模式
|
||||
*/
|
||||
@PostMapping("/strobeMode")
|
||||
public R<Void> strobeMode(@RequestBody HBY100JStrobeModeDto params) {
|
||||
deviceHBY100JBizService.strobeMode(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 灯光调节
|
||||
*/
|
||||
@PostMapping("/lightAdjustment")
|
||||
public R<Void> lightAdjustment(@RequestBody HBY100JLightAdjustmentDto params) {
|
||||
deviceHBY100JBizService.lightAdjustment(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 爆闪频率
|
||||
*/
|
||||
@PostMapping("/strobeFrequency")
|
||||
public R<Void> strobeFrequency(@RequestBody HBY100JStrobeFrequencyDto params) {
|
||||
deviceHBY100JBizService.strobeFrequency(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改音量
|
||||
*/
|
||||
@PostMapping("/updateVolume")
|
||||
public R<Void> updateVolume(@RequestBody HBY100JUpdateVolumeDto params) {
|
||||
deviceHBY100JBizService.updateVolume(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HBY100JUpdateVoiceDto {
|
||||
|
||||
private Long id;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HBY100JForceAlarmActivationDto {
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
List<Long> deviceIds;
|
||||
/**
|
||||
* 0 关闭, 1开启
|
||||
*/
|
||||
private Integer voiceStrobeAlarm;
|
||||
/**
|
||||
* 0 公安,1消防,2应急,3交警,4 市政,5 铁路,6 医疗,7部队,8 水利,9 语音
|
||||
*/
|
||||
private Integer mode;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HBY100JUpdateVolumeDto{
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
private Long deviceId;
|
||||
/**
|
||||
* "volume": 1-100(app端可根据需求把40作为低音量, 70作为中音量,100作为高音量)
|
||||
*/
|
||||
private Integer volume;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HBY100JStrobeFrequencyDto{
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
private Long deviceId;
|
||||
/**
|
||||
* "frequency": 1-12
|
||||
*/
|
||||
private Integer frequency;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class HBY100JLightAdjustmentDto{
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
private Long deviceId;
|
||||
|
||||
/**
|
||||
* 亮度值0-100
|
||||
*/
|
||||
private Integer brightness;
|
||||
// /**
|
||||
// * 红色LED亮度值0-100
|
||||
// */
|
||||
// private Integer red;
|
||||
//
|
||||
// /**
|
||||
// * 蓝色LED亮度值0-100
|
||||
// */
|
||||
// private Integer blue;
|
||||
//
|
||||
// /**
|
||||
// * 黄色LED亮度值0-100
|
||||
// */
|
||||
// private Integer yellow;
|
||||
|
||||
}
|
||||
@Data
|
||||
public static class HBY100JStrobeModeDto{
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
private Long deviceId;
|
||||
/**
|
||||
* 0 关闭 1 开启
|
||||
*/
|
||||
private Integer enable;
|
||||
|
||||
/**
|
||||
* 0 红色爆闪,1 蓝色爆闪,2 黄色爆闪,3,红色顺时针旋转爆闪,4黄色顺时针旋转爆闪,5,红蓝顺时针旋转爆闪,6 红蓝交替爆闪
|
||||
*/
|
||||
private Integer mode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.fuyuanshen.app.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Data
|
||||
public class AppAudioFileDto {
|
||||
|
||||
private Long deviceId;
|
||||
|
||||
/**
|
||||
* 文件
|
||||
*/
|
||||
private MultipartFile file;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.fuyuanshen.app.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Data
|
||||
public class AppFileRenameDto {
|
||||
|
||||
/**
|
||||
* 文件id
|
||||
*/
|
||||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 设备id
|
||||
*/
|
||||
private Long deviceId;
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.fuyuanshen.app.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* PCM生成请求实体
|
||||
*/
|
||||
@Data
|
||||
public class PcmGenerationRequest {
|
||||
private String text;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.fuyuanshen.app.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 文本转语音请求实体
|
||||
*/
|
||||
@Data
|
||||
public class TextToSpeechRequest {
|
||||
|
||||
private Long deviceId;
|
||||
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* 文件后缀格式
|
||||
*/
|
||||
private String fileSuffix;
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
package com.fuyuanshen.app.http;
|
||||
|
||||
import com.alibaba.nls.client.AccessToken;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.Base64;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static cn.dev33.satoken.SaManager.log;
|
||||
|
||||
public class HttpTtsClient {
|
||||
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String appKey;
|
||||
/**
|
||||
* 阿里云TTS服务基础URL
|
||||
*/
|
||||
private static final String BASE_URL = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
|
||||
|
||||
public HttpTtsClient(String accessKeyId, String accessKeySecret, String appKey) {
|
||||
this.accessKeyId = accessKeyId;
|
||||
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";
|
||||
|
||||
// 构建请求体
|
||||
// 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("\"", "\\\"")
|
||||
// );
|
||||
|
||||
String token = refreshAccessToken();
|
||||
String requestBody = " {\n" +
|
||||
" \"appkey\":\""+appKey+"\",\n" +
|
||||
" \"text\":\""+text+"\",\n" +
|
||||
" \"token\":\""+token+"\",\n" +
|
||||
" \"format\":\"mp3\"\n" +
|
||||
" }";
|
||||
|
||||
URL url = new URL(endpoint);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
|
||||
// 设置请求方法和头部
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("Authorization", buildAuthorization());
|
||||
conn.setRequestProperty("Content-Length", String.valueOf(requestBody.getBytes().length));
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// 发送请求体
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(requestBody.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
// 读取响应
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
// 读取音频数据
|
||||
try (InputStream is = conn.getInputStream()) {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
int nRead;
|
||||
byte[] data = new byte[1024];
|
||||
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
||||
fos.write(mp3Data);
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.fuyuanshen.app.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class HttpTtsExample {
|
||||
|
||||
/**
|
||||
* appKey: lbGuq5K5bEH4uxmT
|
||||
* akId: LTAI5t66moCkhNC32TDJ5ReP
|
||||
* akSecret: 2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
String accessKeyId = "LTAI5t66moCkhNC32TDJ5ReP";
|
||||
String accessKeySecret = "2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH";
|
||||
String appKey = "lbGuq5K5bEH4uxmT";
|
||||
|
||||
try {
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(accessKeyId, accessKeySecret, appKey);
|
||||
|
||||
String text = "大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。";
|
||||
String outputPath = "D:\\http_output9.mp3";
|
||||
|
||||
String resultFile = httpClient.saveMp3ToFile(text, outputPath);
|
||||
System.out.println("MP3音频已保存至: " + resultFile);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.fuyuanshen.app.http;
|
||||
|
||||
import okhttp3.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OkHttpTtsClient {
|
||||
|
||||
private OkHttpClient client = new OkHttpClient();
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String appKey;
|
||||
|
||||
public OkHttpTtsClient(String accessKeyId, String accessKeySecret, String appKey) {
|
||||
this.accessKeyId = accessKeyId;
|
||||
this.accessKeySecret = accessKeySecret;
|
||||
this.appKey = appKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用OkHttp调用TTS服务
|
||||
*/
|
||||
public byte[] synthesizeTextToMp3(String text) throws IOException {
|
||||
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
|
||||
String jsonPayload = String.format(
|
||||
"{\"appkey\":\"%s\",\"text\":\"%s\",\"voice\":\"zhifeng\",\"format\":\"MP3\",\"sample_rate\":24000,\"volume\":50,\"speech_rate\":0,\"pitch_rate\":0}",
|
||||
appKey,
|
||||
text.replace("\"", "\\\"")
|
||||
);
|
||||
|
||||
RequestBody body = RequestBody.create(JSON,jsonPayload);
|
||||
Request request = new Request.Builder()
|
||||
.url("https://nls-gateway.cn-shanghai.aliyuncs.com/v1/tts")
|
||||
.post(body)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.addHeader("Authorization", "Bearer " + getAccessToken())
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
if (!response.isSuccessful()) {
|
||||
throw new IOException("HTTP请求失败: " + response.code());
|
||||
}
|
||||
|
||||
ResponseBody responseBody = response.body();
|
||||
if (responseBody != null) {
|
||||
return responseBody.bytes();
|
||||
} else {
|
||||
throw new IOException("响应体为空");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getAccessToken() {
|
||||
// 实现获取访问令牌的逻辑
|
||||
return "your-access-token";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.fuyuanshen.app.http;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* 获取阿里云TTS服务访问令牌
|
||||
*/
|
||||
public class TokenClient {
|
||||
|
||||
public static String getAccessToken(String accessKeyId, String accessKeySecret) throws IOException {
|
||||
String endpoint = "https://nls-meta.cn-shanghai.aliyuncs.com/v1/token";
|
||||
|
||||
URL url = new URL(endpoint);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// 发送认证信息
|
||||
String params = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s",
|
||||
accessKeyId, accessKeySecret);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(params.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
try (InputStream is = conn.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
|
||||
// 解析响应获取token(实际需要使用JSON解析库)
|
||||
return response.toString().replaceAll(".*\"access_token\":\"([^\"]+)\".*", "$1");
|
||||
}
|
||||
} else {
|
||||
throw new IOException("获取令牌失败,状态码: " + responseCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,5 +96,4 @@ public class AppFileService {
|
||||
}
|
||||
return appBusinessFileService.deleteWithValidByIds(List.of(ids), true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,21 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppAudioFileDto;
|
||||
import com.fuyuanshen.app.domain.dto.AppFileRenameDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppFileVo;
|
||||
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.equipment.utils.AlibabaTTSUtil;
|
||||
import com.fuyuanshen.equipment.utils.AudioProcessUtil;
|
||||
import com.fuyuanshen.equipment.utils.FileHashUtil;
|
||||
import com.fuyuanshen.equipment.utils.Mp3Duration;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.service.ISysOssService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -17,8 +31,12 @@ 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;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@ -39,6 +57,11 @@ public class AudioProcessService {
|
||||
private final AudioProcessUtil audioProcessUtil;
|
||||
private final AlibabaTTSUtil alibabaTTSUtil;
|
||||
|
||||
private final FileHashUtil fileHashUtil;
|
||||
private final ISysOssService ossService;
|
||||
private final IAppBusinessFileService appBusinessFileService;
|
||||
private final AppBusinessFileMapper appBusinessFileMapper;
|
||||
|
||||
/**
|
||||
* 处理上传的音频文件
|
||||
*/
|
||||
@ -175,6 +198,28 @@ public class AudioProcessService {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
private String saveByteArrayToFile(InputStream inputStream, String filename) throws IOException {
|
||||
// 确定保存路径(可以是临时目录或指定目录)
|
||||
String directory = System.getProperty("java.io.tmpdir"); // 使用系统临时目录
|
||||
File dir = new File(directory);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 创建完整文件路径
|
||||
File file = new File(dir, filename);
|
||||
|
||||
// 从输入流读取数据并写入文件
|
||||
try (FileOutputStream fos = new FileOutputStream(file);
|
||||
InputStream is = inputStream) {
|
||||
byte[] buffer = new byte[8192]; // 8KB缓冲区
|
||||
int bytesRead;
|
||||
while ((bytesRead = is.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -305,4 +350,191 @@ public class AudioProcessService {
|
||||
}
|
||||
|
||||
|
||||
public String uploadAudioToOss(AppAudioFileDto bo) {
|
||||
MultipartFile file = bo.getFile();
|
||||
// 校验文件格式和大小
|
||||
validateAudioFileForRestful(file);
|
||||
// 上传文件
|
||||
// SysOssVo upload = sysOssService.upload(file);
|
||||
String filename = file.getOriginalFilename();
|
||||
String savedPath = null;
|
||||
try {
|
||||
String fileHash = fileHashUtil.hash(file);
|
||||
SysOssVo upload = ossService.updateHash(file, fileHash);
|
||||
// 强制将HTTP替换为HTTPS
|
||||
if (upload.getUrl() != null && upload.getUrl().startsWith("http://")) {
|
||||
upload.setUrl(upload.getUrl().replaceFirst("^http://", "https://"));
|
||||
}
|
||||
String fileSuffix = filename.substring(filename.lastIndexOf('.')).toLowerCase();
|
||||
AppBusinessFileBo appBusinessFileBo = new AppBusinessFileBo();
|
||||
appBusinessFileBo.setFileId(upload.getOssId());
|
||||
appBusinessFileBo.setBusinessId(bo.getDeviceId());
|
||||
appBusinessFileBo.setFileType(3L);
|
||||
appBusinessFileBo.setCreateBy(AppLoginHelper.getUserId());
|
||||
savedPath = saveByteArrayToFile(file.getInputStream(), 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();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("上传音频文件失败", e);
|
||||
}finally {
|
||||
log.info("删除临时文件: {}", savedPath);
|
||||
if(savedPath != null){
|
||||
deleteTempFile(new File(savedPath));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验音频文件格式
|
||||
*/
|
||||
private void validateAudioFileForRestful(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new IllegalArgumentException("上传文件不能为空");
|
||||
}
|
||||
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (originalFilename == null) {
|
||||
throw new IllegalArgumentException("文件名不能为空");
|
||||
}
|
||||
List<String> SUPPORTED_FORMATS = Arrays.asList(
|
||||
".wav", ".mp3", ".pcm"
|
||||
);
|
||||
|
||||
String ext = originalFilename.substring(originalFilename.lastIndexOf('.')).toLowerCase();
|
||||
// 检查文件扩展名
|
||||
if (!SUPPORTED_FORMATS.contains(ext)) {
|
||||
throw new IllegalArgumentException("只允许上传MP3、WAV、PCM格式的音频文件");
|
||||
}
|
||||
|
||||
// 检查文件大小
|
||||
if (file.getSize() > MAX_AUDIO_SIZE) {
|
||||
throw new IllegalArgumentException("音频大小不能超过5MB");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否为支持的音频格式
|
||||
*/
|
||||
private boolean isSupportedFormat(String filename) {
|
||||
if (filename == null || filename.lastIndexOf('.') == -1) {
|
||||
return false;
|
||||
}
|
||||
String ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
|
||||
return SUPPORTED_FORMATS.contains(ext);
|
||||
}
|
||||
|
||||
public String textToSpeech(Long deviceId,String text, String fileSuffix) {
|
||||
//支持PCM/WAV/MP3格式
|
||||
if (fileSuffix == null || fileSuffix.isEmpty()) {
|
||||
fileSuffix = "mp3";
|
||||
}
|
||||
fileSuffix = fileSuffix.toLowerCase();
|
||||
List<String> SUPPORTED_FORMATS = Arrays.asList(
|
||||
"wav", "mp3", "pcm"
|
||||
);
|
||||
boolean contains = SUPPORTED_FORMATS.contains(fileSuffix);
|
||||
if (!contains) {
|
||||
throw new IllegalArgumentException("不支持的音频格式");
|
||||
}
|
||||
String accessKeyId = "LTAI5t66moCkhNC32TDJ5ReP";
|
||||
String accessKeySecret = "2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH";
|
||||
String appKey = "lbGuq5K5bEH4uxmT";
|
||||
String savedPath = null;
|
||||
try {
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(accessKeyId, accessKeySecret, appKey);
|
||||
//
|
||||
byte[] mp3Data = httpClient.synthesizeTextToMp3(text);
|
||||
// byte[] mp3Data = alibabaTTSUtil.synthesizeTextToMp3(text);
|
||||
|
||||
SysOssVo upload = ossService.upload(mp3Data, generateRandomFileName(fileSuffix));
|
||||
|
||||
// 强制将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();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("上传音频文件失败", e);
|
||||
} finally {
|
||||
log.info("删除临时文件: {}", savedPath);
|
||||
if(savedPath != null){
|
||||
deleteTempFile(new File(savedPath));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final DateTimeFormatter formatter =
|
||||
DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
/**
|
||||
* 生成纯随机文件名(无原文件名依赖)
|
||||
*/
|
||||
public static String generateRandomFileName(String extension) {
|
||||
String timestamp = LocalDateTime.now().format(formatter);
|
||||
int randomNum = random.nextInt(10000);
|
||||
String uuidPart = UUID.randomUUID().toString().substring(0, 8);
|
||||
|
||||
if (!extension.startsWith(".")) {
|
||||
extension = "." + extension;
|
||||
}
|
||||
|
||||
return timestamp + "_" + String.format("%04d", randomNum) + "_" + uuidPart + extension;
|
||||
}
|
||||
|
||||
public List<AppFileVo> queryAudioFileList(Long deviceId) {
|
||||
if(deviceId == null){
|
||||
return null;
|
||||
}
|
||||
AppBusinessFileBo bo = new AppBusinessFileBo();
|
||||
bo.setBusinessId(deviceId);
|
||||
bo.setFileType(3L);
|
||||
List<AppFileVo> appFileVos = appBusinessFileService.queryAppFileList(bo);
|
||||
return appFileVos;
|
||||
}
|
||||
|
||||
public R<Void> deleteAudioFile(Long fileId,Long deviceId) {
|
||||
UpdateWrapper<AppBusinessFile> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("file_id",fileId);
|
||||
updateWrapper.eq("business_id",deviceId);
|
||||
appBusinessFileMapper.delete(updateWrapper);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
public R<Void> renameAudioFile(AppFileRenameDto bo) {
|
||||
UpdateWrapper<AppBusinessFile> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("file_id",bo.getFileId());
|
||||
updateWrapper.eq("business_id",bo.getDeviceId());
|
||||
updateWrapper.set("re_name",bo.getFileName());
|
||||
appBusinessFileMapper.update(updateWrapper);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -13,4 +13,5 @@ public interface MqttConstants {
|
||||
*/
|
||||
String GLOBAL_SUB_KEY = "A/";
|
||||
|
||||
String GLOBAL_PUB_KEY2 = "command/";
|
||||
}
|
||||
|
||||
@ -51,48 +51,27 @@ public class NewReceiverMessageHandler implements MessageHandler {
|
||||
}
|
||||
String imei = payloadDict.getStr("imei");
|
||||
String funcType = payloadDict.getStr("funcType");
|
||||
RedissonClient client = RedisUtils.getClient();
|
||||
String lockKey = "mqtt:consumer:lock:";
|
||||
String KEY = GlobalConstants.GLOBAL_REDIS_KEY + lockKey + imei;
|
||||
log.info("MQTT2获取锁开始{}", KEY);
|
||||
RLock lock = client.getLock(KEY);
|
||||
// 执行业务逻辑
|
||||
if(StringUtils.isNotBlank(imei)){
|
||||
String queueKey = MqttMessageQueueConstants.MQTT_MESSAGE_QUEUE_KEY;
|
||||
String dedupKey = MqttMessageQueueConstants.MQTT_MESSAGE_DEDUP_KEY;
|
||||
RedisUtils.offerDeduplicated(queueKey,dedupKey,imei, Duration.ofSeconds(900));
|
||||
//在线状态
|
||||
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ imei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
|
||||
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(360));
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试获取锁,
|
||||
boolean isLocked = lock.tryLock(60, 3000, TimeUnit.MILLISECONDS);
|
||||
if (isLocked) {
|
||||
// 执行业务逻辑
|
||||
if(StringUtils.isNotBlank(imei)){
|
||||
String queueKey = MqttMessageQueueConstants.MQTT_MESSAGE_QUEUE_KEY;
|
||||
String dedupKey = MqttMessageQueueConstants.MQTT_MESSAGE_DEDUP_KEY;
|
||||
RedisUtils.offerDeduplicated(queueKey,dedupKey,imei, Duration.ofSeconds(900));
|
||||
//在线状态
|
||||
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ imei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
|
||||
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(360));
|
||||
}
|
||||
String[] topicArr = receivedTopic.split("/");
|
||||
|
||||
String[] topicArr = receivedTopic.split("/");
|
||||
NewMqttRuleContext context = new NewMqttRuleContext();
|
||||
context.setCommandType(topicArr[2]+"_"+funcType);
|
||||
context.setDeviceImei(imei);
|
||||
context.setPayloadDict(payloadDict);
|
||||
|
||||
NewMqttRuleContext context = new NewMqttRuleContext();
|
||||
context.setCommandType(topicArr[2]+"_"+funcType);
|
||||
context.setDeviceImei(imei);
|
||||
context.setPayloadDict(payloadDict);
|
||||
boolean ruleExecuted = newRuleEngine.executeRule(context);
|
||||
|
||||
boolean ruleExecuted = newRuleEngine.executeRule(context);
|
||||
|
||||
if (!ruleExecuted) {
|
||||
log.warn("未找到匹配的规则来处理命令类型: {}", topicArr[2] + " : " +funcType);
|
||||
}
|
||||
}else{
|
||||
log.warn("MQTT2获取锁失败,请稍后再试");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
// 释放锁
|
||||
if (lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
if (!ruleExecuted) {
|
||||
log.warn("未找到匹配的规则来处理命令类型: {}", topicArr[2] + " : " +funcType);
|
||||
}
|
||||
// final LockInfo lockInfo = lockTemplate.lock(GlobalConstants.GLOBAL_REDIS_KEY + lockKey + imei, 100L, 3000L, RedissonLockExecutor.class);
|
||||
// if (null == lockInfo) {
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 爆闪模式开启/关闭
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType10StrobeMode implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_10";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
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));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J爆闪模式开启/关闭失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 修改警示灯爆闪频率
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType11Frequency implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_11";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
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));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J修改警示灯爆闪频率失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 强制声光报警开启/关闭
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType12ForceAudio implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_12";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J强制声光报警开启/关闭,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
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));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J强制声光报警开启/关闭失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 警示灯LED亮度调节
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType13Brightness implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_13";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
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));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J警示灯LED亮度调节失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 获取警示灯的当前工作方式(设备下发返回响应数据、设备定时主动上报)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType14Report implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_14";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J设备定时主动上报,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":report";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J设备定时主动上报失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
//package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
//
|
||||
//import com.alibaba.fastjson2.JSONObject;
|
||||
//import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
//import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
//import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
//import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
//
|
||||
///**
|
||||
// * 设备复位
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//public class FuncType1Rest implements NewMqttMessageRule {
|
||||
//
|
||||
// @Override
|
||||
// public String getCommandType() {
|
||||
// return "HBY100_1";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void execute(NewMqttRuleContext context) {
|
||||
// log.info("开始处理设备复位,消息负载:{}", context.getPayloadDict());
|
||||
//
|
||||
// try {
|
||||
// // 构建强制声光报警开关的Redis键
|
||||
//// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
//// context.getDeviceImei() + ":force_audio_visual_alarm_switch";
|
||||
////
|
||||
//// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
//// if (payloadDict != null) {
|
||||
//// // 存储强制声光报警开关状态到Redis
|
||||
//// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
//// }
|
||||
// log.info("设备复位,设备ID:{}", context.getDeviceImei());
|
||||
// } catch (Exception e) {
|
||||
// log.error("处理设备复位失败", e);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@ -0,0 +1,46 @@
|
||||
//package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
//
|
||||
//import com.alibaba.fastjson2.JSONObject;
|
||||
//import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
//import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
//import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
//import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
//
|
||||
///**
|
||||
// * 获取设备基础信息
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//public class FuncType2BaseInfo implements NewMqttMessageRule {
|
||||
//
|
||||
// @Override
|
||||
// public String getCommandType() {
|
||||
// return "HBY100_2";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void execute(NewMqttRuleContext context) {
|
||||
// log.info("开始处理强制声光报警开关,消息负载:{}", context.getPayloadDict());
|
||||
//
|
||||
// try {
|
||||
// // 构建强制声光报警开关的Redis键
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":force_audio_visual_alarm_switch";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// // 存储强制声光报警开关状态到Redis
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
// log.info("强制声光报警开关处理完成,设备ID:{}", context.getDeviceImei());
|
||||
// } catch (Exception e) {
|
||||
// log.error("处理强制声光报警开关失败", e);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 获取设备位置信息(设备下发返回响应数据、设备定时主动上报)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType3Location implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_3";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J获取设备位置信息,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
context.getDeviceImei() + ":location";
|
||||
|
||||
Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
if (payloadDict != null) {
|
||||
RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J获取设备位置信息失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 获取设备电源状态(设备下发返回响应数据、设备定时主动上报)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType4PowerStatus implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_4";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J获取设备电源状态,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
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));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J获取设备电源状态失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 更新语音
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType5UpdateVoice implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_5";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J更新语音,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":updateVoice";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J更新语音失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 语音播报开启/关闭
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType6VoicePlay implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_9";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
log.info("HBY100J语音播报开启/关闭,消息负载:{}", context.getPayloadDict());
|
||||
|
||||
try {
|
||||
// String redisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX +
|
||||
// context.getDeviceImei() + ":VoicePlay";
|
||||
//
|
||||
// Map<String, Object> payloadDict = context.getPayloadDict();
|
||||
// if (payloadDict != null) {
|
||||
// RedisUtils.setCacheObject(redisKey, JSONObject.toJSONString(payloadDict));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J语音播报开启/关闭失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttMessageRule;
|
||||
import com.fuyuanshen.global.mqtt.base.NewMqttRuleContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
|
||||
|
||||
/**
|
||||
* 修改音量
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FuncType9UpdateVolume implements NewMqttMessageRule {
|
||||
|
||||
@Override
|
||||
public String getCommandType() {
|
||||
return "HBY100_9";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(NewMqttRuleContext context) {
|
||||
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));
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("HBY100J修改音量失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 爆闪模式开启/关闭
|
||||
* 对应 funcType="10"
|
||||
* mode:
|
||||
* 0 红色爆闪,1 蓝色爆闪,2 黄色爆闪,3,红色顺时针旋转爆闪,4黄色顺时针旋转爆闪,5,红蓝顺时针旋转爆闪,6 红蓝交替爆闪
|
||||
*/
|
||||
@Data
|
||||
public class FuncType10StrobeModeRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 爆闪模式是否启用
|
||||
* 0 - 禁用
|
||||
* 1 - 启用
|
||||
*/
|
||||
private Integer enable;
|
||||
/**
|
||||
* 爆闪模式类型 0 红色爆闪,1 蓝色爆闪,2 黄色爆闪,3,红色顺时针旋转爆闪,4黄色顺时针旋转爆闪,5,红蓝顺时针旋转爆闪,6 红蓝交替爆闪
|
||||
**/
|
||||
private Integer mode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 修改警示灯爆闪频率
|
||||
* 对应 funcType="11"
|
||||
*/
|
||||
@Data
|
||||
public class FuncType11FrequencyRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
//"frequency": 1-12
|
||||
private Integer frequency;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 强制声光报警开启/关闭
|
||||
* 对应 funcType="12"
|
||||
*/
|
||||
@Data
|
||||
public class FuncType12ForceAudioRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
/**
|
||||
* 语音报警0关闭,1开启
|
||||
*/
|
||||
private Integer voiceStrobeAlarm;
|
||||
//语音模式0公安,1消防,2应急,3交警,4市政,5铁路,6医疗,7部队,8水利
|
||||
private Integer mode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 警示灯LED亮度调节
|
||||
* 对应 funcType="13"
|
||||
*/
|
||||
@Data
|
||||
public class FuncType13BrightnessRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
/**
|
||||
* 红色LED亮度值0-100
|
||||
*/
|
||||
private Integer red;
|
||||
|
||||
/**
|
||||
* 蓝色LED亮度值0-100
|
||||
*/
|
||||
private Integer blue;
|
||||
|
||||
/**
|
||||
* 黄色LED亮度值0-100
|
||||
*/
|
||||
private Integer yellow;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,143 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备状态上报数据DTO
|
||||
* 对应MQTT消息中设备上报的完整状态数据结构
|
||||
*/
|
||||
@Data
|
||||
public class FuncType14StatusReport {
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码(如"14"表示特定功能指令)
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 响应状态码(如"200"表示成功)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 设备详细状态数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 设备详细状态数据内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 语音播报开关:0-关闭,1-开启
|
||||
*/
|
||||
@JsonProperty("voice_broadcast")
|
||||
private Integer voiceBroadcast;
|
||||
|
||||
/**
|
||||
* 警报器(警笛)设置
|
||||
*/
|
||||
@JsonProperty("siren_alarm")
|
||||
private SirenAlarm sirenAlarm;
|
||||
|
||||
/**
|
||||
* LED爆闪设置
|
||||
*/
|
||||
@JsonProperty("led_strobe")
|
||||
private LedStrobe ledStrobe;
|
||||
|
||||
/**
|
||||
* 音量设置(0-100范围)
|
||||
*/
|
||||
@JsonProperty("volume")
|
||||
private Integer volume;
|
||||
|
||||
/**
|
||||
* 亮度设置(RGB三色亮度值)
|
||||
*/
|
||||
@JsonProperty("brightness")
|
||||
private Brightness brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* 警报器(警笛)设置
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class SirenAlarm {
|
||||
|
||||
/**
|
||||
* 是否启用:0-禁用,1-启用
|
||||
*/
|
||||
@JsonProperty("enable")
|
||||
private Integer enable;
|
||||
|
||||
/**
|
||||
* 工作模式:0-默认模式,其他值表示不同报警模式
|
||||
*/
|
||||
@JsonProperty("mode")
|
||||
private Integer mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* LED爆闪设置
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class LedStrobe {
|
||||
|
||||
/**
|
||||
* 是否启用:0-禁用,1-启用
|
||||
*/
|
||||
@JsonProperty("enable")
|
||||
private Integer enable;
|
||||
|
||||
/**
|
||||
* 工作模式:0-默认模式,其他值表示不同爆闪模式
|
||||
*/
|
||||
@JsonProperty("mode")
|
||||
private Integer mode;
|
||||
|
||||
/**
|
||||
* 爆闪频率(单位:Hz或自定义单位)
|
||||
*/
|
||||
@JsonProperty("frequency")
|
||||
private Integer frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* 亮度设置(RGB三色)
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Brightness {
|
||||
|
||||
/**
|
||||
* 红色通道亮度值(0-255或百分比)
|
||||
*/
|
||||
@JsonProperty("red")
|
||||
private Integer red;
|
||||
|
||||
/**
|
||||
* 绿色通道亮度值(0-255或百分比)
|
||||
*/
|
||||
@JsonProperty("green")
|
||||
private Integer green;
|
||||
|
||||
/**
|
||||
* 蓝色通道亮度值(0-255或百分比)
|
||||
*/
|
||||
@JsonProperty("blue")
|
||||
private Integer blue;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 更新设备语音
|
||||
*/
|
||||
@Data
|
||||
public class FuncType5UpdateVoiceReport {
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码("5" 表示操作状态上报)
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 响应状态码("200" 表示请求成功)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 操作详细状态数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 操作状态数据内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 操作执行状态:
|
||||
* 0 - 未开始 / 失败
|
||||
* 1 - 执行中
|
||||
* 2 - 成功完成
|
||||
* (具体含义需结合业务协议定义)
|
||||
*/
|
||||
@JsonProperty("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 操作进度百分比(0-100),仅在 status=1(执行中)时有效
|
||||
*/
|
||||
@JsonProperty("progress")
|
||||
private Integer progress;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 语音资源配置请求DTO
|
||||
* 对应 funcType="5" 的语音资源下发指令(如语音播报文件配置)
|
||||
*/
|
||||
@Data
|
||||
public class FuncType5UpdateVoiceRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码("5" 表示语音资源配置)
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 语音类型:
|
||||
* 0 - 默认语音(如标准提示音)
|
||||
* 1 - 自定义语音
|
||||
* 2 - 紧急语音
|
||||
* (具体含义需依据设备协议定义)
|
||||
*/
|
||||
private Integer voiceType;
|
||||
|
||||
/**
|
||||
* 语音资源URL(MP3等音频文件地址)
|
||||
* 示例:http://8.129.5.250:10001/voice/01.mp3
|
||||
*/
|
||||
private String voiceResource;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 语音播报开启/关闭
|
||||
* 对应 funcType="6"
|
||||
*/
|
||||
@Data
|
||||
public class FuncType6VoicePlayRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
/**
|
||||
* 语音报警0关闭,1开启
|
||||
*/
|
||||
private Integer voiceBroadcast;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 修改音量
|
||||
* 对应 funcType="9"
|
||||
*/
|
||||
@Data
|
||||
public class FuncType9UpdateVolumeRequest {
|
||||
|
||||
/**
|
||||
* 请求唯一标识符(用于链路追踪或幂等处理)
|
||||
*/
|
||||
@JsonProperty("requestId")
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 语音配置数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 语音配置详情内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
//"volume": 1-100(app端可根据需求把40作为低音量, 70作为中音量,100作为高音量)
|
||||
private Integer volume;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备位置上报DTO
|
||||
* 对应MQTT消息中设备上报的地理位置数据
|
||||
*/
|
||||
@Data
|
||||
public class FunctionType3LocationReport {
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码(如"3"表示位置上报)
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 响应状态码(如"200"表示成功)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 位置详细数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 位置详细数据内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 经度(WGS-84坐标系,如22.543100)
|
||||
*/
|
||||
@JsonProperty("longitude")
|
||||
private Double longitude;
|
||||
|
||||
/**
|
||||
* 纬度(WGS-84坐标系,如114.057900)
|
||||
*/
|
||||
@JsonProperty("latitude")
|
||||
private Double latitude;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.fuyuanshen.global.mqtt.rule.hby100j.domin;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备电源状态上报DTO
|
||||
* 对应MQTT消息中设备上报的电源相关状态数据
|
||||
*/
|
||||
@Data
|
||||
public class FunctionType4PowerStatusReport {
|
||||
|
||||
/**
|
||||
* 设备IMEI号(国际移动设备识别码)
|
||||
*/
|
||||
private String imei;
|
||||
|
||||
/**
|
||||
* 功能类型编码(如"4"表示电源状态上报)
|
||||
*/
|
||||
private String funcType;
|
||||
|
||||
/**
|
||||
* 响应状态码(如"200"表示成功)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 时间戳(毫秒级Unix时间戳)
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 电源详细状态数据
|
||||
*/
|
||||
private Data data;
|
||||
|
||||
/**
|
||||
* 电源详细状态数据内部类
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class Data {
|
||||
|
||||
/**
|
||||
* 电池容量(如"5000mAh")
|
||||
*/
|
||||
@JsonProperty("capacity")
|
||||
private String capacity;
|
||||
|
||||
/**
|
||||
* 电压值(单位:V,0表示未检测或无电)
|
||||
*/
|
||||
@JsonProperty("voltage")
|
||||
private Integer voltage;
|
||||
|
||||
/**
|
||||
* 电量百分比(0-100,0表示低电量或未检测)
|
||||
*/
|
||||
@JsonProperty("level")
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 充电状态:0-未充电,1-正在充电
|
||||
*/
|
||||
@JsonProperty("charge")
|
||||
private Integer charge;
|
||||
|
||||
/**
|
||||
* 12V电源状态:0-关闭/无输出,1-开启/有输出
|
||||
*/
|
||||
@JsonProperty("12v_power")
|
||||
private Integer twelveVPower;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.fuyuanshen.global.mqtt.utils;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GenerateIdUtil {
|
||||
/**
|
||||
* 生成数字唯一ID - 基于UUID
|
||||
*/
|
||||
public static String generateNumericId() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
return Math.abs(uuid.toString().hashCode()) + "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成数字唯一ID - 基于时间戳+随机数
|
||||
*/
|
||||
public static long generateTimestampBasedId() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
int random = new Random().nextInt(1000); // 0-999随机数
|
||||
return timestamp * 1000 + random;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,340 @@
|
||||
package com.fuyuanshen.web.service.device;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.fuyuanshen.app.controller.device.bjq.AppDeviceHBY100JController;
|
||||
import com.fuyuanshen.app.domain.AppBusinessFile;
|
||||
import com.fuyuanshen.app.domain.AppPersonnelInfo;
|
||||
import com.fuyuanshen.app.domain.AppPersonnelInfoRecords;
|
||||
import com.fuyuanshen.app.domain.bo.AppBusinessFileBo;
|
||||
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.AppBusinessFileVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceHBY100JDetailVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
|
||||
import com.fuyuanshen.app.mapper.AppBusinessFileMapper;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
|
||||
import com.fuyuanshen.app.service.IAppBusinessFileService;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.core.domain.model.LoginUser;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.core.utils.*;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.common.satoken.utils.LoginHelper;
|
||||
import com.fuyuanshen.equipment.domain.Device;
|
||||
import com.fuyuanshen.equipment.domain.DeviceType;
|
||||
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
|
||||
import com.fuyuanshen.equipment.enums.LightModeEnum;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
|
||||
import com.fuyuanshen.global.mqtt.config.MqttGateway;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
|
||||
import com.fuyuanshen.global.mqtt.rule.hby100j.domin.*;
|
||||
import com.fuyuanshen.global.mqtt.utils.GenerateIdUtil;
|
||||
import com.fuyuanshen.system.domain.SysOss;
|
||||
import com.fuyuanshen.system.domain.vo.SysOssVo;
|
||||
import com.fuyuanshen.system.mapper.SysOssMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
|
||||
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.buildArr;
|
||||
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.generateFixedBitmapData;
|
||||
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
|
||||
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceHBY100JBizService {
|
||||
|
||||
private final DeviceMapper deviceMapper;
|
||||
private final DeviceTypeMapper deviceTypeMapper;
|
||||
private final MqttGateway mqttGateway;
|
||||
private final DeviceLogMapper deviceLogMapper;
|
||||
private final IAppBusinessFileService appBusinessFileService;
|
||||
private final AppBusinessFileMapper appBusinessFileMapper;
|
||||
private final SysOssMapper sysOssMapper;
|
||||
|
||||
|
||||
private static final String DEVICE_TYPE = "HBY100/";
|
||||
/**
|
||||
* 记录设备操作日志
|
||||
*
|
||||
* @param deviceId 设备ID
|
||||
* @param content 日志内容
|
||||
* @param operator 操作人
|
||||
*/
|
||||
private void recordDeviceLog(Long deviceId, String deviceName, String deviceAction, String content, Long operator) {
|
||||
try {
|
||||
// 创建设备日志实体
|
||||
com.fuyuanshen.equipment.domain.DeviceLog deviceLog = new com.fuyuanshen.equipment.domain.DeviceLog();
|
||||
deviceLog.setDeviceId(deviceId);
|
||||
deviceLog.setDeviceAction(deviceAction);
|
||||
deviceLog.setContent(content);
|
||||
deviceLog.setCreateBy(operator);
|
||||
deviceLog.setDeviceName(deviceName);
|
||||
deviceLog.setCreateTime(new Date());
|
||||
|
||||
// 插入日志记录
|
||||
deviceLogMapper.insert(deviceLog);
|
||||
} catch (Exception e) {
|
||||
log.error("记录设备操作日志失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AppDeviceHBY100JDetailVo getInfo(Long id) {
|
||||
Device device = deviceMapper.selectById(id);
|
||||
if (device == null) {
|
||||
throw new RuntimeException("请先将设备入库!!!");
|
||||
}
|
||||
|
||||
AppDeviceHBY100JDetailVo vo = new AppDeviceHBY100JDetailVo();
|
||||
vo.setDeviceId(device.getId());
|
||||
vo.setDeviceName(device.getDeviceName());
|
||||
vo.setDevicePic(device.getDevicePic());
|
||||
vo.setDeviceImei(device.getDeviceImei());
|
||||
vo.setDeviceMac(device.getDeviceMac());
|
||||
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
|
||||
if (deviceType != null) {
|
||||
vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
|
||||
vo.setTypeName(deviceType.getTypeName());
|
||||
}
|
||||
vo.setBluetoothName(device.getBluetoothName());
|
||||
|
||||
// 设备在线状态
|
||||
String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
|
||||
// 设备在线状态
|
||||
if ("1".equals(onlineStatus)) {
|
||||
vo.setOnlineStatus(1);
|
||||
} else if ("2".equals(onlineStatus)) {
|
||||
vo.setOnlineStatus(2);
|
||||
} 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"));
|
||||
} else {
|
||||
vo.setBatteryPercentage("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 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 lightBrightness = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX);
|
||||
if (StringUtils.isNotBlank(lightBrightness)) {
|
||||
vo.setLightBrightness(lightBrightness);
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
||||
private boolean getDeviceStatus(String deviceImei) {
|
||||
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
|
||||
return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null;
|
||||
}
|
||||
|
||||
|
||||
public void forceAlarmActivation(AppDeviceHBY100JController.HBY100JForceAlarmActivationDto bo) {
|
||||
List<Long> deviceIds = bo.getDeviceIds();
|
||||
if (deviceIds == null || deviceIds.isEmpty()) {
|
||||
throw new ServiceException("请选择设备");
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
// recordDeviceLog(deviceId, deviceObj.getDeviceName(), "强制报警激活", "强制报警激活", loginUser.getUserId());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void updateVoice(AppDeviceHBY100JController.HBY100JUpdateVoiceDto dto) {
|
||||
AppBusinessFileVo appBusinessFileVo = appBusinessFileMapper.selectVoById(dto.getId());
|
||||
if(appBusinessFileVo == null){
|
||||
throw new ServiceException("文件不存在");
|
||||
}
|
||||
Device deviceObj = deviceMapper.selectById(appBusinessFileVo.getBusinessId());
|
||||
// if (getDeviceStatus(deviceObj.getDeviceImei())) {
|
||||
// throw new ServiceException(deviceObj.getDeviceName() + ",设备已断开连接");
|
||||
// }
|
||||
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
SysOssVo sysOssVo = sysOssMapper.selectVoById(appBusinessFileVo.getFileId());
|
||||
FuncType5UpdateVoiceRequest request = new FuncType5UpdateVoiceRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("5");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType5UpdateVoiceRequest.Data data = new FuncType5UpdateVoiceRequest.Data();
|
||||
data.setVoiceResource(sysOssVo.getUrl());
|
||||
data.setVoiceType(0);
|
||||
request.setData(data);
|
||||
log.info("HBY100J更新语音,参数:{}", request);
|
||||
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
|
||||
UpdateWrapper<AppBusinessFile> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("business_id", appBusinessFileVo.getBusinessId());
|
||||
updateWrapper.set("use_status", 0);
|
||||
appBusinessFileMapper.update(updateWrapper);
|
||||
|
||||
UpdateWrapper<AppBusinessFile> updateWrapper2 = new UpdateWrapper<>();
|
||||
updateWrapper2.eq("id", appBusinessFileVo.getId());
|
||||
updateWrapper2.set("use_status", 1);
|
||||
appBusinessFileMapper.update(updateWrapper2);
|
||||
}
|
||||
|
||||
private String buildMqttTopic(String deviceImei) {
|
||||
String tenantId = LoginHelper.getTenantId();
|
||||
return MqttConstants.GLOBAL_PUB_KEY2 +tenantId + "/" + DEVICE_TYPE + deviceImei;
|
||||
}
|
||||
|
||||
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() + ",设备已断开连接");
|
||||
// }
|
||||
FuncType10StrobeModeRequest request = new FuncType10StrobeModeRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("10");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType10StrobeModeRequest.Data data = new FuncType10StrobeModeRequest.Data();
|
||||
data.setMode(params.getMode());
|
||||
data.setEnable(params.getEnable());
|
||||
request.setData(data);
|
||||
log.info("HBY100J爆闪模式开启/关闭,下发设备参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
|
||||
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() + ",设备已断开连接");
|
||||
// }
|
||||
FuncType13BrightnessRequest request = new FuncType13BrightnessRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("13");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType13BrightnessRequest.Data data = new FuncType13BrightnessRequest.Data();
|
||||
data.setRed(params.getBrightness());
|
||||
data.setBlue(params.getBrightness());
|
||||
data.setYellow(params.getBrightness());
|
||||
request.setData(data);
|
||||
log.info("HBY100J灯光调节,下发设备参数:{}", request);
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
|
||||
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() + ",设备已断开连接");
|
||||
// }
|
||||
FuncType11FrequencyRequest request = new FuncType11FrequencyRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("11");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType11FrequencyRequest.Data data = new FuncType11FrequencyRequest.Data();
|
||||
data.setFrequency(params.getFrequency());
|
||||
request.setData(data);
|
||||
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() + ",设备已断开连接");
|
||||
// }
|
||||
FuncType9UpdateVolumeRequest request = new FuncType9UpdateVolumeRequest();
|
||||
request.setRequestId(GenerateIdUtil.generateNumericId());
|
||||
request.setImei(deviceObj.getDeviceImei());
|
||||
request.setFuncType("9");
|
||||
request.setTimestamp(System.currentTimeMillis());
|
||||
FuncType9UpdateVolumeRequest.Data data = new FuncType9UpdateVolumeRequest.Data();
|
||||
data.setVolume(params.getVolume());
|
||||
request.setData(data);
|
||||
log.info("HBY100J更新音量,下发设备参数:{}", JSON.toJSONString(request));
|
||||
mqttGateway.sendMsgToMqtt(buildMqttTopic(deviceObj.getDeviceImei()), 1, JSON.toJSONString(request));
|
||||
}
|
||||
}
|
||||
@ -279,11 +279,13 @@ justauth:
|
||||
# MQTT配置
|
||||
mqtt:
|
||||
username: admin
|
||||
password: fys123456
|
||||
url: tcp://47.107.152.87:1883
|
||||
password: #YtvpSfCNG
|
||||
url: tcp://47.120.79.150:2883
|
||||
subClientId: fys_subClient
|
||||
subTopic: A/#,status/tenantCode/#,report/tenantCode/#
|
||||
pubTopic: B/#,command/tenantCode/#
|
||||
subTopic: A/#
|
||||
pubTopic: B/#
|
||||
subTopic2: command/894078/#
|
||||
pubTopic2: status/894078/#
|
||||
pubClientId: fys_pubClient
|
||||
|
||||
|
||||
|
||||
@ -283,14 +283,16 @@ mqtt:
|
||||
password: #YtvpSfCNG
|
||||
url: tcp://47.120.79.150:3883
|
||||
subClientId: fys_subClient
|
||||
subTopic: A/#,status/tenantCode/#,report/tenantCode/#
|
||||
pubTopic: B/#,command/tenantCode/#
|
||||
subTopic: A/#
|
||||
pubTopic: B/#
|
||||
subTopic2: status/894078/#
|
||||
pubTopic2: command/894078/#
|
||||
pubClientId: fys_pubClient
|
||||
|
||||
# TTS语音交互配置
|
||||
alibaba:
|
||||
tts:
|
||||
appKey: KTwSUKMrf2olFfjC
|
||||
akId: LTAI5t6RsfCvQh57qojzbEoe
|
||||
akSecret: MTqvK2mXYeCRkl1jVPndiNumyaad0R
|
||||
appKey: lbGuq5K5bEH4uxmT
|
||||
akId: LTAI5t66moCkhNC32TDJ5ReP
|
||||
akSecret: 2F3sdoBJ08bYvJcuDgSkLnJwGXsvYH
|
||||
|
||||
|
||||
@ -39,8 +39,8 @@ public class EncryptUtilsTest {
|
||||
loginBody.setClientId("e5cd7e4891bf95d1d19206ce24a7b32e");
|
||||
loginBody.setGrantType("password");
|
||||
loginBody.setTenantId("894078");
|
||||
loginBody.setCode("15");
|
||||
loginBody.setUuid("28ecf3d396ce4e6db8eb414992235fad");
|
||||
loginBody.setCode("6");
|
||||
loginBody.setUuid("399d45194f3d4c7e9cbfb3294b198a9b");
|
||||
// loginBody.setUsername("admin");
|
||||
// loginBody.setPassword("admin123");
|
||||
loginBody.setUsername("dyf");
|
||||
|
||||
@ -47,5 +47,18 @@ public class AppBusinessFile extends TenantEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 文件时长
|
||||
*/
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* 重命名
|
||||
*/
|
||||
private String reName;
|
||||
|
||||
/**
|
||||
* 是否使用语音播报(0-否,1-是)
|
||||
*/
|
||||
private Integer useStatus;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ public class AppBusinessFileBo extends BaseEntity {
|
||||
private Long businessId;
|
||||
|
||||
/**
|
||||
* 文件类型(1:操作说明,2:产品参数)
|
||||
* 文件类型(1:操作说明,2:产品参数,3:语音管理)
|
||||
*/
|
||||
private Long fileType;
|
||||
|
||||
@ -49,4 +49,11 @@ public class AppBusinessFileBo extends BaseEntity {
|
||||
|
||||
|
||||
private List<Long> ids;
|
||||
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* 是否使用语音播报(0-否,1-是)
|
||||
*/
|
||||
private Integer useStatus;
|
||||
}
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
package com.fuyuanshen.app.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class AppDeviceHBY100JDetailVo implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
@ExcelProperty(value = "设备ID")
|
||||
private Long deviceId;
|
||||
|
||||
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 设备IMEI
|
||||
*/
|
||||
private String deviceImei;
|
||||
|
||||
/**
|
||||
* 设备MAC
|
||||
*/
|
||||
private String deviceMac;
|
||||
|
||||
/**
|
||||
* 通讯方式 0:4G;1:蓝牙,2 4G&蓝牙
|
||||
*/
|
||||
private Integer communicationMode;
|
||||
|
||||
/**
|
||||
* 设备图片
|
||||
*/
|
||||
private String devicePic;
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 蓝牙名称
|
||||
*/
|
||||
private String bluetoothName;
|
||||
|
||||
//电量百分比
|
||||
private String batteryPercentage;
|
||||
|
||||
//充电状态(0没有充电,1正在充电,2为已充满)
|
||||
private String chargeState;
|
||||
|
||||
/**
|
||||
* 在线状态(0离线,1在线)
|
||||
*/
|
||||
private Integer onlineStatus;
|
||||
|
||||
// 经度
|
||||
private String longitude;
|
||||
|
||||
// 纬度
|
||||
private String latitude;
|
||||
|
||||
// 逆解析地址
|
||||
private String address;
|
||||
|
||||
// 亮度
|
||||
private String lightBrightness;
|
||||
|
||||
// 音量
|
||||
private Integer volume;
|
||||
|
||||
|
||||
/**
|
||||
* 语音资源URL(MP3等音频文件地址)
|
||||
*/
|
||||
private String voiceResource;
|
||||
|
||||
// 报警模式 0公安,1 消防,2应急,3交警,4 市政,5 铁路,6 医疗,7 部队,8 水利,9 语音
|
||||
private String alarmMode;
|
||||
|
||||
// 强制报警开关: 0 关闭, 1开启
|
||||
private String voiceStrobeAlarm;
|
||||
|
||||
/**
|
||||
* 0 红色爆闪,1 蓝色爆闪,2 黄色爆闪,3,红色顺时针旋转爆闪,4黄色顺时针旋转爆闪,5,红蓝顺时针旋转爆闪,6 红蓝交替爆闪
|
||||
*/
|
||||
private Integer strobeMode;
|
||||
|
||||
/**
|
||||
* 爆闪频率
|
||||
*/
|
||||
private Integer strobeFrequency;
|
||||
|
||||
}
|
||||
@ -51,6 +51,11 @@ public class AppDeviceShareVo implements Serializable {
|
||||
@ExcelProperty(value = "设备名称")
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 设备mac地址
|
||||
*/
|
||||
private String deviceMac;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
|
||||
@ -27,4 +27,16 @@ public class AppFileVo {
|
||||
* 文件url
|
||||
*/
|
||||
private String fileUrl;
|
||||
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* 扩展文件名称
|
||||
*/
|
||||
private String fileNameExt;
|
||||
|
||||
/***
|
||||
* 是否使用语音播报(0-否,1-是)
|
||||
*/
|
||||
private Integer useStatus;
|
||||
}
|
||||
|
||||
@ -78,4 +78,5 @@ public interface IAppBusinessFileService {
|
||||
|
||||
|
||||
List<AppFileVo> queryAppFileList(AppBusinessFileBo bo);
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<mapper namespace="com.fuyuanshen.app.mapper.AppBusinessFileMapper">
|
||||
|
||||
<select id="queryAppFileList" resultType="com.fuyuanshen.app.domain.vo.AppFileVo">
|
||||
select a.id,a.business_id,a.file_id,a.file_type,b.file_name,b.url fileUrl from app_business_file a left join sys_oss b on a.file_id = b.oss_id
|
||||
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
|
||||
SUBSTRING_INDEX(COALESCE(a.re_name, b.original_name), '.', 1)
|
||||
ELSE
|
||||
a.re_name
|
||||
END AS fileNameExt,a.use_status
|
||||
from app_business_file a left join sys_oss b on a.file_id = b.oss_id
|
||||
where 1=1
|
||||
<if test="businessId != null">
|
||||
and a.business_id = #{businessId}
|
||||
|
||||
@ -16,10 +16,8 @@ import com.fuyuanshen.customer.domain.vo.ConsumerVo;
|
||||
import com.fuyuanshen.customer.mapper.CustomerMapper;
|
||||
import com.fuyuanshen.customer.service.CustomerService;
|
||||
import com.fuyuanshen.system.domain.SysUserRole;
|
||||
import com.fuyuanshen.system.domain.bo.SysUserBo;
|
||||
import com.fuyuanshen.system.mapper.SysRoleMapper;
|
||||
import com.fuyuanshen.system.mapper.SysUserRoleMapper;
|
||||
import com.fuyuanshen.system.service.ISysUserService;
|
||||
import com.fuyuanshen.system.service.impl.SysUserServiceImpl;
|
||||
import io.undertow.util.BadRequestException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@ -18,6 +18,12 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org</groupId>
|
||||
<artifactId>jaudiotagger</artifactId>
|
||||
<version>2.0.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>com.fuyuanshen</groupId> -->
|
||||
<!-- <artifactId>fys-app</artifactId> -->
|
||||
|
||||
@ -10,32 +10,36 @@ import lombok.EqualsAndHashCode;
|
||||
/**
|
||||
* 设备维修图片对象 device_repair_images
|
||||
*
|
||||
*
|
||||
* @date 2025-09-02
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("device_repair_images")
|
||||
public class DeviceRepairImages extends TenantEntity {
|
||||
|
||||
/**
|
||||
* 维修图片ID
|
||||
*/
|
||||
@TableId(value = "image_id", type = IdType.AUTO)
|
||||
@TableField(insertStrategy = FieldStrategy.NEVER)
|
||||
private Long imageId;
|
||||
|
||||
/**
|
||||
* 维修记录ID
|
||||
*/
|
||||
@Schema(title = "维修记录ID")
|
||||
private Long recordId;
|
||||
|
||||
/**
|
||||
* 图片类型(维修前/维修后)
|
||||
*/
|
||||
@Schema(title = "图片类型(维修前/维修后)")
|
||||
private RepairImageType imageType;
|
||||
|
||||
/**
|
||||
* 图片存储路径
|
||||
*/
|
||||
@Schema(title = "图片存储路径")
|
||||
private String imageUrl;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package com.fuyuanshen.equipment.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 绑定设备参数
|
||||
*/
|
||||
@Data
|
||||
public class Hby100jForceAlarmBo {
|
||||
|
||||
private Long deviceId;
|
||||
|
||||
|
||||
}
|
||||
@ -244,10 +244,10 @@ public class DeviceTypeServiceImpl extends ServiceImpl<DeviceTypeMapper, DeviceT
|
||||
throw new RuntimeException("设备类型不存在");
|
||||
}
|
||||
|
||||
if (!deviceType.getTypeName().equals(resources.getTypeName())) {
|
||||
if (!deviceType.getTypeName().equals(resources.getTypeName()) || !deviceType.getAppModelDictionary().equals(resources.getAppModelDictionary())) {
|
||||
int count = deviceMapper.countByDeviceTypeId(deviceType.getId());
|
||||
if (count > 0) {
|
||||
throw new RuntimeException("该设备类型下已有设备,无法修改设备类型名称!!!");
|
||||
throw new RuntimeException("该设备类型下已有设备,无法修改设备类型名称和路由跳转!!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -113,6 +113,21 @@ public class AlibabaTTSUtil {
|
||||
DEFAULT_VOLUME, DEFAULT_SPEECH_RATE, DEFAULT_PITCH_RATE);
|
||||
}
|
||||
|
||||
public byte[] synthesizeTextToMp3(String text){
|
||||
try {
|
||||
// 获取访问令牌
|
||||
String token = getValidAccessToken();
|
||||
// 使用HTTP方式调用
|
||||
HttpTtsClient httpClient = new HttpTtsClient(appkey,token);
|
||||
|
||||
return httpClient.synthesizeTextToMp3(text);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成语音文件 - 完整版(支持所有参数调节)
|
||||
*
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package com.fuyuanshen.equipment.utils;
|
||||
|
||||
import com.alibaba.nls.client.AccessToken;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import static cn.dev33.satoken.SaManager.log;
|
||||
|
||||
public class HttpTtsClient {
|
||||
|
||||
private String appKey;
|
||||
private String token;
|
||||
/**
|
||||
* 阿里云TTS服务基础URL
|
||||
*/
|
||||
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;
|
||||
this.token = token;
|
||||
}
|
||||
/**
|
||||
* 使用HTTP POST方式调用阿里云TTS服务生成MP3格式语音
|
||||
*/
|
||||
public byte[] synthesizeTextToMp3(String text) 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("\"", "\\\"")
|
||||
// );
|
||||
String requestBody = " {\n" +
|
||||
" \"appkey\":\""+appKey+"\",\n" +
|
||||
" \"text\":\""+text+"\",\n" +
|
||||
" \"token\":\""+token+"\",\n" +
|
||||
" \"format\":\"mp3\"\n" +
|
||||
" }";
|
||||
|
||||
URL url = new URL(endpoint);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
|
||||
// 设置请求方法和头部
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
// conn.setRequestProperty("Authorization", buildAuthorization());
|
||||
conn.setRequestProperty("Content-Length", String.valueOf(requestBody.getBytes().length));
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// 发送请求体
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(requestBody.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
// 读取响应
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
// 读取音频数据
|
||||
try (InputStream is = conn.getInputStream()) {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
int nRead;
|
||||
byte[] data = new byte[1024];
|
||||
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
} else {
|
||||
throw new IOException("HTTP请求失败,状态码: " + responseCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存MP3到文件
|
||||
*/
|
||||
public String saveMp3ToFile(String text, String outputPath) throws IOException {
|
||||
byte[] mp3Data = synthesizeTextToMp3(text);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
||||
fos.write(mp3Data);
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.fuyuanshen.equipment.utils;
|
||||
|
||||
import org.jaudiotagger.audio.AudioFileIO;
|
||||
import org.jaudiotagger.audio.mp3.MP3File;
|
||||
import java.io.File;
|
||||
|
||||
public class Mp3Duration {
|
||||
|
||||
/**
|
||||
* 获取MP3文件的播放时长(秒)
|
||||
*
|
||||
* @param filePath MP3文件路径
|
||||
* @return 播放时长(秒)
|
||||
*/
|
||||
public static int getMp3Duration(String filePath) {
|
||||
try {
|
||||
File file = new File(filePath);
|
||||
MP3File mp3File = (MP3File) AudioFileIO.read(file);
|
||||
return mp3File.getMP3AudioHeader().getTrackLength();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return -1; // 错误时返回-1
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String filePath = "D:\\http_output.mp3"; // 替换为实际路径
|
||||
int duration = getMp3Duration(filePath);
|
||||
if (duration != -1) {
|
||||
System.out.println("MP3时长: " + duration + " 秒");
|
||||
} else {
|
||||
System.out.println("无法获取MP3时长");
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
qrcode.png
Normal file
BIN
qrcode.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Reference in New Issue
Block a user