Compare commits
No commits in common. "af02378f959717b79ba3a602f900ac71dee7b940" and "88021b2912467e9921a5755cc5efdf9c2d6d1db9" have entirely different histories.
af02378f95
...
88021b2912
62
.trae/documents/保存单体电压_温度与充放电量到对应表.md
Normal file
62
.trae/documents/保存单体电压_温度与充放电量到对应表.md
Normal file
@ -0,0 +1,62 @@
|
||||
## 目标
|
||||
- 将 `MqttService` 中解析的三类数据按实体模型入库:
|
||||
- 单体电压数据 → 表 `subsystem_voltage`
|
||||
- 单体温度数据 → 表 `subsystem_temperature`
|
||||
- 累计充/放电量 → 新增表(如 `charge_discharge_summary`)
|
||||
|
||||
## 现状与模型
|
||||
- 单体电压解析位于 `src/main/java/com/evobms/project/bms/service/MqttService.java:257-265`,具体方法在 `parseCellVoltageAtIndex` 与 `parseCellVoltagesDetail`。
|
||||
- 领域模型:`SubsystemVoltage`(`src/main/java/com/evobms/project/Battery/domain/SubsystemVoltage.java`)
|
||||
- Mapper/XML:`SubsystemVoltageMapper` 与 `mybatis/voltage/SubsystemVoltageMapper.xml`
|
||||
- 单体温度解析位于 `parseCellTemperatureAtIndex` 与 `parseCellTemperaturesDetail`。
|
||||
- 领域模型:`SubsystemTemperature`(`src/main/java/com/evobms/project/Battery/domain/SubsystemTemperature.java`)
|
||||
- Mapper/XML:`SubsystemTemperatureMapper` 与 `mybatis/temperature/SubsystemTemperatureMapper.xml`
|
||||
- 累计充/放电量解析在 `parseChargeDischargeAtIndex`,目前 `saveChargeDischargeSummary(...)` 空实现,代码库未定义实体与表。
|
||||
|
||||
## 字段映射
|
||||
- 电压(来自 `parseCellVoltageAtIndex`)
|
||||
- `device_id` ⇔ 设备 SN
|
||||
- `timestamp` ⇔ `new Date()`
|
||||
- `subsystem_count` ⇔ 索引77
|
||||
- `subsystem_no` ⇔ 索引78
|
||||
- `subsystem_voltage` ⇔ 索引79-80 ×0.1V
|
||||
- `subsystem_current` ⇔ 索引81-82 (值-10000)×0.1A
|
||||
- `total_battery_count` ⇔ 索引83-84
|
||||
- `frame_start_battery_no` ⇔ 索引85-86
|
||||
- `frame_battery_count` ⇔ 索引87
|
||||
- `battery_voltages` ⇔ 从 `parseCellVoltagesDetail` 得到列表,按 "," 连接为字符串(mV→V)
|
||||
- 温度(来自 `parseCellTemperatureAtIndex`)
|
||||
- `device_id`、`timestamp`
|
||||
- `subsystem_count` ⇔ 索引449
|
||||
- `subsystem_no` ⇔ 索引450
|
||||
- `temp_probe_count` ⇔ 索引451-452
|
||||
- `temperature_values` ⇔ 从 `parseCellTemperaturesDetail` 得到列表(字节-40℃),按 "," 连接为字符串
|
||||
- 充/放电汇总(来自 `parseChargeDischargeAtIndex`)
|
||||
- 建议新增实体 `ChargeDischargeSummary`:`device_id`, `timestamp`, `discharge_kwh`, `charge_kwh`, 审计字段
|
||||
|
||||
## 实施步骤
|
||||
1. 在 `MqttService` 注入服务
|
||||
- `ISubsystemVoltageService`、`ISubsystemTemperatureService`
|
||||
2. 电压数据保存
|
||||
- 调整 `parseCellVoltagesDetail(byte[], start, deviceSn, startCellIndex, cellCount)` 返回 `List<Double>`(以 V 为单位)
|
||||
- 在 `parseCellVoltageAtIndex(...)` 构造 `SubsystemVoltage`:填充映射字段与 `battery_voltages`(以 "," 连接),调用 `ISubsystemVoltageService.insertSubsystemVoltage(...)`
|
||||
3. 温度数据保存
|
||||
- 调整 `parseCellTemperaturesDetail(byte[], start, deviceSn, tempCount)` 返回 `List<Integer>`(单位 ℃)
|
||||
- 在 `parseCellTemperatureAtIndex(...)` 构造 `SubsystemTemperature`:填充映射字段与 `temperature_values`(以 "," 连接),调用 `ISubsystemTemperatureService.insertSubsystemTemperature(...)`
|
||||
4. 累计充/放电量持久化
|
||||
- 新增实体、Mapper、XML、Service(命名示例:`ChargeDischargeSummary`、`ChargeDischargeSummaryMapper`、`ChargeDischargeSummaryServiceImpl`)
|
||||
- 在 `saveChargeDischargeSummary(deviceSn, dischargeKwh, chargeKwh)` 构造实体并插入
|
||||
5. 审计字段
|
||||
- 为入库对象设置 `create_time`(使用 `BaseEntity.setCreateTime(new Date())`),`create_by` 设置为设备 SN
|
||||
|
||||
## 校验与兼容
|
||||
- 编译并运行现有单元/集成测试,确保构建成功
|
||||
- 注意 `SubsystemTemperatureMapper.xml` 中 `updatedTime` 属性命名与 `BaseEntity.updateTime` 不一致,当前插入流程不依赖该字段,可后续统一为 `updateTime`
|
||||
|
||||
## 变更点位
|
||||
- `MqttService.java:257-265` 处的三个解析方法内新增调用保存方法
|
||||
- 新增或调整的私有方法:`saveSubsystemVoltage(...)`、`saveSubsystemTemperature(...)`、完善 `saveChargeDischargeSummary(...)`
|
||||
- 新实体与持久化文件(仅用于充/放电汇总)按上述命名与目录创建
|
||||
|
||||
## 交付结果
|
||||
- 三类数据均入库,对应后台列表页可查询;极值数据已按此前改造保持一致风格
|
||||
8
.vite/deps/_metadata.json
Normal file
8
.vite/deps/_metadata.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"hash": "764c59fb",
|
||||
"configHash": "64491d45",
|
||||
"lockfileHash": "e3b0c442",
|
||||
"browserHash": "4636522a",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
||||
3
.vite/deps/package.json
Normal file
3
.vite/deps/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +1,4 @@
|
||||
{
|
||||
"java.compile.nullAnalysis.mode": "automatic"
|
||||
"java.compile.nullAnalysis.mode": "automatic",
|
||||
"java.configuration.updateBuildConfiguration": "interactive"
|
||||
}
|
||||
50
README.md
50
README.md
@ -42,53 +42,3 @@
|
||||
16. 缓存监控:对系统的缓存信息查询,命令统计等。
|
||||
17. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||
|
||||
## 在线体验
|
||||
|
||||
- admin/admin123
|
||||
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
||||
|
||||
演示地址:http://vue.ruoyi.vip
|
||||
文档地址:http://doc.ruoyi.vip
|
||||
|
||||
## 演示图
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## 若依前后端分离交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) 点击按钮入群。
|
||||
Binary file not shown.
138
ota/1.1.1.bin
Normal file
138
ota/1.1.1.bin
Normal file
@ -0,0 +1,138 @@
|
||||
```
|
||||
String finalNickName = currentUserNickName;
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
if (uploadFile != null && uploadFile.exists()) {
|
||||
String planUserIds = dingTalkProperties.getPlanUserId();
|
||||
if (StringUtils.isNotBlank(planUserIds)) {
|
||||
String mediaId = mediaService.uploadMedia("file", uploadFile.getAbsolutePath());
|
||||
// 支持多人推送,假设多个 userId 以逗号分隔
|
||||
String[] userIds = planUserIds.split(",");
|
||||
for (String userId : userIds) {
|
||||
String cleanUserId = userId.trim();
|
||||
if (StringUtils.isNotBlank(cleanUserId)) {
|
||||
try {
|
||||
robotGroupService.sendFileToUser(cleanUserId, mediaId, originalFilename);
|
||||
log.info("上传的工艺计划表已成功发送给用户: {}", cleanUserId);
|
||||
} catch (Exception e) {
|
||||
log.error("发送文件给用户 {} 异常", cleanUserId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("未配置钉钉工艺计划接收人(planUserId),跳过发送文件");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送文件给工艺计划接收人异常", e);
|
||||
} finally {
|
||||
if (uploadFile != null && uploadFile.exists()) {
|
||||
uploadFile.delete();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 发送文件给个人
|
||||
*
|
||||
* @param userId 接收人userId
|
||||
* @param mediaId 媒体文件ID
|
||||
* @param fileName 文件名
|
||||
* @return success
|
||||
*/
|
||||
public String sendFileToUser(String userId, String mediaId, String fileName) {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
|
||||
BatchSendOTOHeaders headers = new BatchSendOTOHeaders();
|
||||
headers.xAcsDingtalkAccessToken = tokenManager.getAccessToken();
|
||||
|
||||
String msgParam = String.format("{\"mediaId\":\"%s\",\"fileName\":\"%s\"}",
|
||||
mediaId, fileName);
|
||||
|
||||
BatchSendOTORequest request = new BatchSendOTORequest()
|
||||
.setRobotCode(properties.getRobotCode())
|
||||
.setUserIds(Arrays.asList(userId))
|
||||
.setMsgKey("sampleFile")
|
||||
.setMsgParam(msgParam);
|
||||
|
||||
client.batchSendOTOWithOptions(request, headers, new com.aliyun.teautil.models.RuntimeOptions());
|
||||
log.info("机器人个人文件发送成功, userId: {}, fileName: {}", userId, fileName);
|
||||
return "success";
|
||||
} catch (Exception e) {
|
||||
log.error("机器人个人文件发送失败", e);
|
||||
throw new DingException("机器人个人文件发送失败", e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 发送Markdown消息给个人 (批量单聊)
|
||||
*
|
||||
* @param userId 接收人userId
|
||||
* @param title 标题
|
||||
* @param text Markdown内容
|
||||
*/
|
||||
public void sendMarkdownToUser(String userId, String title, String text) {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
|
||||
BatchSendOTOHeaders headers = new BatchSendOTOHeaders();
|
||||
headers.xAcsDingtalkAccessToken = tokenManager.getAccessToken();
|
||||
|
||||
String msgParam = String.format("{\"title\":\"%s\",\"text\":\"%s\"}",
|
||||
title.replace("\"", "\\\""),
|
||||
text.replace("\"", "\\\"").replace("\n", "\\n"));
|
||||
|
||||
BatchSendOTORequest request = new BatchSendOTORequest()
|
||||
.setRobotCode(properties.getRobotCode())
|
||||
.setUserIds(Collections.singletonList(userId))
|
||||
.setMsgKey("sampleMarkdown")
|
||||
.setMsgParam(msgParam);
|
||||
|
||||
client.batchSendOTOWithOptions(request, headers, new RuntimeOptions());
|
||||
log.info("机器人个人Markdown消息发送成功, userId: {}, title: {}", userId, title);
|
||||
} catch (Exception e) {
|
||||
log.error("机器人个人Markdown消息发送失败", e);
|
||||
throw new DingException("机器人个人Markdown消息发送失败", e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 刷新AccessToken
|
||||
*/
|
||||
private void refresh() {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
GetAccessTokenRequest request = new GetAccessTokenRequest()
|
||||
.setAppKey(properties.getAppKey())
|
||||
.setAppSecret(properties.getAppSecret());
|
||||
|
||||
GetAccessTokenResponse response = client.getAccessToken(request);
|
||||
if (response.getBody() != null) {
|
||||
this.accessToken = response.getBody().getAccessToken();
|
||||
// 设置过期时间,提前100秒刷新
|
||||
this.expireTime = System.currentTimeMillis() + (response.getBody().getExpireIn() * 1000) - 100000;
|
||||
log.info("钉钉AccessToken刷新成功,过期时间: {}", this.expireTime);
|
||||
} else {
|
||||
throw new DingException("刷新AccessToken失败,返回为空");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("刷新钉钉AccessToken失败", e);
|
||||
throw new DingException("刷新钉钉AccessToken失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
```
|
||||
138
ota/2.2.0.bin
Normal file
138
ota/2.2.0.bin
Normal file
@ -0,0 +1,138 @@
|
||||
```
|
||||
String finalNickName = currentUserNickName;
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
if (uploadFile != null && uploadFile.exists()) {
|
||||
String planUserIds = dingTalkProperties.getPlanUserId();
|
||||
if (StringUtils.isNotBlank(planUserIds)) {
|
||||
String mediaId = mediaService.uploadMedia("file", uploadFile.getAbsolutePath());
|
||||
// 支持多人推送,假设多个 userId 以逗号分隔
|
||||
String[] userIds = planUserIds.split(",");
|
||||
for (String userId : userIds) {
|
||||
String cleanUserId = userId.trim();
|
||||
if (StringUtils.isNotBlank(cleanUserId)) {
|
||||
try {
|
||||
robotGroupService.sendFileToUser(cleanUserId, mediaId, originalFilename);
|
||||
log.info("上传的工艺计划表已成功发送给用户: {}", cleanUserId);
|
||||
} catch (Exception e) {
|
||||
log.error("发送文件给用户 {} 异常", cleanUserId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("未配置钉钉工艺计划接收人(planUserId),跳过发送文件");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送文件给工艺计划接收人异常", e);
|
||||
} finally {
|
||||
if (uploadFile != null && uploadFile.exists()) {
|
||||
uploadFile.delete();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 发送文件给个人
|
||||
*
|
||||
* @param userId 接收人userId
|
||||
* @param mediaId 媒体文件ID
|
||||
* @param fileName 文件名
|
||||
* @return success
|
||||
*/
|
||||
public String sendFileToUser(String userId, String mediaId, String fileName) {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
|
||||
BatchSendOTOHeaders headers = new BatchSendOTOHeaders();
|
||||
headers.xAcsDingtalkAccessToken = tokenManager.getAccessToken();
|
||||
|
||||
String msgParam = String.format("{\"mediaId\":\"%s\",\"fileName\":\"%s\"}",
|
||||
mediaId, fileName);
|
||||
|
||||
BatchSendOTORequest request = new BatchSendOTORequest()
|
||||
.setRobotCode(properties.getRobotCode())
|
||||
.setUserIds(Arrays.asList(userId))
|
||||
.setMsgKey("sampleFile")
|
||||
.setMsgParam(msgParam);
|
||||
|
||||
client.batchSendOTOWithOptions(request, headers, new com.aliyun.teautil.models.RuntimeOptions());
|
||||
log.info("机器人个人文件发送成功, userId: {}, fileName: {}", userId, fileName);
|
||||
return "success";
|
||||
} catch (Exception e) {
|
||||
log.error("机器人个人文件发送失败", e);
|
||||
throw new DingException("机器人个人文件发送失败", e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 发送Markdown消息给个人 (批量单聊)
|
||||
*
|
||||
* @param userId 接收人userId
|
||||
* @param title 标题
|
||||
* @param text Markdown内容
|
||||
*/
|
||||
public void sendMarkdownToUser(String userId, String title, String text) {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
|
||||
BatchSendOTOHeaders headers = new BatchSendOTOHeaders();
|
||||
headers.xAcsDingtalkAccessToken = tokenManager.getAccessToken();
|
||||
|
||||
String msgParam = String.format("{\"title\":\"%s\",\"text\":\"%s\"}",
|
||||
title.replace("\"", "\\\""),
|
||||
text.replace("\"", "\\\"").replace("\n", "\\n"));
|
||||
|
||||
BatchSendOTORequest request = new BatchSendOTORequest()
|
||||
.setRobotCode(properties.getRobotCode())
|
||||
.setUserIds(Collections.singletonList(userId))
|
||||
.setMsgKey("sampleMarkdown")
|
||||
.setMsgParam(msgParam);
|
||||
|
||||
client.batchSendOTOWithOptions(request, headers, new RuntimeOptions());
|
||||
log.info("机器人个人Markdown消息发送成功, userId: {}, title: {}", userId, title);
|
||||
} catch (Exception e) {
|
||||
log.error("机器人个人Markdown消息发送失败", e);
|
||||
throw new DingException("机器人个人Markdown消息发送失败", e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
/**
|
||||
* 刷新AccessToken
|
||||
*/
|
||||
private void refresh() {
|
||||
try {
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
config.regionId = "central";
|
||||
Client client = new Client(config);
|
||||
GetAccessTokenRequest request = new GetAccessTokenRequest()
|
||||
.setAppKey(properties.getAppKey())
|
||||
.setAppSecret(properties.getAppSecret());
|
||||
|
||||
GetAccessTokenResponse response = client.getAccessToken(request);
|
||||
if (response.getBody() != null) {
|
||||
this.accessToken = response.getBody().getAccessToken();
|
||||
// 设置过期时间,提前100秒刷新
|
||||
this.expireTime = System.currentTimeMillis() + (response.getBody().getExpireIn() * 1000) - 100000;
|
||||
log.info("钉钉AccessToken刷新成功,过期时间: {}", this.expireTime);
|
||||
} else {
|
||||
throw new DingException("刷新AccessToken失败,返回为空");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("刷新钉钉AccessToken失败", e);
|
||||
throw new DingException("刷新钉钉AccessToken失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
```
|
||||
27
pom.xml
27
pom.xml
@ -22,7 +22,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>16</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<pagehelper.spring.boot.starter.version>1.4.7</pagehelper.spring.boot.starter.version>
|
||||
<fastjson.version>2.0.58</fastjson.version>
|
||||
@ -30,6 +30,7 @@
|
||||
<commons.io.version>2.19.0</commons.io.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
<jwt.version>0.9.1</jwt.version>
|
||||
<mysql.version>8.0.33</mysql.version>
|
||||
<kaptcha.version>2.3.3</kaptcha.version>
|
||||
<swagger.version>3.0.0</swagger.version>
|
||||
<poi.version>4.1.2</poi.version>
|
||||
@ -44,12 +45,24 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- SpringBoot 核心包 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot 测试 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -96,9 +109,10 @@
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
<!-- <scope>runtime</scope>-->
|
||||
</dependency>
|
||||
|
||||
<!-- pagehelper 分页插件 -->
|
||||
@ -270,7 +284,6 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -287,8 +300,8 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>14</source>
|
||||
<target>14</target>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@ -15,6 +15,7 @@ public final class BboxApiConstants {
|
||||
public static final int CODE_DEVICE_NOT_REGISTERED = 901; // 设备未在平台注册,如平台未录入
|
||||
public static final int CODE_DEVICE_DISABLED = 902; // 设备已被禁用
|
||||
public static final int CODE_FILE_NOT_FOUND = 903; // 文件不存在
|
||||
public static final int CODE_PARAM_INVALID = 904; // 参数无效/缺失
|
||||
|
||||
// 对应消息文本(可用于统一提示)
|
||||
public static final String MSG_SUCCESS = "成功";
|
||||
@ -23,4 +24,5 @@ public final class BboxApiConstants {
|
||||
public static final String MSG_DEVICE_NOT_REGISTERED = "设备未在平台注册,如平台未录入";
|
||||
public static final String MSG_DEVICE_DISABLED = "设备已被禁用";
|
||||
public static final String MSG_FILE_NOT_FOUND = "文件不存在";
|
||||
}
|
||||
public static final String MSG_PARAM_INVALID = "参数无效";
|
||||
}
|
||||
|
||||
@ -12,17 +12,61 @@ import com.evobms.framework.web.page.TableSupport;
|
||||
*/
|
||||
public class PageUtils extends PageHelper
|
||||
{
|
||||
/** 设备历史平铺列表允许的每页条数 */
|
||||
public static final int[] HISTORY_PAGE_SIZES = {10, 20, 100, 500};
|
||||
|
||||
/**
|
||||
* 设置请求分页数据
|
||||
*/
|
||||
public static void startPage()
|
||||
{
|
||||
startPage(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param doCount 是否执行 COUNT;大数据量历史列表可传 false 避免扫行计数超时
|
||||
*/
|
||||
public static void startPage(boolean doCount)
|
||||
{
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Integer pageNum = pageDomain.getPageNum();
|
||||
Integer pageSize = pageDomain.getPageSize();
|
||||
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
|
||||
Boolean reasonable = pageDomain.getReasonable();
|
||||
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
|
||||
PageHelper.startPage(pageNum, pageSize, doCount, null, null)
|
||||
.setOrderBy(orderBy)
|
||||
.setReasonable(reasonable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 历史平铺:对时间范围内全部 vehicle_data 做库内分页;pageSize 规范为 10/20/100/500。
|
||||
*
|
||||
* @return 实际使用的每页条数
|
||||
*/
|
||||
public static int startHistoryPage(boolean doCount) {
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
int pageNum = pageDomain.getPageNum() == null || pageDomain.getPageNum() < 1 ? 1 : pageDomain.getPageNum();
|
||||
int pageSize = normalizeHistoryPageSize(pageDomain.getPageSize());
|
||||
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
|
||||
Boolean reasonable = pageDomain.getReasonable();
|
||||
PageHelper.startPage(pageNum, pageSize, doCount, null, null)
|
||||
.setOrderBy(orderBy)
|
||||
.setReasonable(reasonable);
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
/** 将请求的 pageSize 收敛到 10、20、100、500(不足 10 按 10) */
|
||||
public static int normalizeHistoryPageSize(Integer requested) {
|
||||
if (requested == null || requested <= 0) {
|
||||
return HISTORY_PAGE_SIZES[0];
|
||||
}
|
||||
int chosen = HISTORY_PAGE_SIZES[0];
|
||||
for (int allowed : HISTORY_PAGE_SIZES) {
|
||||
if (requested >= allowed) {
|
||||
chosen = allowed;
|
||||
}
|
||||
}
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
package com.evobms.framework.aspectj.lang.annotation;
|
||||
|
||||
import com.evobms.common.utils.poi.ExcelHandlerAdapter;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import com.evobms.common.utils.poi.ExcelHandlerAdapter;
|
||||
|
||||
/**
|
||||
* 自定义导出Excel数据注解
|
||||
|
||||
@ -10,7 +10,9 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.ExecutorChannel;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
|
||||
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
|
||||
@ -60,6 +62,9 @@ public class MqttConfig {
|
||||
@Value("${mqtt.cleanSession}")
|
||||
private boolean cleanSession;
|
||||
|
||||
@Value("${mqtt.completionTimeout:20000}")
|
||||
private int completionTimeout;
|
||||
|
||||
// 支持逗号分隔的多个主题,例如:/bbox/EVO0002/#,/bbox/000010000200003/#
|
||||
@Value("#{'${mqtt.subscribeTopic}'.split(',')}")
|
||||
private String[] subscribeTopics;
|
||||
@ -87,11 +92,17 @@ public class MqttConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* MQTT消息接收通道
|
||||
* MQTT消息接收通道 (异步处理,防止入库慢阻塞MQTT底层网络线程导致掉线)
|
||||
*/
|
||||
@Bean
|
||||
public MessageChannel mqttInputChannel() {
|
||||
return new DirectChannel();
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(10);
|
||||
executor.setMaxPoolSize(50);
|
||||
executor.setQueueCapacity(1000);
|
||||
executor.setThreadNamePrefix("mqtt-handler-");
|
||||
executor.initialize();
|
||||
return new ExecutorChannel(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +119,7 @@ public class MqttConfig {
|
||||
|
||||
MqttPahoMessageDrivenChannelAdapter adapter =
|
||||
new MqttPahoMessageDrivenChannelAdapter(clientId + "_inbound", mqttClientFactory(), topics);
|
||||
adapter.setCompletionTimeout(5000);
|
||||
adapter.setCompletionTimeout(completionTimeout);
|
||||
// 使用字节载荷转换器,保留原始二进制帧
|
||||
DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
|
||||
converter.setPayloadAsBytes(true);
|
||||
@ -150,7 +161,6 @@ public class MqttConfig {
|
||||
// 尽最大可能保留原始字节(ISO_8859_1一一映射)
|
||||
payloadBytes = ((String) payloadObj).getBytes(StandardCharsets.ISO_8859_1);
|
||||
} else {
|
||||
// 兜底:从toString获取,再按ISO_8859_1转换
|
||||
payloadBytes = payloadObj.toString().getBytes(StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@ import java.util.List;
|
||||
import javax.sql.DataSource;
|
||||
import org.apache.ibatis.io.VFS;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -122,11 +122,11 @@ public class MyBatisConfig
|
||||
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
||||
VFS.addImplClass(SpringBootVFS.class);
|
||||
|
||||
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
|
||||
sessionFactory.setDataSource(dataSource);
|
||||
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
|
||||
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||
return sessionFactory.getObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,8 +114,15 @@ public class SecurityConfig
|
||||
requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-ui/**", "/swagger-resources/**", "/webjars/**", "/v3/api-docs/**", "/*/api-docs", "/druid/**", "/doc.html", "/doc.html/**", "/knife4j/**").permitAll()
|
||||
.antMatchers("/dev-api/swagger-ui/**", "/dev-api/swagger-resources/**", "/dev-api/v3/api-docs/**", "/dev-api/doc.html", "/dev-api/knife4j/**").permitAll()
|
||||
.antMatchers("/devices/**","/ota/**").permitAll()
|
||||
.antMatchers("/battery-data/**").permitAll()
|
||||
.antMatchers("/vehicle-data/**").permitAll()
|
||||
.antMatchers("/vehicle-location/**").permitAll()
|
||||
.antMatchers("/subsystem-voltage/**").permitAll()
|
||||
.antMatchers("/subsystem-temperature/**").permitAll()
|
||||
.antMatchers("/extreme-values/**").permitAll()
|
||||
.antMatchers("/iot/**").permitAll()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated();
|
||||
|
||||
@ -23,7 +23,7 @@ import springfox.documentation.spring.web.plugins.Docket;
|
||||
|
||||
/**
|
||||
* Swagger2的接口配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
@ -54,11 +54,7 @@ public class SwaggerConfig
|
||||
.apiInfo(apiInfo())
|
||||
// 设置哪些接口暴露给Swagger展示
|
||||
.select()
|
||||
// 扫描所有有注解的api,用这种方式更灵活
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
// 扫描指定包中的swagger注解
|
||||
// .apis(RequestHandlerSelectors.basePackage("com.evobms.project.tool.swagger"))
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.apis(RequestHandlerSelectors.basePackage("com.evobms.project"))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
/* 设置安全模式,swagger可以设置访问token */
|
||||
@ -112,9 +108,9 @@ public class SwaggerConfig
|
||||
// 用ApiInfoBuilder进行定制
|
||||
return new ApiInfoBuilder()
|
||||
// 设置标题
|
||||
.title("标题:若依管理系统_接口文档")
|
||||
.title("标题:EVO-BMS 电池管理系统_接口文档")
|
||||
// 描述
|
||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||
.description("")
|
||||
// 作者信息
|
||||
.contact(new Contact(ruoyiConfig.getName(), null, null))
|
||||
// 版本
|
||||
|
||||
@ -4,13 +4,15 @@ import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BaseEntity implements Serializable
|
||||
@ -19,27 +21,37 @@ public class BaseEntity implements Serializable
|
||||
|
||||
/** 搜索值 */
|
||||
@JsonIgnore
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty(value = "搜索值")
|
||||
private String searchValue;
|
||||
|
||||
/** 创建者 */
|
||||
@ApiModelProperty(value = "创建者")
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
@ApiModelProperty(value = "更新者")
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
/** 请求参数 */
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@ApiModelProperty(value = "请求参数")
|
||||
@TableField(exist = false)
|
||||
private Map<String, Object> params;
|
||||
|
||||
public String getSearchValue()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.evobms.project.Battery.controller;
|
||||
package com.evobms.project.battery.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -14,21 +14,24 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.Battery.domain.ExtremeValues;
|
||||
import com.evobms.project.Battery.service.IExtremeValuesService;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
import com.evobms.project.battery.service.IExtremeValuesService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 电池极值数据Controller
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-14
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/BatteryData/BatteryData")
|
||||
@RequestMapping("/Battery/ExtremeValues")
|
||||
@Api(tags = "电池极值数据")
|
||||
public class ExtremeValuesController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
@ -37,8 +40,9 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 查询电池极值数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:list')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询电池极值数据列表")
|
||||
public TableDataInfo list(ExtremeValues extremeValues)
|
||||
{
|
||||
startPage();
|
||||
@ -49,9 +53,10 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 导出电池极值数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:export')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:export')")
|
||||
@Log(title = "电池极值数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出电池极值数据列表")
|
||||
public void export(HttpServletResponse response, ExtremeValues extremeValues)
|
||||
{
|
||||
List<ExtremeValues> list = extremeValuesService.selectExtremeValuesList(extremeValues);
|
||||
@ -62,8 +67,9 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 获取电池极值数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:query')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取电池极值数据详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(extremeValuesService.selectExtremeValuesById(id));
|
||||
@ -72,9 +78,10 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 新增电池极值数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:add')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:add')")
|
||||
@Log(title = "电池极值数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增电池极值数据")
|
||||
public AjaxResult add(@RequestBody ExtremeValues extremeValues)
|
||||
{
|
||||
return toAjax(extremeValuesService.insertExtremeValues(extremeValues));
|
||||
@ -83,9 +90,10 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 修改电池极值数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:edit')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:edit')")
|
||||
@Log(title = "电池极值数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改电池极值数据")
|
||||
public AjaxResult edit(@RequestBody ExtremeValues extremeValues)
|
||||
{
|
||||
return toAjax(extremeValuesService.updateExtremeValues(extremeValues));
|
||||
@ -94,9 +102,10 @@ public class ExtremeValuesController extends BaseController
|
||||
/**
|
||||
* 删除电池极值数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('BatteryData:BatteryData:remove')")
|
||||
@PreAuthorize("@ss.hasPermi('Battery:ExtremeValues:remove')")
|
||||
@Log(title = "电池极值数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除电池极值数据")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(extremeValuesService.deleteExtremeValuesByIds(ids));
|
||||
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.battery.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
import com.evobms.project.battery.service.ISubsystemTemperatureService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统温度信息Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/Battery/SubsystemTemperature")
|
||||
@Api(tags = "可充电储能子系统温度信息")
|
||||
public class SubsystemTemperatureController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private ISubsystemTemperatureService subsystemTemperatureService;
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询子系统温度信息列表")
|
||||
public TableDataInfo list(SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
startPage();
|
||||
List<SubsystemTemperature> list = subsystemTemperatureService.selectSubsystemTemperatureList(subsystemTemperature);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出可充电储能子系统温度信息列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:export')")
|
||||
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出子系统温度信息列表")
|
||||
public void export(HttpServletResponse response, SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
List<SubsystemTemperature> list = subsystemTemperatureService.selectSubsystemTemperatureList(subsystemTemperature);
|
||||
ExcelUtil<SubsystemTemperature> util = new ExcelUtil<SubsystemTemperature>(SubsystemTemperature.class);
|
||||
util.exportExcel(response, list, "可充电储能子系统温度信息数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可充电储能子系统温度信息详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取子系统温度信息详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(subsystemTemperatureService.selectSubsystemTemperatureById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统温度信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:add')")
|
||||
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增子系统温度信息")
|
||||
public AjaxResult add(@RequestBody SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
return toAjax(subsystemTemperatureService.insertSubsystemTemperature(subsystemTemperature));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统温度信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:edit')")
|
||||
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改子系统温度信息")
|
||||
public AjaxResult edit(@RequestBody SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
return toAjax(subsystemTemperatureService.updateSubsystemTemperature(subsystemTemperature));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统温度信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:remove')")
|
||||
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除子系统温度信息")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(subsystemTemperatureService.deleteSubsystemTemperatureByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.battery.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
import com.evobms.project.battery.service.ISubsystemVoltageService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统电压信息Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/Battery/SubsystemVoltage")
|
||||
@Api(tags = "可充电储能子系统电压信息")
|
||||
public class SubsystemVoltageController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private ISubsystemVoltageService subsystemVoltageService;
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询子系统电压信息列表")
|
||||
public TableDataInfo list(SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
startPage();
|
||||
List<SubsystemVoltage> list = subsystemVoltageService.selectSubsystemVoltageList(subsystemVoltage);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出可充电储能子系统电压信息列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:export')")
|
||||
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出子系统电压信息列表")
|
||||
public void export(HttpServletResponse response, SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
List<SubsystemVoltage> list = subsystemVoltageService.selectSubsystemVoltageList(subsystemVoltage);
|
||||
ExcelUtil<SubsystemVoltage> util = new ExcelUtil<SubsystemVoltage>(SubsystemVoltage.class);
|
||||
util.exportExcel(response, list, "可充电储能子系统电压信息数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可充电储能子系统电压信息详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取子系统电压信息详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(subsystemVoltageService.selectSubsystemVoltageById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统电压信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:add')")
|
||||
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增子系统电压信息")
|
||||
public AjaxResult add(@RequestBody SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
return toAjax(subsystemVoltageService.insertSubsystemVoltage(subsystemVoltage));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统电压信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:edit')")
|
||||
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改子系统电压信息")
|
||||
public AjaxResult edit(@RequestBody SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
return toAjax(subsystemVoltageService.updateSubsystemVoltage(subsystemVoltage));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统电压信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:remove')")
|
||||
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除子系统电压信息")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(subsystemVoltageService.deleteSubsystemVoltageByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
package com.evobms.project.Battery.domain;
|
||||
package com.evobms.project.battery.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
@ -10,220 +14,238 @@ import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 电池极值数据对象 extreme_values
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@ApiModel(description = "电池极值数据对象")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ExtremeValues extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/** 最高电压电池子系统号 */
|
||||
@ApiModelProperty(value = "最高电压电池子系统号")
|
||||
@Excel(name = "最高电压电池子系统号")
|
||||
private Integer maxVoltageSubsystemNo;
|
||||
|
||||
/** 最高电压电池单体代号 */
|
||||
@ApiModelProperty(value = "最高电压电池单体代号")
|
||||
@Excel(name = "最高电压电池单体代号")
|
||||
private Integer maxVoltageBatteryNo;
|
||||
|
||||
/** 电池单体电压最高值(V) */
|
||||
@ApiModelProperty(value = "电池单体电压最高值(V)")
|
||||
@Excel(name = "电池单体电压最高值(V)")
|
||||
private BigDecimal maxVoltageValue;
|
||||
|
||||
/** 最低电压电池子系统号 */
|
||||
@ApiModelProperty(value = "最低电压电池子系统号")
|
||||
@Excel(name = "最低电压电池子系统号")
|
||||
private Integer minVoltageSubsystemNo;
|
||||
|
||||
/** 最低电压电池单体代号 */
|
||||
@ApiModelProperty(value = "最低电压电池单体代号")
|
||||
@Excel(name = "最低电压电池单体代号")
|
||||
private Integer minVoltageBatteryNo;
|
||||
|
||||
/** 电池单体电压最低值(V) */
|
||||
@ApiModelProperty(value = "电池单体电压最低值(V)")
|
||||
@Excel(name = "电池单体电压最低值(V)")
|
||||
private BigDecimal minVoltageValue;
|
||||
|
||||
/** 最高温度子系统号 */
|
||||
@ApiModelProperty(value = "最高温度子系统号")
|
||||
@Excel(name = "最高温度子系统号")
|
||||
private Integer maxTempSubsystemNo;
|
||||
|
||||
/** 最高温度探针序号 */
|
||||
@ApiModelProperty(value = "最高温度探针序号")
|
||||
@Excel(name = "最高温度探针序号")
|
||||
private Integer maxTempProbeNo;
|
||||
|
||||
/** 最高温度值(℃) */
|
||||
@ApiModelProperty(value = "最高温度值(℃)")
|
||||
@Excel(name = "最高温度值(℃)")
|
||||
private BigDecimal maxTempValue;
|
||||
|
||||
/** 最低温度子系统号 */
|
||||
@ApiModelProperty(value = "最低温度子系统号")
|
||||
@Excel(name = "最低温度子系统号")
|
||||
private Integer minTempSubsystemNo;
|
||||
|
||||
/** 最低温度探针序号 */
|
||||
@ApiModelProperty(value = "最低温度探针序号")
|
||||
@Excel(name = "最低温度探针序号")
|
||||
private Integer minTempProbeNo;
|
||||
|
||||
/** 最低温度值(℃) */
|
||||
@ApiModelProperty(value = "最低温度值(℃)")
|
||||
@Excel(name = "最低温度值(℃)")
|
||||
private BigDecimal minTempValue;
|
||||
|
||||
public void setId(Long id)
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId()
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId)
|
||||
public void setDeviceId(String deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getDeviceId()
|
||||
public String getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setTimestamp(Date timestamp)
|
||||
public void setTimestamp(Date timestamp)
|
||||
{
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public Date getTimestamp()
|
||||
public Date getTimestamp()
|
||||
{
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setMaxVoltageSubsystemNo(Integer maxVoltageSubsystemNo)
|
||||
public void setMaxVoltageSubsystemNo(Integer maxVoltageSubsystemNo)
|
||||
{
|
||||
this.maxVoltageSubsystemNo = maxVoltageSubsystemNo;
|
||||
}
|
||||
|
||||
public Integer getMaxVoltageSubsystemNo()
|
||||
public Integer getMaxVoltageSubsystemNo()
|
||||
{
|
||||
return maxVoltageSubsystemNo;
|
||||
}
|
||||
|
||||
public void setMaxVoltageBatteryNo(Integer maxVoltageBatteryNo)
|
||||
public void setMaxVoltageBatteryNo(Integer maxVoltageBatteryNo)
|
||||
{
|
||||
this.maxVoltageBatteryNo = maxVoltageBatteryNo;
|
||||
}
|
||||
|
||||
public Integer getMaxVoltageBatteryNo()
|
||||
public Integer getMaxVoltageBatteryNo()
|
||||
{
|
||||
return maxVoltageBatteryNo;
|
||||
}
|
||||
|
||||
public void setMaxVoltageValue(BigDecimal maxVoltageValue)
|
||||
public void setMaxVoltageValue(BigDecimal maxVoltageValue)
|
||||
{
|
||||
this.maxVoltageValue = maxVoltageValue;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxVoltageValue()
|
||||
public BigDecimal getMaxVoltageValue()
|
||||
{
|
||||
return maxVoltageValue;
|
||||
}
|
||||
|
||||
public void setMinVoltageSubsystemNo(Integer minVoltageSubsystemNo)
|
||||
public void setMinVoltageSubsystemNo(Integer minVoltageSubsystemNo)
|
||||
{
|
||||
this.minVoltageSubsystemNo = minVoltageSubsystemNo;
|
||||
}
|
||||
|
||||
public Integer getMinVoltageSubsystemNo()
|
||||
public Integer getMinVoltageSubsystemNo()
|
||||
{
|
||||
return minVoltageSubsystemNo;
|
||||
}
|
||||
|
||||
public void setMinVoltageBatteryNo(Integer minVoltageBatteryNo)
|
||||
public void setMinVoltageBatteryNo(Integer minVoltageBatteryNo)
|
||||
{
|
||||
this.minVoltageBatteryNo = minVoltageBatteryNo;
|
||||
}
|
||||
|
||||
public Integer getMinVoltageBatteryNo()
|
||||
public Integer getMinVoltageBatteryNo()
|
||||
{
|
||||
return minVoltageBatteryNo;
|
||||
}
|
||||
|
||||
public void setMinVoltageValue(BigDecimal minVoltageValue)
|
||||
public void setMinVoltageValue(BigDecimal minVoltageValue)
|
||||
{
|
||||
this.minVoltageValue = minVoltageValue;
|
||||
}
|
||||
|
||||
public BigDecimal getMinVoltageValue()
|
||||
public BigDecimal getMinVoltageValue()
|
||||
{
|
||||
return minVoltageValue;
|
||||
}
|
||||
|
||||
public void setMaxTempSubsystemNo(Integer maxTempSubsystemNo)
|
||||
public void setMaxTempSubsystemNo(Integer maxTempSubsystemNo)
|
||||
{
|
||||
this.maxTempSubsystemNo = maxTempSubsystemNo;
|
||||
}
|
||||
|
||||
public Integer getMaxTempSubsystemNo()
|
||||
public Integer getMaxTempSubsystemNo()
|
||||
{
|
||||
return maxTempSubsystemNo;
|
||||
}
|
||||
|
||||
public void setMaxTempProbeNo(Integer maxTempProbeNo)
|
||||
public void setMaxTempProbeNo(Integer maxTempProbeNo)
|
||||
{
|
||||
this.maxTempProbeNo = maxTempProbeNo;
|
||||
}
|
||||
|
||||
public Integer getMaxTempProbeNo()
|
||||
public Integer getMaxTempProbeNo()
|
||||
{
|
||||
return maxTempProbeNo;
|
||||
}
|
||||
|
||||
public void setMaxTempValue(BigDecimal maxTempValue)
|
||||
public void setMaxTempValue(BigDecimal maxTempValue)
|
||||
{
|
||||
this.maxTempValue = maxTempValue;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxTempValue()
|
||||
public BigDecimal getMaxTempValue()
|
||||
{
|
||||
return maxTempValue;
|
||||
}
|
||||
|
||||
public void setMinTempSubsystemNo(Integer minTempSubsystemNo)
|
||||
public void setMinTempSubsystemNo(Integer minTempSubsystemNo)
|
||||
{
|
||||
this.minTempSubsystemNo = minTempSubsystemNo;
|
||||
}
|
||||
|
||||
public Integer getMinTempSubsystemNo()
|
||||
public Integer getMinTempSubsystemNo()
|
||||
{
|
||||
return minTempSubsystemNo;
|
||||
}
|
||||
|
||||
public void setMinTempProbeNo(Integer minTempProbeNo)
|
||||
public void setMinTempProbeNo(Integer minTempProbeNo)
|
||||
{
|
||||
this.minTempProbeNo = minTempProbeNo;
|
||||
}
|
||||
|
||||
public Integer getMinTempProbeNo()
|
||||
public Integer getMinTempProbeNo()
|
||||
{
|
||||
return minTempProbeNo;
|
||||
}
|
||||
|
||||
public void setMinTempValue(BigDecimal minTempValue)
|
||||
public void setMinTempValue(BigDecimal minTempValue)
|
||||
{
|
||||
this.minTempValue = minTempValue;
|
||||
}
|
||||
|
||||
public BigDecimal getMinTempValue()
|
||||
public BigDecimal getMinTempValue()
|
||||
{
|
||||
return minTempValue;
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.evobms.project.battery.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统温度信息对象 subsystem_temperature
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "可充电储能子系统温度信息对象")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SubsystemTemperature extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/** 可充电储能子系统个数 */
|
||||
@ApiModelProperty(value = "可充电储能子系统个数")
|
||||
@Excel(name = "可充电储能子系统个数")
|
||||
private Integer subsystemCount;
|
||||
|
||||
/** 可充电储能子系统号 */
|
||||
@ApiModelProperty(value = "可充电储能子系统号")
|
||||
@Excel(name = "可充电储能子系统号")
|
||||
private Integer subsystemNo;
|
||||
|
||||
/** 可充电储能温度探针个数 */
|
||||
@ApiModelProperty(value = "可充电储能温度探针个数")
|
||||
@Excel(name = "可充电储能温度探针个数")
|
||||
private Integer tempProbeCount;
|
||||
|
||||
/** 各温度探针检测的温度值数组(℃) */
|
||||
@ApiModelProperty(value = "各温度探针检测的温度值数组(℃)")
|
||||
@Excel(name = "各温度探针检测的温度值数组(℃)")
|
||||
private String temperatureValues;
|
||||
|
||||
/** 创建时间 */
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.evobms.project.battery.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统电压信息对象 subsystem_voltage
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(description = "可充电储能子系统电压信息对象")
|
||||
public class SubsystemVoltage extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/** 可充电储能子系统个数 */
|
||||
@ApiModelProperty(value = "可充电储能子系统个数")
|
||||
@Excel(name = "可充电储能子系统个数")
|
||||
private Integer subsystemCount;
|
||||
|
||||
/** 可充电储能子系统号 */
|
||||
@ApiModelProperty(value = "可充电储能子系统号")
|
||||
@Excel(name = "可充电储能子系统号")
|
||||
private Integer subsystemNo;
|
||||
|
||||
/** 可充电储能装置电压(V) */
|
||||
@ApiModelProperty(value = "可充电储能装置电压(V)")
|
||||
@Excel(name = "可充电储能装置电压(V)")
|
||||
private BigDecimal subsystemVoltage;
|
||||
|
||||
/** 可充电储能装置电流(A) */
|
||||
@ApiModelProperty(value = "可充电储能装置电流(A)")
|
||||
@Excel(name = "可充电储能装置电流(A)")
|
||||
private BigDecimal subsystemCurrent;
|
||||
|
||||
/** 单体电池总数 */
|
||||
@ApiModelProperty(value = "单体电池总数")
|
||||
@Excel(name = "单体电池总数")
|
||||
private Integer totalBatteryCount;
|
||||
|
||||
/** 本帧起始电池序号 */
|
||||
@ApiModelProperty(value = "本帧起始电池序号")
|
||||
@Excel(name = "本帧起始电池序号")
|
||||
private Integer frameStartBatteryNo;
|
||||
|
||||
/** 本帧单体电池总数 */
|
||||
@ApiModelProperty(value = "本帧单体电池总数")
|
||||
@Excel(name = "本帧单体电池总数")
|
||||
private Integer frameBatteryCount;
|
||||
|
||||
/** 单体电池电压数组(V) */
|
||||
@ApiModelProperty(value = "单体电池电压数组(V)")
|
||||
@Excel(name = "单体电池电压数组(V)")
|
||||
private String batteryVoltages;
|
||||
|
||||
/** 创建时间 */
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@ -1,19 +1,22 @@
|
||||
package com.evobms.project.Battery.mapper;
|
||||
package com.evobms.project.battery.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.Battery.domain.ExtremeValues;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 电池极值数据Mapper接口
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
public interface ExtremeValuesMapper
|
||||
{
|
||||
public interface ExtremeValuesMapper extends BaseMapper<ExtremeValues> {
|
||||
/**
|
||||
* 查询电池极值数据
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 电池极值数据
|
||||
*/
|
||||
@ -21,7 +24,7 @@ public interface ExtremeValuesMapper
|
||||
|
||||
/**
|
||||
* 查询电池极值数据列表
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 电池极值数据集合
|
||||
*/
|
||||
@ -29,7 +32,7 @@ public interface ExtremeValuesMapper
|
||||
|
||||
/**
|
||||
* 新增电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -37,7 +40,7 @@ public interface ExtremeValuesMapper
|
||||
|
||||
/**
|
||||
* 修改电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -45,7 +48,7 @@ public interface ExtremeValuesMapper
|
||||
|
||||
/**
|
||||
* 删除电池极值数据
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -53,9 +56,13 @@ public interface ExtremeValuesMapper
|
||||
|
||||
/**
|
||||
* 批量删除电池极值数据
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteExtremeValuesByIds(Long[] ids);
|
||||
|
||||
ExtremeValues selectLatestByDeviceId(@Param("deviceId") String deviceId);
|
||||
|
||||
ExtremeValues selectLatestByDeviceIdBefore(@Param("deviceId") String deviceId, @Param("beforeTime") Date beforeTime);
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.evobms.project.battery.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统温度信息Mapper接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
public interface SubsystemTemperatureMapper extends BaseMapper<SubsystemTemperature>
|
||||
{
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 可充电储能子系统温度信息
|
||||
*/
|
||||
public SubsystemTemperature selectSubsystemTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息列表
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 可充电储能子系统温度信息集合
|
||||
*/
|
||||
public List<SubsystemTemperature> selectSubsystemTemperatureList(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSubsystemTemperature(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSubsystemTemperature(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统温度信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统温度信息
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemTemperatureByIds(Long[] ids);
|
||||
|
||||
SubsystemTemperature selectLatestByDeviceAndSubsystem(@Param("deviceId") String deviceId, @Param("subsystemNo") Integer subsystemNo);
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.evobms.project.battery.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统电压信息Mapper接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
public interface SubsystemVoltageMapper extends BaseMapper<SubsystemVoltage>
|
||||
{
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 可充电储能子系统电压信息
|
||||
*/
|
||||
public SubsystemVoltage selectSubsystemVoltageById(Long id);
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息列表
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 可充电储能子系统电压信息集合
|
||||
*/
|
||||
public List<SubsystemVoltage> selectSubsystemVoltageList(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSubsystemVoltage(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSubsystemVoltage(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统电压信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemVoltageById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统电压信息
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemVoltageByIds(Long[] ids);
|
||||
|
||||
SubsystemVoltage selectLatestByDeviceAndSubsystem(@Param("deviceId") String deviceId, @Param("subsystemNo") Integer subsystemNo);
|
||||
}
|
||||
@ -1,19 +1,19 @@
|
||||
package com.evobms.project.Battery.service;
|
||||
package com.evobms.project.battery.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.Battery.domain.ExtremeValues;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
|
||||
/**
|
||||
* 电池极值数据Service接口
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
public interface IExtremeValuesService
|
||||
public interface IExtremeValuesService
|
||||
{
|
||||
/**
|
||||
* 查询电池极值数据
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 电池极值数据
|
||||
*/
|
||||
@ -21,7 +21,7 @@ public interface IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 查询电池极值数据列表
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 电池极值数据集合
|
||||
*/
|
||||
@ -29,7 +29,7 @@ public interface IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 新增电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -37,7 +37,7 @@ public interface IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 修改电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -45,7 +45,7 @@ public interface IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 批量删除电池极值数据
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的电池极值数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
@ -53,9 +53,13 @@ public interface IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 删除电池极值数据信息
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteExtremeValuesById(Long id);
|
||||
|
||||
ExtremeValues selectLatestByDeviceId(String deviceId);
|
||||
|
||||
ExtremeValues selectLatestByDeviceIdBefore(String deviceId, java.util.Date beforeTime);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.evobms.project.battery.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统温度信息Service接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
public interface ISubsystemTemperatureService extends IService<SubsystemTemperature>
|
||||
{
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 可充电储能子系统温度信息
|
||||
*/
|
||||
public SubsystemTemperature selectSubsystemTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息列表
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 可充电储能子系统温度信息集合
|
||||
*/
|
||||
public List<SubsystemTemperature> selectSubsystemTemperatureList(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSubsystemTemperature(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSubsystemTemperature(SubsystemTemperature subsystemTemperature);
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统温度信息
|
||||
*
|
||||
* @param ids 需要删除的可充电储能子系统温度信息主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemTemperatureByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统温度信息信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemTemperatureById(Long id);
|
||||
|
||||
SubsystemTemperature selectLatestByDeviceAndSubsystem(String deviceId, Integer subsystemNo);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.evobms.project.battery.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统电压信息Service接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
public interface ISubsystemVoltageService extends IService<SubsystemVoltage>
|
||||
{
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 可充电储能子系统电压信息
|
||||
*/
|
||||
public SubsystemVoltage selectSubsystemVoltageById(Long id);
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息列表
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 可充电储能子系统电压信息集合
|
||||
*/
|
||||
public List<SubsystemVoltage> selectSubsystemVoltageList(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSubsystemVoltage(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSubsystemVoltage(SubsystemVoltage subsystemVoltage);
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统电压信息
|
||||
*
|
||||
* @param ids 需要删除的可充电储能子系统电压信息主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemVoltageByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统电压信息信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSubsystemVoltageById(Long id);
|
||||
|
||||
SubsystemVoltage selectLatestByDeviceAndSubsystem(String deviceId, Integer subsystemNo);
|
||||
}
|
||||
@ -1,28 +1,30 @@
|
||||
package com.evobms.project.Battery.service.impl;
|
||||
package com.evobms.project.battery.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.evobms.project.Battery.mapper.ExtremeValuesMapper;
|
||||
import com.evobms.project.Battery.domain.ExtremeValues;
|
||||
import com.evobms.project.Battery.service.IExtremeValuesService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.battery.mapper.ExtremeValuesMapper;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
import com.evobms.project.battery.service.IExtremeValuesService;
|
||||
|
||||
/**
|
||||
* 电池极值数据Service业务层处理
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@Service
|
||||
public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
public class ExtremeValuesServiceImpl extends ServiceImpl<ExtremeValuesMapper, ExtremeValues> implements IExtremeValuesService
|
||||
{
|
||||
@Autowired
|
||||
private ExtremeValuesMapper extremeValuesMapper;
|
||||
|
||||
/**
|
||||
* 查询电池极值数据
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 电池极值数据
|
||||
*/
|
||||
@ -34,19 +36,40 @@ public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 查询电池极值数据列表
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 电池极值数据
|
||||
*/
|
||||
@Override
|
||||
public List<ExtremeValues> selectExtremeValuesList(ExtremeValues extremeValues)
|
||||
{
|
||||
return extremeValuesMapper.selectExtremeValuesList(extremeValues);
|
||||
LambdaQueryWrapper<ExtremeValues> qw = new LambdaQueryWrapper<>();
|
||||
if (extremeValues != null) {
|
||||
if (extremeValues.getDeviceId() != null && !extremeValues.getDeviceId().isEmpty()) {
|
||||
qw.eq(ExtremeValues::getDeviceId, extremeValues.getDeviceId());
|
||||
}
|
||||
if (extremeValues.getTimestamp() != null) {
|
||||
qw.ge(ExtremeValues::getTimestamp, extremeValues.getTimestamp());
|
||||
}
|
||||
java.util.Map<String, Object> params = extremeValues.getParams();
|
||||
if (params != null) {
|
||||
java.util.Date begin = com.evobms.common.utils.DateUtils.parseDate(params.get("beginTime"));
|
||||
java.util.Date end = com.evobms.common.utils.DateUtils.parseDate(params.get("endTime"));
|
||||
if (begin != null) {
|
||||
qw.ge(ExtremeValues::getTimestamp, begin);
|
||||
}
|
||||
if (end != null) {
|
||||
qw.le(ExtremeValues::getTimestamp, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
qw.orderByDesc(ExtremeValues::getTimestamp);
|
||||
return extremeValuesMapper.selectList(qw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -59,7 +82,7 @@ public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 修改电池极值数据
|
||||
*
|
||||
*
|
||||
* @param extremeValues 电池极值数据
|
||||
* @return 结果
|
||||
*/
|
||||
@ -72,7 +95,7 @@ public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 批量删除电池极值数据
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的电池极值数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -84,7 +107,7 @@ public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
|
||||
/**
|
||||
* 删除电池极值数据信息
|
||||
*
|
||||
*
|
||||
* @param id 电池极值数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -93,4 +116,14 @@ public class ExtremeValuesServiceImpl implements IExtremeValuesService
|
||||
{
|
||||
return extremeValuesMapper.deleteExtremeValuesById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtremeValues selectLatestByDeviceId(String deviceId) {
|
||||
return extremeValuesMapper.selectLatestByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtremeValues selectLatestByDeviceIdBefore(String deviceId, java.util.Date beforeTime) {
|
||||
return extremeValuesMapper.selectLatestByDeviceIdBefore(deviceId, beforeTime);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.evobms.project.battery.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.battery.mapper.SubsystemTemperatureMapper;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
import com.evobms.project.battery.service.ISubsystemTemperatureService;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统温度信息Service业务层处理
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@Service
|
||||
public class SubsystemTemperatureServiceImpl extends ServiceImpl<SubsystemTemperatureMapper, SubsystemTemperature> implements ISubsystemTemperatureService
|
||||
{
|
||||
@Autowired
|
||||
private SubsystemTemperatureMapper subsystemTemperatureMapper;
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 可充电储能子系统温度信息
|
||||
*/
|
||||
@Override
|
||||
public SubsystemTemperature selectSubsystemTemperatureById(Long id)
|
||||
{
|
||||
return subsystemTemperatureMapper.selectSubsystemTemperatureById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统温度信息列表
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 可充电储能子系统温度信息
|
||||
*/
|
||||
@Override
|
||||
public List<SubsystemTemperature> selectSubsystemTemperatureList(SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
LambdaQueryWrapper<SubsystemTemperature> qw = new LambdaQueryWrapper<>();
|
||||
if (subsystemTemperature != null) {
|
||||
if (subsystemTemperature.getDeviceId() != null && !subsystemTemperature.getDeviceId().isEmpty()) {
|
||||
qw.eq(SubsystemTemperature::getDeviceId, subsystemTemperature.getDeviceId());
|
||||
}
|
||||
if (subsystemTemperature.getTimestamp() != null) {
|
||||
qw.ge(SubsystemTemperature::getTimestamp, subsystemTemperature.getTimestamp());
|
||||
}
|
||||
java.util.Map<String, Object> params = subsystemTemperature.getParams();
|
||||
if (params != null) {
|
||||
java.util.Date begin = com.evobms.common.utils.DateUtils.parseDate(params.get("beginTime"));
|
||||
java.util.Date end = com.evobms.common.utils.DateUtils.parseDate(params.get("endTime"));
|
||||
if (begin != null) {
|
||||
qw.ge(SubsystemTemperature::getTimestamp, begin);
|
||||
}
|
||||
if (end != null) {
|
||||
qw.le(SubsystemTemperature::getTimestamp, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
qw.orderByDesc(SubsystemTemperature::getTimestamp);
|
||||
return subsystemTemperatureMapper.selectList(qw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertSubsystemTemperature(SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
return subsystemTemperatureMapper.insertSubsystemTemperature(subsystemTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统温度信息
|
||||
*
|
||||
* @param subsystemTemperature 可充电储能子系统温度信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateSubsystemTemperature(SubsystemTemperature subsystemTemperature)
|
||||
{
|
||||
return subsystemTemperatureMapper.updateSubsystemTemperature(subsystemTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统温度信息
|
||||
*
|
||||
* @param ids 需要删除的可充电储能子系统温度信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSubsystemTemperatureByIds(Long[] ids)
|
||||
{
|
||||
return subsystemTemperatureMapper.deleteSubsystemTemperatureByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统温度信息信息
|
||||
*
|
||||
* @param id 可充电储能子系统温度信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSubsystemTemperatureById(Long id)
|
||||
{
|
||||
return subsystemTemperatureMapper.deleteSubsystemTemperatureById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsystemTemperature selectLatestByDeviceAndSubsystem(String deviceId, Integer subsystemNo) {
|
||||
return subsystemTemperatureMapper.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.evobms.project.battery.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.battery.mapper.SubsystemVoltageMapper;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
import com.evobms.project.battery.service.ISubsystemVoltageService;
|
||||
|
||||
/**
|
||||
* 可充电储能子系统电压信息Service业务层处理
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@Service
|
||||
public class SubsystemVoltageServiceImpl extends ServiceImpl<SubsystemVoltageMapper, SubsystemVoltage> implements ISubsystemVoltageService
|
||||
{
|
||||
@Autowired
|
||||
private SubsystemVoltageMapper subsystemVoltageMapper;
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 可充电储能子系统电压信息
|
||||
*/
|
||||
@Override
|
||||
public SubsystemVoltage selectSubsystemVoltageById(Long id)
|
||||
{
|
||||
return subsystemVoltageMapper.selectSubsystemVoltageById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询可充电储能子系统电压信息列表
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 可充电储能子系统电压信息
|
||||
*/
|
||||
@Override
|
||||
public List<SubsystemVoltage> selectSubsystemVoltageList(SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
LambdaQueryWrapper<SubsystemVoltage> qw = new LambdaQueryWrapper<>();
|
||||
if (subsystemVoltage != null) {
|
||||
if (subsystemVoltage.getDeviceId() != null && !subsystemVoltage.getDeviceId().isEmpty()) {
|
||||
qw.eq(SubsystemVoltage::getDeviceId, subsystemVoltage.getDeviceId());
|
||||
}
|
||||
if (subsystemVoltage.getTimestamp() != null) {
|
||||
qw.ge(SubsystemVoltage::getTimestamp, subsystemVoltage.getTimestamp());
|
||||
}
|
||||
java.util.Map<String, Object> params = subsystemVoltage.getParams();
|
||||
if (params != null) {
|
||||
java.util.Date begin = com.evobms.common.utils.DateUtils.parseDate(params.get("beginTime"));
|
||||
java.util.Date end = com.evobms.common.utils.DateUtils.parseDate(params.get("endTime"));
|
||||
if (begin != null) {
|
||||
qw.ge(SubsystemVoltage::getTimestamp, begin);
|
||||
}
|
||||
if (end != null) {
|
||||
qw.le(SubsystemVoltage::getTimestamp, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
qw.orderByDesc(SubsystemVoltage::getTimestamp);
|
||||
return subsystemVoltageMapper.selectList(qw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertSubsystemVoltage(SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
return subsystemVoltageMapper.insertSubsystemVoltage(subsystemVoltage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改可充电储能子系统电压信息
|
||||
*
|
||||
* @param subsystemVoltage 可充电储能子系统电压信息
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateSubsystemVoltage(SubsystemVoltage subsystemVoltage)
|
||||
{
|
||||
return subsystemVoltageMapper.updateSubsystemVoltage(subsystemVoltage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除可充电储能子系统电压信息
|
||||
*
|
||||
* @param ids 需要删除的可充电储能子系统电压信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSubsystemVoltageByIds(Long[] ids)
|
||||
{
|
||||
return subsystemVoltageMapper.deleteSubsystemVoltageByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除可充电储能子系统电压信息信息
|
||||
*
|
||||
* @param id 可充电储能子系统电压信息主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSubsystemVoltageById(Long id)
|
||||
{
|
||||
return subsystemVoltageMapper.deleteSubsystemVoltageById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsystemVoltage selectLatestByDeviceAndSubsystem(String deviceId, Integer subsystemNo) {
|
||||
return subsystemVoltageMapper.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsChargeDetail;
|
||||
import com.evobms.project.bms.service.IBmsChargeDetailService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS充电过程详细数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/chargedetail/data")
|
||||
public class BmsChargeDetailController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsChargeDetailService bmsChargeDetailService;
|
||||
|
||||
/**
|
||||
* 查询BMS充电过程详细数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
startPage();
|
||||
List<BmsChargeDetail> list = bmsChargeDetailService.selectBmsChargeDetailList(bmsChargeDetail);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS充电过程详细数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS充电过程详细数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
List<BmsChargeDetail> list = bmsChargeDetailService.selectBmsChargeDetailList(bmsChargeDetail);
|
||||
ExcelUtil<BmsChargeDetail> util = new ExcelUtil<BmsChargeDetail>(BmsChargeDetail.class);
|
||||
util.exportExcel(response, list, "BMS充电过程详细数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS充电过程详细数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsChargeDetailService.selectBmsChargeDetailById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS充电过程详细数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS充电过程详细数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
return toAjax(bmsChargeDetailService.insertBmsChargeDetail(bmsChargeDetail));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS充电过程详细数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS充电过程详细数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
return toAjax(bmsChargeDetailService.updateBmsChargeDetail(bmsChargeDetail));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS充电过程详细数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS充电过程详细数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsChargeDetailService.deleteBmsChargeDetailByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsChargeTemperature;
|
||||
import com.evobms.project.bms.service.IBmsChargeTemperatureService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS充电座温度数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/chargetemperature/data")
|
||||
public class BmsChargeTemperatureController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsChargeTemperatureService bmsChargeTemperatureService;
|
||||
|
||||
/**
|
||||
* 查询BMS充电座温度数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
startPage();
|
||||
List<BmsChargeTemperature> list = bmsChargeTemperatureService.selectBmsChargeTemperatureList(bmsChargeTemperature);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS充电座温度数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS充电座温度数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
List<BmsChargeTemperature> list = bmsChargeTemperatureService.selectBmsChargeTemperatureList(bmsChargeTemperature);
|
||||
ExcelUtil<BmsChargeTemperature> util = new ExcelUtil<BmsChargeTemperature>(BmsChargeTemperature.class);
|
||||
util.exportExcel(response, list, "BMS充电座温度数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS充电座温度数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsChargeTemperatureService.selectBmsChargeTemperatureById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS充电座温度数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS充电座温度数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
return toAjax(bmsChargeTemperatureService.insertBmsChargeTemperature(bmsChargeTemperature));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS充电座温度数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS充电座温度数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
return toAjax(bmsChargeTemperatureService.updateBmsChargeTemperature(bmsChargeTemperature));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS充电座温度数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS充电座温度数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsChargeTemperatureService.deleteBmsChargeTemperatureByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -1,196 +0,0 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import com.evobms.project.bms.domain.BmsDevice;
|
||||
import com.evobms.project.bms.service.IBmsDeviceService;
|
||||
//import com.evobms.project.bms.service.MqttService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* BMS设备Controller
|
||||
*
|
||||
* @author evobms
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/device")
|
||||
public class BmsDeviceController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IBmsDeviceService bmsDeviceService;
|
||||
|
||||
// @Autowired(required = false)
|
||||
// private MqttService mqttService;
|
||||
|
||||
/**
|
||||
* 查询BMS设备列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsDevice bmsDevice) {
|
||||
startPage();
|
||||
List<BmsDevice> list = bmsDeviceService.selectBmsDeviceList(bmsDevice);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS设备详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:query')")
|
||||
@GetMapping(value = "/{deviceId}")
|
||||
public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId) {
|
||||
return success(bmsDeviceService.selectBmsDeviceByDeviceId(deviceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS设备
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:add')")
|
||||
@Log(title = "BMS设备", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsDevice bmsDevice) {
|
||||
return toAjax(bmsDeviceService.insertBmsDevice(bmsDevice));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS设备
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:edit')")
|
||||
@Log(title = "BMS设备", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsDevice bmsDevice) {
|
||||
return toAjax(bmsDeviceService.updateBmsDevice(bmsDevice));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS设备
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:remove')")
|
||||
@Log(title = "BMS设备", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{deviceIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] deviceIds) {
|
||||
return toAjax(bmsDeviceService.deleteBmsDeviceByDeviceIds(deviceIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新设备状态
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:edit')")
|
||||
@Log(title = "BMS设备状态", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/status")
|
||||
public AjaxResult updateStatus(@RequestBody Map<String, Object> params) {
|
||||
Long[] deviceIds = (Long[]) params.get("deviceIds");
|
||||
String status = (String) params.get("status");
|
||||
return toAjax(bmsDeviceService.updateBmsDeviceStatus(deviceIds, status));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 查询设备状态
|
||||
// */
|
||||
// @PreAuthorize("@ss.hasPermi('bms:device:query')")
|
||||
// @PostMapping("/queryStatus/{deviceCode}")
|
||||
// public AjaxResult queryDeviceStatus(@PathVariable String deviceCode) {
|
||||
// if (mqttService != null) {
|
||||
// mqttService.queryDeviceStatus(deviceCode);
|
||||
// return success("设备状态查询命令已发送");
|
||||
// } else {
|
||||
// return error("MQTT服务未启用,无法发送查询命令");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 重启设备
|
||||
// */
|
||||
// @PreAuthorize("@ss.hasPermi('bms:device:edit')")
|
||||
// @Log(title = "重启BMS设备", businessType = BusinessType.UPDATE)
|
||||
// @PostMapping("/restart/{deviceCode}")
|
||||
// public AjaxResult restartDevice(@PathVariable String deviceCode) {
|
||||
// if (mqttService != null) {
|
||||
// mqttService.restartDevice(deviceCode);
|
||||
// return success("设备重启命令已发送");
|
||||
// } else {
|
||||
// return error("MQTT服务未启用,无法发送重启命令");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 配置设备参数
|
||||
// */
|
||||
// @PreAuthorize("@ss.hasPermi('bms:device:edit')")
|
||||
// @Log(title = "配置BMS设备", businessType = BusinessType.UPDATE)
|
||||
// @PostMapping("/config/{deviceCode}")
|
||||
// public AjaxResult configDevice(@PathVariable String deviceCode, @RequestBody Map<String, Object> config) {
|
||||
// if (mqttService != null) {
|
||||
// mqttService.configDevice(deviceCode, config);
|
||||
// return success("设备配置命令已发送");
|
||||
// } else {
|
||||
// return error("MQTT服务未启用,无法发送配置命令");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 发送自定义MQTT消息
|
||||
// */
|
||||
// @PreAuthorize("@ss.hasPermi('bms:device:edit')")
|
||||
// @Log(title = "发送MQTT消息", businessType = BusinessType.OTHER)
|
||||
// @PostMapping("/mqtt/send")
|
||||
// public AjaxResult sendMqttMessage(@RequestBody Map<String, String> params) {
|
||||
// if (mqttService != null) {
|
||||
// String topic = params.get("topic");
|
||||
// String message = params.get("message");
|
||||
// mqttService.sendMessage(topic, message);
|
||||
// return success("MQTT消息已发送");
|
||||
// } else {
|
||||
// return error("MQTT服务未启用,无法发送消息");
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取设备统计信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:device:list')")
|
||||
@GetMapping("/statistics")
|
||||
public AjaxResult getStatistics() {
|
||||
Map<String, Object> statistics = new HashMap<>();
|
||||
|
||||
// 查询所有设备
|
||||
List<BmsDevice> allDevices = bmsDeviceService.selectBmsDeviceList(new BmsDevice());
|
||||
|
||||
// 统计设备数量
|
||||
long totalCount = allDevices.size();
|
||||
long onlineCount = allDevices.stream().filter(device -> "0".equals(device.getStatus())).count();
|
||||
long offlineCount = totalCount - onlineCount;
|
||||
|
||||
// 计算平均温度
|
||||
double avgTemperature = allDevices.stream()
|
||||
.filter(device -> device.getTemperature() != null)
|
||||
.mapToDouble(BmsDevice::getTemperature)
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
|
||||
// 计算平均剩余电量
|
||||
double avgCapacity = allDevices.stream()
|
||||
.filter(device -> device.getRemainingCapacity() != null)
|
||||
.mapToDouble(BmsDevice::getRemainingCapacity)
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
|
||||
statistics.put("totalCount", totalCount);
|
||||
statistics.put("onlineCount", onlineCount);
|
||||
statistics.put("offlineCount", offlineCount);
|
||||
statistics.put("avgTemperature", Math.round(avgTemperature * 100.0) / 100.0);
|
||||
statistics.put("avgCapacity", Math.round(avgCapacity * 100.0) / 100.0);
|
||||
|
||||
return success(statistics);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsRuntimeData;
|
||||
import com.evobms.project.bms.service.IBmsRuntimeDataService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS实时运行数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/runtime/data")
|
||||
public class BmsRuntimeDataController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsRuntimeDataService bmsRuntimeDataService;
|
||||
|
||||
/**
|
||||
* 查询BMS实时运行数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
startPage();
|
||||
List<BmsRuntimeData> list = bmsRuntimeDataService.selectBmsRuntimeDataList(bmsRuntimeData);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS实时运行数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS实时运行数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
List<BmsRuntimeData> list = bmsRuntimeDataService.selectBmsRuntimeDataList(bmsRuntimeData);
|
||||
ExcelUtil<BmsRuntimeData> util = new ExcelUtil<BmsRuntimeData>(BmsRuntimeData.class);
|
||||
util.exportExcel(response, list, "BMS实时运行数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS实时运行数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsRuntimeDataService.selectBmsRuntimeDataById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS实时运行数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS实时运行数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
return toAjax(bmsRuntimeDataService.insertBmsRuntimeData(bmsRuntimeData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS实时运行数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS实时运行数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
return toAjax(bmsRuntimeDataService.updateBmsRuntimeData(bmsRuntimeData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS实时运行数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS实时运行数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsRuntimeDataService.deleteBmsRuntimeDataByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsSopData;
|
||||
import com.evobms.project.bms.service.IBmsSopDataService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS功率能力(SOP)数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/sop/data")
|
||||
public class BmsSopDataController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsSopDataService bmsSopDataService;
|
||||
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsSopData bmsSopData)
|
||||
{
|
||||
startPage();
|
||||
List<BmsSopData> list = bmsSopDataService.selectBmsSopDataList(bmsSopData);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS功率能力(SOP)数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS功率能力(SOP)数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsSopData bmsSopData)
|
||||
{
|
||||
List<BmsSopData> list = bmsSopDataService.selectBmsSopDataList(bmsSopData);
|
||||
ExcelUtil<BmsSopData> util = new ExcelUtil<BmsSopData>(BmsSopData.class);
|
||||
util.exportExcel(response, list, "BMS功率能力(SOP)数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS功率能力(SOP)数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsSopDataService.selectBmsSopDataById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS功率能力(SOP)数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS功率能力(SOP)数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsSopData bmsSopData)
|
||||
{
|
||||
return toAjax(bmsSopDataService.insertBmsSopData(bmsSopData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS功率能力(SOP)数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS功率能力(SOP)数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsSopData bmsSopData)
|
||||
{
|
||||
return toAjax(bmsSopDataService.updateBmsSopData(bmsSopData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS功率能力(SOP)数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS功率能力(SOP)数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsSopDataService.deleteBmsSopDataByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsSystemStatus;
|
||||
import com.evobms.project.bms.service.IBmsSystemStatusService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS系统状态数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/systemstatus/data")
|
||||
public class BmsSystemStatusController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsSystemStatusService bmsSystemStatusService;
|
||||
|
||||
/**
|
||||
* 查询BMS系统状态数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
startPage();
|
||||
List<BmsSystemStatus> list = bmsSystemStatusService.selectBmsSystemStatusList(bmsSystemStatus);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS系统状态数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS系统状态数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
List<BmsSystemStatus> list = bmsSystemStatusService.selectBmsSystemStatusList(bmsSystemStatus);
|
||||
ExcelUtil<BmsSystemStatus> util = new ExcelUtil<BmsSystemStatus>(BmsSystemStatus.class);
|
||||
util.exportExcel(response, list, "BMS系统状态数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS系统状态数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsSystemStatusService.selectBmsSystemStatusById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS系统状态数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS系统状态数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
return toAjax(bmsSystemStatusService.insertBmsSystemStatus(bmsSystemStatus));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS系统状态数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS系统状态数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
return toAjax(bmsSystemStatusService.updateBmsSystemStatus(bmsSystemStatus));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS系统状态数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS系统状态数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsSystemStatusService.deleteBmsSystemStatusByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.bms.domain.BmsVoltageChannelData;
|
||||
import com.evobms.project.bms.service.IBmsVoltageChannelDataService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* BMS电压通道数据Controller
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/voltagechannel/data")
|
||||
public class BmsVoltageChannelDataController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsVoltageChannelDataService bmsVoltageChannelDataService;
|
||||
|
||||
/**
|
||||
* 查询BMS电压通道数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
startPage();
|
||||
List<BmsVoltageChannelData> list = bmsVoltageChannelDataService.selectBmsVoltageChannelDataList(bmsVoltageChannelData);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出BMS电压通道数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:export')")
|
||||
@Log(title = "BMS电压通道数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
List<BmsVoltageChannelData> list = bmsVoltageChannelDataService.selectBmsVoltageChannelDataList(bmsVoltageChannelData);
|
||||
ExcelUtil<BmsVoltageChannelData> util = new ExcelUtil<BmsVoltageChannelData>(BmsVoltageChannelData.class);
|
||||
util.exportExcel(response, list, "BMS电压通道数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BMS电压通道数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(bmsVoltageChannelDataService.selectBmsVoltageChannelDataById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS电压通道数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:add')")
|
||||
@Log(title = "BMS电压通道数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
return toAjax(bmsVoltageChannelDataService.insertBmsVoltageChannelData(bmsVoltageChannelData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS电压通道数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:edit')")
|
||||
@Log(title = "BMS电压通道数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
return toAjax(bmsVoltageChannelDataService.updateBmsVoltageChannelData(bmsVoltageChannelData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS电压通道数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('bms:data:remove')")
|
||||
@Log(title = "BMS电压通道数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(bmsVoltageChannelDataService.deleteBmsVoltageChannelDataByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -5,17 +5,30 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class GBT32960FullDecoder {
|
||||
private static final Logger log = LoggerFactory.getLogger(GBT32960FullDecoder.class);
|
||||
|
||||
// 从SN码生成AES密钥
|
||||
private static byte[] generateKeyFromSn(String sn) {
|
||||
StringBuilder keyStr = new StringBuilder(sn);
|
||||
while (keyStr.length() < 16) {
|
||||
keyStr.append("0");
|
||||
String s = sn == null ? "" : sn;
|
||||
String key;
|
||||
if ("EVO0001".equals(s)) {
|
||||
StringBuilder sb = new StringBuilder(16);
|
||||
sb.append("EVO0001");
|
||||
while (sb.length() < 16) sb.append('0');
|
||||
key = sb.toString();
|
||||
} else if (s.length() >= 16) {
|
||||
key = s.substring(s.length() - 16);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder(16);
|
||||
sb.append(s);
|
||||
while (sb.length() < 16) sb.append('0');
|
||||
key = sb.toString();
|
||||
}
|
||||
keyStr = new StringBuilder(keyStr.substring(0, 16));
|
||||
return keyStr.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||
return key.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
// AES解密
|
||||
@ -57,149 +70,236 @@ public class GBT32960FullDecoder {
|
||||
}
|
||||
|
||||
// 详细的协议解析方法
|
||||
public static String parseGBT32960Data(byte[] receivedData, String deviceSn) {
|
||||
String bytesData = null;
|
||||
try {
|
||||
log.info("=== GBT32960协议数据解析 ===");
|
||||
log.info("实际数据长度: " + receivedData.length + " 字节");
|
||||
// 1. 检查起始位
|
||||
if (receivedData.length < 2 || receivedData[0] != 0x23 || receivedData[1] != 0x23) {
|
||||
log.error("无效的起始位或数据过短");
|
||||
return null;
|
||||
}
|
||||
log.info("起始位: 0x2323 ✓");
|
||||
public static String parseGBT32960Data(byte[] receivedData, String deviceSn) {
|
||||
String bytesData = null;
|
||||
try {
|
||||
log.info("=== GBT32960协议数据解析 ===");
|
||||
log.info("实际数据长度: " + receivedData.length + " 字节");
|
||||
// 1. 检查起始位
|
||||
if (receivedData.length < 2 || receivedData[0] != 0x23 || receivedData[1] != 0x23) {
|
||||
log.error("无效的起始位或数据过短");
|
||||
return null;
|
||||
}
|
||||
log.info("起始位: 0x2323 ✓");
|
||||
|
||||
// 2. 打印完整数据用于调试
|
||||
log.info("完整数据: " + bytesToHex(receivedData));
|
||||
// 2. 打印完整数据用于调试
|
||||
log.info("完整数据: " + bytesToHex(receivedData));
|
||||
|
||||
// 3. 分析协议结构
|
||||
int offset = 2; // 跳过起始位
|
||||
// 3. 分析协议结构
|
||||
int offset = 2; // 跳过起始位
|
||||
|
||||
// 命令标识
|
||||
byte commandId = receivedData[offset++];
|
||||
log.info("命令标识: 0x" + String.format("%02X", commandId));
|
||||
// 命令标识
|
||||
byte commandId = receivedData[offset++];
|
||||
log.info("命令标识: 0x" + String.format("%02X", commandId));
|
||||
|
||||
// 应答标志
|
||||
byte responseFlag = receivedData[offset++];
|
||||
log.info("应答标志: 0x" + String.format("%02X", responseFlag));
|
||||
// 应答标志
|
||||
byte responseFlag = receivedData[offset++];
|
||||
log.info("应答标志: 0x" + String.format("%02X", responseFlag));
|
||||
|
||||
// VIN码 (17字节)
|
||||
byte[] vin = Arrays.copyOfRange(receivedData, offset, offset + 17);
|
||||
offset += 17;
|
||||
log.info("VIN码: " + bytesToHex(vin) + " (" + new String(vin).trim() + ")");
|
||||
// VIN码 (17字节)
|
||||
byte[] vin = Arrays.copyOfRange(receivedData, offset, offset + 17);
|
||||
offset += 17;
|
||||
log.info("VIN码: " + bytesToHex(vin) + " (" + new String(vin).trim() + ")");
|
||||
|
||||
// 加密方式
|
||||
byte encryptionMethod = receivedData[offset++];
|
||||
log.info("加密方式: 0x" + String.format("%02X", encryptionMethod));
|
||||
// 加密方式
|
||||
byte encryptionMethod = receivedData[offset++];
|
||||
log.info("加密方式: 0x" + String.format("%02X", encryptionMethod));
|
||||
|
||||
if (encryptionMethod != 0x03) {
|
||||
log.error("不支持的解密方式,期望AES128(0x03)");
|
||||
return null;
|
||||
}
|
||||
if (encryptionMethod != 0x03) {
|
||||
log.error("不支持的解密方式,期望AES128(0x03)");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 数据单元长度 (WORD, 大端序)
|
||||
int dataUnitLength = ((receivedData[offset] & 0xFF) << 8) | (receivedData[offset + 1] & 0xFF);
|
||||
offset += 2;
|
||||
log.info("声明的数据单元长度: " + dataUnitLength + " 字节");
|
||||
// 数据单元长度 (WORD, 大端序)
|
||||
int dataUnitLength = ((receivedData[offset] & 0xFF) << 8) | (receivedData[offset + 1] & 0xFF);
|
||||
offset += 2;
|
||||
log.info("声明的数据单元长度: " + dataUnitLength + " 字节");
|
||||
|
||||
// 计算当前头部长度
|
||||
int headerLength = offset;
|
||||
log.info("协议头部长度: " + headerLength + " 字节");
|
||||
// 计算当前头部长度
|
||||
int headerLength = offset;
|
||||
log.info("协议头部长度: " + headerLength + " 字节");
|
||||
|
||||
// 剩余数据长度
|
||||
int remainingDataLength = receivedData.length - headerLength;
|
||||
log.info("剩余数据长度: " + remainingDataLength + " 字节");
|
||||
// 剩余数据长度
|
||||
int remainingDataLength = receivedData.length - headerLength;
|
||||
log.info("剩余数据长度: " + remainingDataLength + " 字节");
|
||||
|
||||
// 4. 重新计算期望长度
|
||||
// 方案1: 如果BCC是1字节
|
||||
int expectedLength1 = headerLength + dataUnitLength + 1;
|
||||
// 方案2: 如果BCC是2字节(根据您最初描述)
|
||||
int expectedLength2 = headerLength + dataUnitLength + 2;
|
||||
// 4. 重新计算期望长度
|
||||
// 方案1: 如果BCC是1字节
|
||||
int expectedLength1 = headerLength + dataUnitLength + 1;
|
||||
// 方案2: 如果BCC是2字节(根据您最初描述)
|
||||
int expectedLength2 = headerLength + dataUnitLength + 2;
|
||||
|
||||
log.info("期望长度 (BCC=1字节): " + expectedLength1);
|
||||
log.info("期望长度 (BCC=2字节): " + expectedLength2);
|
||||
log.info("实际长度: " + receivedData.length);
|
||||
log.info("期望长度 (BCC=1字节): " + expectedLength1);
|
||||
log.info("期望长度 (BCC=2字节): " + expectedLength2);
|
||||
log.info("实际长度: " + receivedData.length);
|
||||
|
||||
// 5. 确定正确的数据范围
|
||||
int encryptedDataStart = offset;
|
||||
int encryptedDataEnd;
|
||||
int bccStart;
|
||||
// 5. 确定正确的数据范围
|
||||
int encryptedDataStart = offset;
|
||||
int encryptedDataEnd;
|
||||
int bccStart;
|
||||
|
||||
if (receivedData.length == expectedLength1) {
|
||||
// BCC为1字节
|
||||
encryptedDataEnd = encryptedDataStart + dataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
log.info("采用方案: BCC为1字节");
|
||||
} else if (receivedData.length == expectedLength2) {
|
||||
// BCC为2字节
|
||||
encryptedDataEnd = encryptedDataStart + dataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
log.info("采用方案: BCC为2字节");
|
||||
} else {
|
||||
// 自动适应:使用剩余的所有数据作为加密数据
|
||||
encryptedDataEnd = receivedData.length - 1; // 假设BCC为1字节
|
||||
int actualDataUnitLength = encryptedDataEnd - encryptedDataStart;
|
||||
log.info("长度不匹配,使用实际数据单元长度: " + actualDataUnitLength + " 字节");
|
||||
dataUnitLength = actualDataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
}
|
||||
if (receivedData.length == expectedLength1) {
|
||||
// BCC为1字节
|
||||
encryptedDataEnd = encryptedDataStart + dataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
log.info("采用方案: BCC为1字节");
|
||||
} else if (receivedData.length == expectedLength2) {
|
||||
// BCC为2字节
|
||||
encryptedDataEnd = encryptedDataStart + dataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
log.info("采用方案: BCC为2字节");
|
||||
} else {
|
||||
// 自动适应:使用剩余的所有数据作为加密数据
|
||||
encryptedDataEnd = receivedData.length - 1; // 假设BCC为1字节
|
||||
int actualDataUnitLength = encryptedDataEnd - encryptedDataStart;
|
||||
log.info("长度不匹配,使用实际数据单元长度: " + actualDataUnitLength + " 字节");
|
||||
dataUnitLength = actualDataUnitLength;
|
||||
bccStart = encryptedDataEnd;
|
||||
}
|
||||
|
||||
// 6. 提取加密数据
|
||||
byte[] encryptedData = Arrays.copyOfRange(receivedData, encryptedDataStart, encryptedDataStart + dataUnitLength);
|
||||
log.info("加密数据长度: " + encryptedData.length + " 字节");
|
||||
log.info("加密数据 (前64字节): " + bytesToHex(Arrays.copyOf(encryptedData, Math.min(64, encryptedData.length))) + "...");
|
||||
// 6. 提取加密数据
|
||||
byte[] encryptedData = Arrays.copyOfRange(receivedData, encryptedDataStart, encryptedDataStart + dataUnitLength);
|
||||
log.info("加密数据长度: " + encryptedData.length + " 字节");
|
||||
log.info("加密数据 (前64字节): " + bytesToHex(Arrays.copyOf(encryptedData, Math.min(64, encryptedData.length))) + "...");
|
||||
if (encryptedData.length % 16 != 0) {
|
||||
log.error("AES密文长度非法,不是16倍数,length=" + encryptedData.length);
|
||||
return null;
|
||||
}
|
||||
// 7. 提取BCC校验码
|
||||
int bccLength = receivedData.length - (encryptedDataStart + dataUnitLength);
|
||||
byte[] receivedBCC = Arrays.copyOfRange(receivedData, encryptedDataStart + dataUnitLength, receivedData.length);
|
||||
//log.info("BCC长度: " + bccLength + " 字节");
|
||||
//log.info("接收到的BCC: " + bytesToHex(receivedBCC));
|
||||
|
||||
// 7. 提取BCC校验码
|
||||
int bccLength = receivedData.length - (encryptedDataStart + dataUnitLength);
|
||||
byte[] receivedBCC = Arrays.copyOfRange(receivedData, encryptedDataStart + dataUnitLength, receivedData.length);
|
||||
//log.info("BCC长度: " + bccLength + " 字节");
|
||||
//log.info("接收到的BCC: " + bytesToHex(receivedBCC));
|
||||
// 8. 计算BCC校验范围:从命令单元开始到加密数据结束
|
||||
int bccCalcStart = 2; // 从命令标识开始 (跳过0x2323)
|
||||
int bccCalcEnd = encryptedDataStart + dataUnitLength;
|
||||
byte calculatedBCC = calculateBCC(receivedData, bccCalcStart, bccCalcEnd);
|
||||
|
||||
// 8. 计算BCC校验范围:从命令单元开始到加密数据结束
|
||||
int bccCalcStart = 2; // 从命令标识开始 (跳过0x2323)
|
||||
int bccCalcEnd = encryptedDataStart + dataUnitLength;
|
||||
byte calculatedBCC = calculateBCC(receivedData, bccCalcStart, bccCalcEnd);
|
||||
log.info("BCC计算范围: 字节[" + bccCalcStart + "~" + bccCalcEnd + ")");
|
||||
log.info("计算出的BCC: 0x" + String.format("%02X", calculatedBCC));
|
||||
|
||||
log.info("BCC计算范围: 字节[" + bccCalcStart + "~" + bccCalcEnd + ")");
|
||||
log.info("计算出的BCC: 0x" + String.format("%02X", calculatedBCC));
|
||||
|
||||
// 验证BCC (只比较第一个字节)
|
||||
if (receivedBCC.length > 0 && calculatedBCC == receivedBCC[0]) {
|
||||
log.info("BCC校验通过 ✓");
|
||||
} else {
|
||||
log.error("BCC校验失败!");
|
||||
}
|
||||
// 验证BCC (只比较第一个字节)
|
||||
if (receivedBCC.length > 0 && calculatedBCC == receivedBCC[0]) {
|
||||
log.info("BCC校验通过 ✓");
|
||||
} else {
|
||||
log.error("BCC校验失败!");
|
||||
}
|
||||
|
||||
|
||||
//使用的AES密钥
|
||||
byte[] aesKey = generateKeyFromSn(deviceSn);
|
||||
byte[] decryptedData = decryptData(encryptedData, aesKey);
|
||||
bytesData = bytesToHex(decryptedData);
|
||||
log.info("解密成功!");
|
||||
log.info("解密后数据长度: " + decryptedData.length + " 字节");
|
||||
log.info("解密后数据 (完整): " + bytesData);
|
||||
//使用的AES密钥
|
||||
byte[] aesKey = generateKeyFromSn(deviceSn);
|
||||
System.out.println(Arrays.toString(aesKey));
|
||||
System.out.println(aesKey.length);
|
||||
log.info("AES密钥: " + bytesToHex(aesKey));
|
||||
byte[] decryptedData = decryptData(encryptedData, aesKey);
|
||||
bytesData = bytesToHex(decryptedData);
|
||||
log.info("解密成功!");
|
||||
log.info("解密后数据长度: " + decryptedData.length + " 字节");
|
||||
log.info("解密后数据 (完整): " + bytesData);
|
||||
|
||||
|
||||
// 10. 解析解密后的数据单元
|
||||
// parseDecryptedDataUnit(decryptedData);
|
||||
// 10. 解析解密后的数据单元
|
||||
// parseDecryptedDataUnit(decryptedData);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("解析过程中发生错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
log.error("解析过程中发生错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bytesData;
|
||||
}
|
||||
|
||||
/* public static String parseGBT32960Data(byte[] frame, String deviceSn) throws Exception {
|
||||
|
||||
if (frame == null || frame.length < 25) {
|
||||
throw new IllegalArgumentException("报文长度非法");
|
||||
}
|
||||
return bytesData;
|
||||
int offset = 0;
|
||||
// 1. 起始符校验 0x23 0x23
|
||||
|
||||
if (frame[offset++] != 0x23 || frame[offset++] != 0x23) {
|
||||
throw new IllegalArgumentException("非法起始位,非0x2323");
|
||||
}
|
||||
// 2. 命令标识
|
||||
byte commandId = frame[offset++];
|
||||
// 3. 应答标志
|
||||
byte responseFlag = frame[offset++];
|
||||
// 4. VIN (17字节)
|
||||
byte[] vinBytes = Arrays.copyOfRange(frame, offset, offset + 17);
|
||||
String vin = new String(vinBytes).trim();
|
||||
offset += 17;
|
||||
// 5. 加密方式
|
||||
byte encryptType = frame[offset++];
|
||||
// 6. 数据单元长度 (大端)
|
||||
if (offset + 2 > frame.length) {
|
||||
throw new IllegalArgumentException("数据单元长度字段越界");
|
||||
}
|
||||
int dataUnitLength = ((frame[offset] & 0xFF) << 8) | (frame[offset + 1] & 0xFF);
|
||||
offset += 2;
|
||||
int headerLength = offset;
|
||||
|
||||
// 7. 校验整体长度
|
||||
// 标准格式:
|
||||
// 头部 + 数据单元 + 1字节BCC
|
||||
int expectedLength = headerLength + dataUnitLength + 1;
|
||||
if (frame.length != expectedLength) {
|
||||
throw new IllegalArgumentException("报文长度不匹配,声明长度=" + dataUnitLength + ",实际长度=" + frame.length + ",期望总长度=" + expectedLength);
|
||||
}
|
||||
// 8. 提取数据单元
|
||||
byte[] dataUnit = Arrays.copyOfRange(frame, headerLength, headerLength + dataUnitLength
|
||||
);
|
||||
// 9. BCC 校验
|
||||
// BCC范围:从命令标识开始
|
||||
byte receivedBcc = frame[frame.length - 1];
|
||||
byte calculatedBcc = calculateBCC(frame, 2, headerLength + dataUnitLength
|
||||
);
|
||||
if (receivedBcc != calculatedBcc) {
|
||||
throw new IllegalStateException(
|
||||
String.format("BCC校验失败,收到=0x%02X 计算=0x%02X",
|
||||
receivedBcc, calculatedBcc)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 10. 加密处理
|
||||
|
||||
if (encryptType == 0x01) {
|
||||
// 不加密
|
||||
return bytesToHex(dataUnit);
|
||||
}
|
||||
|
||||
if (encryptType != 0x03) {
|
||||
throw new UnsupportedOperationException(
|
||||
"不支持的加密方式: " + encryptType);
|
||||
}
|
||||
|
||||
// AES 必须 16倍数
|
||||
if (dataUnitLength % 16 != 0) {
|
||||
throw new IllegalStateException(
|
||||
"AES密文长度非法,不是16倍数,length=" + dataUnitLength);
|
||||
}
|
||||
|
||||
|
||||
// 11. AES解密
|
||||
|
||||
byte[] aesKey = generateKeyFromSn(deviceSn);
|
||||
|
||||
byte[] decrypted = decryptData(dataUnit, aesKey);
|
||||
|
||||
return bytesToHex(decrypted);
|
||||
}
|
||||
*/
|
||||
|
||||
private static void parseDecryptedDataUnit(byte[] decryptedData) {
|
||||
log.info("\n=== 数据单元解析 ===");
|
||||
log.info("\n=== 数据单元解析 ===");
|
||||
|
||||
if (decryptedData == null || decryptedData.length == 0) {
|
||||
log.info("解密数据为空");
|
||||
log.info("解密数据为空");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("数据单元总长度: " + decryptedData.length + " 字节");
|
||||
log.info("数据单元内容: " + bytesToHex(decryptedData));
|
||||
log.info("数据单元总长度: " + decryptedData.length + " 字节");
|
||||
log.info("数据单元内容: " + bytesToHex(decryptedData));
|
||||
|
||||
// 尝试解析采集时间(前6字节BCD)
|
||||
if (decryptedData.length >= 6) {
|
||||
@ -268,16 +368,26 @@ public class GBT32960FullDecoder {
|
||||
|
||||
private static String typeName(int typeId) {
|
||||
switch (typeId & 0xFF) {
|
||||
case 0x01: return "整车数据";
|
||||
case 0x02: return "驱动电机数据";
|
||||
case 0x03: return "燃料电池数据";
|
||||
case 0x04: return "发动机数据";
|
||||
case 0x05: return "车辆位置数据";
|
||||
case 0x06: return "极值数据";
|
||||
case 0x07: return "报警数据";
|
||||
case 0x08: return "储能装置电压数据";
|
||||
case 0x09: return "储能装置温度数据";
|
||||
default: return String.format("未知类型(0x%02X)", typeId);
|
||||
case 0x01:
|
||||
return "整车数据";
|
||||
case 0x02:
|
||||
return "驱动电机数据";
|
||||
case 0x03:
|
||||
return "燃料电池数据";
|
||||
case 0x04:
|
||||
return "发动机数据";
|
||||
case 0x05:
|
||||
return "车辆位置数据";
|
||||
case 0x06:
|
||||
return "极值数据";
|
||||
case 0x07:
|
||||
return "报警数据";
|
||||
case 0x08:
|
||||
return "储能装置电压数据";
|
||||
case 0x09:
|
||||
return "储能装置温度数据";
|
||||
default:
|
||||
return String.format("未知类型(0x%02X)", typeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,48 +2,68 @@ package com.evobms.project.bms.controller;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.*;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "mqtt.legacyReceiver.enabled", havingValue = "true")
|
||||
public class GBT32960MqttReceiver {
|
||||
private static final String BROKER = "tcp://61.182.73.218:1883";
|
||||
private static final String CLIENT_ID = "evobms-client";
|
||||
private static final String TOPIC = "/bbox/EVO0002/#";
|
||||
private static final String DEVICE_SN = "EVO0002";
|
||||
@Value("${mqtt.host}")
|
||||
private String broker;
|
||||
@Value("${mqtt.clientId}")
|
||||
private String clientId;
|
||||
@Value("${mqtt.username:}")
|
||||
private String username;
|
||||
@Value("${mqtt.password:}")
|
||||
private String password;
|
||||
@Value("${mqtt.connectionTimeout:30}")
|
||||
private int connectionTimeout;
|
||||
@Value("${mqtt.keepAliveInterval:60}")
|
||||
private int keepAliveInterval;
|
||||
@Value("${mqtt.automaticReconnect:true}")
|
||||
private boolean automaticReconnect;
|
||||
@Value("${mqtt.cleanSession:true}")
|
||||
private boolean cleanSession;
|
||||
@Value("${mqtt.subscribeTopic:/bbox/+/#}")
|
||||
private String subscribeTopic;
|
||||
|
||||
@Bean
|
||||
public void initMQtt() throws MqttException {
|
||||
MqttClient client = new MqttClient(BROKER, CLIENT_ID, new MemoryPersistence());
|
||||
public void initMQtt() {
|
||||
try {
|
||||
MqttClient client = new MqttClient(broker, clientId, new MemoryPersistence());
|
||||
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setCleanSession(true);
|
||||
|
||||
client.setCallback(new MqttCallback() {
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
System.out.println("MQTT连接断开: " + cause.getMessage());
|
||||
MqttConnectOptions options = new MqttConnectOptions();
|
||||
options.setCleanSession(cleanSession);
|
||||
options.setAutomaticReconnect(automaticReconnect);
|
||||
options.setConnectionTimeout(connectionTimeout);
|
||||
options.setKeepAliveInterval(keepAliveInterval);
|
||||
if (username != null && !username.isEmpty()) {
|
||||
options.setUserName(username);
|
||||
}
|
||||
if (password != null && !password.isEmpty()) {
|
||||
options.setPassword(password.toCharArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) {
|
||||
System.out.println("\n收到MQTT消息,主题: " + topic);
|
||||
System.out.println("QoS: " + message.getQos());
|
||||
client.setCallback(new MqttCallback() {
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
}
|
||||
|
||||
// 直接处理字节数组
|
||||
byte[] payload = message.getPayload();
|
||||
// GBT32960FullDecoder.parseGBT32960Data(payload, DEVICE_SN);
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage message) {
|
||||
byte[] payload = message.getPayload();
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken token) {
|
||||
// 发布完成回调
|
||||
}
|
||||
});
|
||||
|
||||
client.connect(options);
|
||||
client.subscribe(TOPIC);
|
||||
System.out.println("已成功连接到MQTT Broker并订阅主题: " + TOPIC);
|
||||
client.connect(options);
|
||||
client.subscribe(subscribeTopic);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ import com.evobms.common.constant.Constants;
|
||||
import com.evobms.common.constant.BboxApiConstants;
|
||||
import com.evobms.common.utils.StringUtils;
|
||||
import com.evobms.project.bms.service.MqttService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -25,6 +27,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/bms/mqtt")
|
||||
@Api(tags = "MQTT消息发布")
|
||||
public class MqttPublishController {
|
||||
private static final Logger log = LoggerFactory.getLogger(MqttPublishController.class);
|
||||
|
||||
@ -39,12 +42,12 @@ public class MqttPublishController {
|
||||
*/
|
||||
@PostMapping("/publish")
|
||||
// @Log(title = "MQTT消息发布", businessType = BusinessType.INSERT)
|
||||
@ApiOperation("发布文本消息")
|
||||
public AjaxResult publishMessage(@RequestParam String topic, @RequestParam String message) {
|
||||
try {
|
||||
if (mqttService == null) {
|
||||
return AjaxResult.error("MQTT服务未启用");
|
||||
}
|
||||
|
||||
mqttService.sendMessage(topic, message);
|
||||
log.info("发布消息成功 -> 主题: {}, 内容: {}", topic, message);
|
||||
return AjaxResult.success("消息发布成功", "主题: " + topic + ", 内容: " + message);
|
||||
@ -58,6 +61,7 @@ public class MqttPublishController {
|
||||
* 发布原始十六进制字节消息到指定主题
|
||||
*/
|
||||
@PostMapping("/publishHex")
|
||||
@ApiOperation("发布HEX消息")
|
||||
public AjaxResult publishHex(@RequestParam String topic, @RequestParam String hex) {
|
||||
try {
|
||||
if (mqttService == null) {
|
||||
@ -78,6 +82,7 @@ public class MqttPublishController {
|
||||
* 获取当前请求的鉴权令牌(从请求头读取并去除前缀)
|
||||
*/
|
||||
@GetMapping("/authToken")
|
||||
@ApiOperation("获取鉴权令牌")
|
||||
public AjaxResult getAuthToken(HttpServletRequest request) {
|
||||
try {
|
||||
String raw = request.getHeader(tokenHeader);
|
||||
@ -129,6 +134,7 @@ public class MqttPublishController {
|
||||
*/
|
||||
@PostMapping("/publishDeviceData")
|
||||
// @Log(title = "设备数据发布", businessType = BusinessType.INSERT)
|
||||
@ApiOperation("发布设备测试数据")
|
||||
public AjaxResult publishDeviceData(@RequestParam String deviceCode) {
|
||||
try {
|
||||
if (mqttService == null) {
|
||||
@ -160,6 +166,7 @@ public class MqttPublishController {
|
||||
* 快速测试 - 发布消息到test设备
|
||||
*/
|
||||
@GetMapping("/quickTest")
|
||||
@ApiOperation("快速测试发布")
|
||||
public AjaxResult quickTest() {
|
||||
try {
|
||||
if (mqttService == null) {
|
||||
@ -192,6 +199,7 @@ public class MqttPublishController {
|
||||
*/
|
||||
@PostMapping("/batchPublish")
|
||||
// @Log(title = "批量MQTT消息发布", businessType = BusinessType.INSERT)
|
||||
@ApiOperation("批量发布测试消息")
|
||||
public AjaxResult batchPublish(@RequestParam String deviceCode, @RequestParam(defaultValue = "5") int count) {
|
||||
try {
|
||||
if (mqttService == null) {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.evobms.project.bms.controller;
|
||||
|
||||
import com.evobms.project.bms.service.MqttService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.slf4j.Logger;
|
||||
@ -17,6 +19,7 @@ import java.util.Map;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/mqtt/test")
|
||||
@Api(tags = "MQTT测试")
|
||||
public class MqttTestController {
|
||||
private static final Logger log = LoggerFactory.getLogger(MqttTestController.class);
|
||||
|
||||
@ -31,12 +34,11 @@ public class MqttTestController {
|
||||
* @return 测试结果
|
||||
*/
|
||||
@PostMapping("/handleDeviceData")
|
||||
@ApiOperation("测试处理设备数据")
|
||||
public Map<String, Object> testHandleDeviceData(
|
||||
@RequestParam String topic,
|
||||
@RequestParam byte[] payload) {
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
try {
|
||||
// 调用handleDeviceData方法
|
||||
mqttService.handleDeviceData(topic, payload);
|
||||
@ -46,14 +48,12 @@ public class MqttTestController {
|
||||
result.put("message", "消息处理成功");
|
||||
result.put("topic", topic);
|
||||
result.put("payload", payload);
|
||||
|
||||
// 解析主题获取设备编号(模拟方法内部逻辑)
|
||||
String[] topicParts = topic.split("/");
|
||||
if (topicParts.length >= 3) {
|
||||
String deviceCode = topicParts[1];
|
||||
result.put("extractedDeviceCode", deviceCode);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("测试处理设备数据发生错误: {}", e.getMessage(), e);
|
||||
result.put("success", false);
|
||||
@ -66,10 +66,10 @@ public class MqttTestController {
|
||||
|
||||
/**
|
||||
* 生成测试数据
|
||||
*
|
||||
* @return 测试用的JSON数据
|
||||
*/
|
||||
@GetMapping("/generateTestData")
|
||||
@ApiOperation("生成测试数据")
|
||||
public Map<String, Object> generateTestData() {
|
||||
Map<String, Object> testData = new HashMap<>();
|
||||
testData.put("voltage", 12.5);
|
||||
|
||||
101
src/main/java/com/evobms/project/bms/domain/BmsChargeDetail.java
Normal file
101
src/main/java/com/evobms/project/bms/domain/BmsChargeDetail.java
Normal file
@ -0,0 +1,101 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.github.xiaoymin.knife4j.annotations.Ignore;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS充电过程详细数据对象 bms_charge_detail
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class BmsChargeDetail extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date timestamp;
|
||||
|
||||
/** 慢充电流(A) */
|
||||
@Excel(name = "慢充电流(A)")
|
||||
@ApiModelProperty(value = "慢充电流(A)")
|
||||
private BigDecimal acChargeCurrent;
|
||||
|
||||
/** 慢充电压(V) */
|
||||
@Excel(name = "慢充电压(V)")
|
||||
@ApiModelProperty(value = "慢充电压(V)")
|
||||
private BigDecimal acChargeVoltage;
|
||||
|
||||
/** 快充电流(A) */
|
||||
@Excel(name = "快充电流(A)")
|
||||
@ApiModelProperty(value = "快充电流(A)")
|
||||
private BigDecimal dcChargeCurrent;
|
||||
|
||||
/** 快充电压(V) */
|
||||
@Excel(name = "快充电压(V)")
|
||||
@ApiModelProperty(value = "快充电压(V)")
|
||||
private BigDecimal dcChargeVoltage;
|
||||
|
||||
/** 充电时长(min) */
|
||||
@Excel(name = "充电时长(min)")
|
||||
@ApiModelProperty(value = "充电时长min")
|
||||
private Long chargeTime;
|
||||
|
||||
/** 慢充停止码 */
|
||||
@Excel(name = "慢充停止码")
|
||||
@ApiModelProperty(value = "慢充停止码")
|
||||
private Integer acStopCode;
|
||||
|
||||
/** 快充停止码 */
|
||||
@Excel(name = "快充停止码")
|
||||
@ApiModelProperty(value = "快充停止码")
|
||||
private Integer dcStopCode;
|
||||
|
||||
/** 慢充CP值 */
|
||||
@Excel(name = "慢充CP值")
|
||||
@ApiModelProperty(value = "慢充CP值")
|
||||
private Integer acCpValue;
|
||||
|
||||
/** 慢充枪阻值 */
|
||||
@Excel(name = "慢充枪阻值")
|
||||
@ApiModelProperty(value = "慢充枪阻值")
|
||||
private Integer acGunResistance;
|
||||
|
||||
/** 充电阶段 */
|
||||
@Excel(name = "充电阶段")
|
||||
@ApiModelProperty(value = "充电阶段")
|
||||
private Integer chargingStage;
|
||||
|
||||
/** 慢充阶段 */
|
||||
@Excel(name = "慢充阶段")
|
||||
@ApiModelProperty(value = "慢充阶段")
|
||||
private Integer acStage;
|
||||
|
||||
/** 快充阶段 */
|
||||
@Excel(name = "快充阶段")
|
||||
@ApiModelProperty(value = "快充阶段")
|
||||
private Integer dcStage;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS充电座温度数据对象 bms_charge_temperature
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class BmsChargeTemperature extends BaseEntity
|
||||
{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
private Date timestamp;
|
||||
|
||||
/** 温度编号(1-8) */
|
||||
@Excel(name = "温度编号(1-8)")
|
||||
@ApiModelProperty(value = "温度编号(1-8)")
|
||||
private Integer tempIndex;
|
||||
|
||||
/** 温度(℃) */
|
||||
@Excel(name = "温度(℃)")
|
||||
@ApiModelProperty(value = "温度(℃)")
|
||||
private BigDecimal temperature;
|
||||
|
||||
}
|
||||
@ -1,203 +0,0 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* BMS设备对象 bms_device
|
||||
*
|
||||
* @author evobms
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@TableName("bms_device")
|
||||
public class BmsDevice extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 设备ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long deviceId;
|
||||
|
||||
/** 设备编号 */
|
||||
@Excel(name = "设备编号")
|
||||
private String deviceCode;
|
||||
|
||||
/** 设备名称 */
|
||||
@Excel(name = "设备名称")
|
||||
private String deviceName;
|
||||
|
||||
/** 设备类型 */
|
||||
@Excel(name = "设备类型")
|
||||
private String deviceType;
|
||||
|
||||
/** 设备状态(0正常 1停用) */
|
||||
@Excel(name = "设备状态", readConverterExp = "0=正常,1=停用")
|
||||
private String status;
|
||||
|
||||
/** 电池容量(Ah) */
|
||||
@Excel(name = "电池容量")
|
||||
private Double batteryCapacity;
|
||||
|
||||
/** 额定电压(V) */
|
||||
@Excel(name = "额定电压")
|
||||
private Double ratedVoltage;
|
||||
|
||||
/** 当前电压(V) */
|
||||
private Double currentVoltage;
|
||||
|
||||
/** 当前电流(A) */
|
||||
private Double currentCurrent;
|
||||
|
||||
/** 剩余电量(%) */
|
||||
private Double remainingCapacity;
|
||||
|
||||
/** 温度(℃) */
|
||||
private Double temperature;
|
||||
|
||||
/** 最后通信时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date lastCommTime;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
@TableLogic
|
||||
private String delFlag;
|
||||
|
||||
/** 版本号(乐观锁) */
|
||||
@Version
|
||||
private Integer version;
|
||||
|
||||
public void setDeviceId(Long deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public Long getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceCode(String deviceCode) {
|
||||
this.deviceCode = deviceCode;
|
||||
}
|
||||
|
||||
public String getDeviceCode() {
|
||||
return deviceCode;
|
||||
}
|
||||
|
||||
public void setDeviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public void setDeviceType(String deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
}
|
||||
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setBatteryCapacity(Double batteryCapacity) {
|
||||
this.batteryCapacity = batteryCapacity;
|
||||
}
|
||||
|
||||
public Double getBatteryCapacity() {
|
||||
return batteryCapacity;
|
||||
}
|
||||
|
||||
public void setRatedVoltage(Double ratedVoltage) {
|
||||
this.ratedVoltage = ratedVoltage;
|
||||
}
|
||||
|
||||
public Double getRatedVoltage() {
|
||||
return ratedVoltage;
|
||||
}
|
||||
|
||||
public void setCurrentVoltage(Double currentVoltage) {
|
||||
this.currentVoltage = currentVoltage;
|
||||
}
|
||||
|
||||
public Double getCurrentVoltage() {
|
||||
return currentVoltage;
|
||||
}
|
||||
|
||||
public void setCurrentCurrent(Double currentCurrent) {
|
||||
this.currentCurrent = currentCurrent;
|
||||
}
|
||||
|
||||
public Double getCurrentCurrent() {
|
||||
return currentCurrent;
|
||||
}
|
||||
|
||||
public void setRemainingCapacity(Double remainingCapacity) {
|
||||
this.remainingCapacity = remainingCapacity;
|
||||
}
|
||||
|
||||
public Double getRemainingCapacity() {
|
||||
return remainingCapacity;
|
||||
}
|
||||
|
||||
public void setTemperature(Double temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setLastCommTime(Date lastCommTime) {
|
||||
this.lastCommTime = lastCommTime;
|
||||
}
|
||||
|
||||
public Date getLastCommTime() {
|
||||
return lastCommTime;
|
||||
}
|
||||
|
||||
public void setDelFlag(String delFlag) {
|
||||
this.delFlag = delFlag;
|
||||
}
|
||||
|
||||
public String getDelFlag() {
|
||||
return delFlag;
|
||||
}
|
||||
|
||||
public void setVersion(Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BmsDevice{" +
|
||||
"deviceId=" + deviceId +
|
||||
", deviceCode='" + deviceCode + '\'' +
|
||||
", deviceName='" + deviceName + '\'' +
|
||||
", deviceType='" + deviceType + '\'' +
|
||||
", status='" + status + '\'' +
|
||||
", batteryCapacity=" + batteryCapacity +
|
||||
", ratedVoltage=" + ratedVoltage +
|
||||
", currentVoltage=" + currentVoltage +
|
||||
", currentCurrent=" + currentCurrent +
|
||||
", remainingCapacity=" + remainingCapacity +
|
||||
", temperature=" + temperature +
|
||||
", lastCommTime=" + lastCommTime +
|
||||
", delFlag='" + delFlag + '\'' +
|
||||
", version=" + version +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS实时运行数据对象 bms_runtime_data
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BmsRuntimeData extends BaseEntity
|
||||
{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date timestamp;
|
||||
|
||||
/** 车速(km/h) */
|
||||
@Excel(name = "车速(km/h)")
|
||||
@ApiModelProperty(value = "车速(km/h)")
|
||||
private BigDecimal vehicleSpeed;
|
||||
|
||||
/** 总里程(km) */
|
||||
@Excel(name = "总里程(km)")
|
||||
@ApiModelProperty(value = "总里程(km)")
|
||||
private Long mileage;
|
||||
|
||||
/** 系统电压(V) */
|
||||
@Excel(name = "系统电压(V)")
|
||||
@ApiModelProperty(value = "系统电压(V)")
|
||||
private BigDecimal systemVoltage;
|
||||
|
||||
/** 系统电流(A) */
|
||||
@Excel(name = "系统电流(A)")
|
||||
@ApiModelProperty(value = "系统电流(A)")
|
||||
private BigDecimal systemCurrent;
|
||||
|
||||
/** 绝缘电阻(KΩ) */
|
||||
@Excel(name = "绝缘电阻(KΩ)")
|
||||
@ApiModelProperty(value = "绝缘电阻(KΩ)")
|
||||
private Long insulationResistance;
|
||||
|
||||
/** 最大SOC(%) */
|
||||
@Excel(name = "最大SOC(%)")
|
||||
@ApiModelProperty(value = "最大SOC(%)")
|
||||
private BigDecimal socMax;
|
||||
|
||||
/** 最小SOC(%) */
|
||||
@Excel(name = "最小SOC(%)")
|
||||
@ApiModelProperty(value = "最小SOC(%)")
|
||||
private BigDecimal socMin;
|
||||
|
||||
/** GPV电压(V) */
|
||||
@Excel(name = "GPV电压(V)")
|
||||
@ApiModelProperty(value = "GPV电压(V)")
|
||||
private BigDecimal gpvVoltage;
|
||||
|
||||
/** 行车阶段 */
|
||||
@Excel(name = "行车阶段")
|
||||
@ApiModelProperty(value = "行车阶段")
|
||||
private Integer runStatus;
|
||||
|
||||
/** 行车上电阶段 */
|
||||
@Excel(name = "行车上电阶段")
|
||||
@ApiModelProperty(value = "行车上电阶段")
|
||||
private Integer powerStatus;
|
||||
|
||||
}
|
||||
113
src/main/java/com/evobms/project/bms/domain/BmsSopData.java
Normal file
113
src/main/java/com/evobms/project/bms/domain/BmsSopData.java
Normal file
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS功率能力(SOP)数据对象 bms_sop_data
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BmsSopData extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@TableField("`timestamp`")
|
||||
private Date timestamp;
|
||||
|
||||
/** 10秒放电SOP(A) */
|
||||
@Excel(name = "10秒放电SOP(A)")
|
||||
@ApiModelProperty(value = "10秒放电SOP(A)")
|
||||
@TableField("discharge_sop_10s")
|
||||
private Long dischargeSop10s;
|
||||
|
||||
/** 30秒放电SOP(A) */
|
||||
@Excel(name = "30秒放电SOP(A)")
|
||||
@ApiModelProperty(value = "30秒放电SOP(A)")
|
||||
@TableField("discharge_sop_30s")
|
||||
private Long dischargeSop30s;
|
||||
|
||||
/** 60秒放电SOP(A) */
|
||||
@Excel(name = "60秒放电SOP(A)")
|
||||
@ApiModelProperty(value = "60秒放电SOP(A)")
|
||||
@TableField("discharge_sop_60s")
|
||||
private Long dischargeSop60s;
|
||||
|
||||
/** 持续放电SOP(A) */
|
||||
@Excel(name = "持续放电SOP(A)")
|
||||
@ApiModelProperty(value = "持续放电SOP(A)")
|
||||
@TableField("discharge_sop_continuous")
|
||||
private Long dischargeSopContinuous;
|
||||
|
||||
/** 放电融合SOP(A) */
|
||||
@Excel(name = "放电融合SOP(A)")
|
||||
@ApiModelProperty(value = "放电融合SOP(A)")
|
||||
private Long dischargeSopTotal;
|
||||
|
||||
/** 10秒回馈SOP(A) */
|
||||
@Excel(name = "10秒回馈SOP(A)")
|
||||
@ApiModelProperty(value = "10秒回馈SOP(A)")
|
||||
@TableField("regen_sop_10s")
|
||||
private Long regenSop10s;
|
||||
|
||||
/** 30秒回馈SOP(A) */
|
||||
@Excel(name = "30秒回馈SOP(A)")
|
||||
@ApiModelProperty(value = "30秒回馈SOP(A)")
|
||||
@TableField("regen_sop_30s")
|
||||
private Long regenSop30s;
|
||||
|
||||
/** 60秒回馈SOP(A) */
|
||||
@Excel(name = "60秒回馈SOP(A)")
|
||||
@ApiModelProperty(value = "60秒回馈SOP(A)")
|
||||
@TableField("regen_sop_60s")
|
||||
private Long regenSop60s;
|
||||
|
||||
/** 持续回馈SOP(A) */
|
||||
@Excel(name = "持续回馈SOP(A)")
|
||||
@ApiModelProperty(value = "持续回馈SOP(A)")
|
||||
@TableField("regen_sop_continuous")
|
||||
private Long regenSopContinuous;
|
||||
|
||||
/** 回馈融合SOP(A) */
|
||||
@Excel(name = "回馈融合SOP(A)")
|
||||
@ApiModelProperty(value = "回馈融合SOP(A)")
|
||||
private Long regenSopTotal;
|
||||
|
||||
/** 充电SOP(A) */
|
||||
@Excel(name = "充电SOP(A)")
|
||||
@ApiModelProperty(value = "充电SOP(A)")
|
||||
@TableField("charge_sop")
|
||||
private Long chargeSop;
|
||||
|
||||
/** 慢充SOP(A) */
|
||||
@Excel(name = "慢充SOP(A)")
|
||||
@ApiModelProperty(value = "慢充SOP(A)")
|
||||
@TableField("ac_charge_sop")
|
||||
private Long acChargeSop;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS系统状态数据对象 bms_system_status
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class BmsSystemStatus extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
private Date timestamp;
|
||||
|
||||
/** 继电器状态 */
|
||||
@Excel(name = "继电器状态")
|
||||
@ApiModelProperty(value = "继电器状态")
|
||||
private Long relayStatus;
|
||||
|
||||
/** ON/A+/CC状态 */
|
||||
@Excel(name = "ON/A+/CC状态")
|
||||
@ApiModelProperty(value = "ON/A+/CC状态")
|
||||
private Long onaaccStatus;
|
||||
|
||||
/** 系统复位次数 */
|
||||
@Excel(name = "系统复位次数")
|
||||
@ApiModelProperty(value = "系统复位次数")
|
||||
private Long resetCount;
|
||||
|
||||
/** 电池循环次数 */
|
||||
@Excel(name = "电池循环次数")
|
||||
@ApiModelProperty(value = "电池循环次数")
|
||||
private Long cycleCount;
|
||||
/** 电池循环次数 */
|
||||
@Excel(name = "电池芯单体数")
|
||||
@ApiModelProperty(value = "电池芯单体数")
|
||||
private Long cellCount;
|
||||
|
||||
/** 2.5V采样电压(V) */
|
||||
@Excel(name = "2.5V采样电压(V)")
|
||||
@ApiModelProperty(value = "2.5V采样电压(V)")
|
||||
@TableField("sample_25v")
|
||||
private BigDecimal sample25v;
|
||||
|
||||
/** 5V采样电压(V) */
|
||||
@Excel(name = "5V采样电压(V)")
|
||||
@ApiModelProperty(value = "5V采样电压(V)")
|
||||
@TableField("sample_5v")
|
||||
private BigDecimal sample5v;
|
||||
|
||||
/** 测温点数量(V) */
|
||||
@Excel(name = "测温点数量(V)")
|
||||
@ApiModelProperty(value = "测温点数量(V)")
|
||||
@TableField("temp_sensor_count")
|
||||
private Integer tempSensorCount;
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.evobms.project.bms.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* BMS电压通道数据对象 bms_voltage_channel_data
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class BmsVoltageChannelData extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
private Date timestamp;
|
||||
|
||||
/** 通道类型(RTP/RTN) */
|
||||
@Excel(name = "通道类型(RTP/RTN)")
|
||||
@ApiModelProperty(value = "通道类型(RTP/RTN)")
|
||||
private String channelType;
|
||||
|
||||
/** 通道编号 */
|
||||
@Excel(name = "通道编号")
|
||||
@ApiModelProperty(value = "通道编号")
|
||||
private Integer channelIndex;
|
||||
|
||||
/** 电压(V) */
|
||||
@Excel(name = "电压(V)")
|
||||
@ApiModelProperty(value = "电压(V)")
|
||||
private BigDecimal voltage;
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsChargeDetail;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS充电过程详细数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsChargeDetailMapper extends BaseMapper<BmsChargeDetail> {
|
||||
/**
|
||||
* 查询BMS充电过程详细数据
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return BMS充电过程详细数据
|
||||
*/
|
||||
public BmsChargeDetail selectBmsChargeDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS充电过程详细数据列表
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return BMS充电过程详细数据集合
|
||||
*/
|
||||
public List<BmsChargeDetail> selectBmsChargeDetailList(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 新增BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsChargeDetail(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 修改BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsChargeDetail(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 删除BMS充电过程详细数据
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电过程详细数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeDetailByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsChargeTemperature;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS充电座温度数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsChargeTemperatureMapper extends BaseMapper<BmsChargeTemperature> {
|
||||
/**
|
||||
* 查询BMS充电座温度数据
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return BMS充电座温度数据
|
||||
*/
|
||||
public BmsChargeTemperature selectBmsChargeTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS充电座温度数据列表
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return BMS充电座温度数据集合
|
||||
*/
|
||||
public List<BmsChargeTemperature> selectBmsChargeTemperatureList(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 新增BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 修改BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 删除BMS充电座温度数据
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电座温度数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeTemperatureByIds(Long[] ids);
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.evobms.project.bms.domain.BmsDevice;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BMS设备Mapper接口
|
||||
*
|
||||
* @author evobms
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Mapper
|
||||
public interface BmsDeviceMapper extends BaseMapper<BmsDevice> {
|
||||
|
||||
/**
|
||||
* 查询BMS设备列表
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return BMS设备集合
|
||||
*/
|
||||
List<BmsDevice> selectBmsDeviceList(BmsDevice bmsDevice);
|
||||
|
||||
/**
|
||||
* 根据设备编号查询设备信息
|
||||
*
|
||||
* @param deviceCode 设备编号
|
||||
* @return BMS设备
|
||||
*/
|
||||
BmsDevice selectBmsDeviceByCode(@Param("deviceCode") String deviceCode);
|
||||
|
||||
/**
|
||||
* 批量更新设备状态
|
||||
*
|
||||
* @param deviceIds 设备ID数组
|
||||
* @param status 状态
|
||||
* @return 结果
|
||||
*/
|
||||
int updateBmsDeviceStatus(@Param("deviceIds") Long[] deviceIds, @Param("status") String status);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsRuntimeData;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS实时运行数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsRuntimeDataMapper extends BaseMapper<BmsRuntimeData> {
|
||||
/**
|
||||
* 查询BMS实时运行数据
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return BMS实时运行数据
|
||||
*/
|
||||
public BmsRuntimeData selectBmsRuntimeDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS实时运行数据列表
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return BMS实时运行数据集合
|
||||
*/
|
||||
public List<BmsRuntimeData> selectBmsRuntimeDataList(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 新增BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsRuntimeData(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 修改BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsRuntimeData(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 删除BMS实时运行数据
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsRuntimeDataById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS实时运行数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsRuntimeDataByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsSopData;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS功率能力(SOP)数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsSopDataMapper extends BaseMapper<BmsSopData> {
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return BMS功率能力(SOP)数据
|
||||
*/
|
||||
public BmsSopData selectBmsSopDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据列表
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return BMS功率能力(SOP)数据集合
|
||||
*/
|
||||
public List<BmsSopData> selectBmsSopDataList(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 新增BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsSopData(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 修改BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsSopData(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 删除BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSopDataById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSopDataByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsSystemStatus;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS系统状态数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsSystemStatusMapper extends BaseMapper<BmsSystemStatus> {
|
||||
/**
|
||||
* 查询BMS系统状态数据
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return BMS系统状态数据
|
||||
*/
|
||||
public BmsSystemStatus selectBmsSystemStatusById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS系统状态数据列表
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return BMS系统状态数据集合
|
||||
*/
|
||||
public List<BmsSystemStatus> selectBmsSystemStatusList(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 新增BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsSystemStatus(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 修改BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsSystemStatus(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 删除BMS系统状态数据
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSystemStatusById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS系统状态数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSystemStatusByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsVoltageChannelData;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* BMS电压通道数据Mapper接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface BmsVoltageChannelDataMapper extends BaseMapper<BmsVoltageChannelData> {
|
||||
/**
|
||||
* 查询BMS电压通道数据
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return BMS电压通道数据
|
||||
*/
|
||||
public BmsVoltageChannelData selectBmsVoltageChannelDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS电压通道数据列表
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return BMS电压通道数据集合
|
||||
*/
|
||||
public List<BmsVoltageChannelData> selectBmsVoltageChannelDataList(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 新增BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 修改BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 删除BMS电压通道数据
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsVoltageChannelDataById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除BMS电压通道数据
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsVoltageChannelDataByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsChargeDetail;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS充电过程详细数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsChargeDetailService extends IService<BmsChargeDetail> {
|
||||
/**
|
||||
* 查询BMS充电过程详细数据
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return BMS充电过程详细数据
|
||||
*/
|
||||
public BmsChargeDetail selectBmsChargeDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS充电过程详细数据列表
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return BMS充电过程详细数据集合
|
||||
*/
|
||||
public List<BmsChargeDetail> selectBmsChargeDetailList(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 新增BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsChargeDetail(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 修改BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsChargeDetail(BmsChargeDetail bmsChargeDetail);
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电过程详细数据
|
||||
*
|
||||
* @param ids 需要删除的BMS充电过程详细数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeDetailByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS充电过程详细数据信息
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeDetailById(Long id);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsChargeTemperature;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS充电座温度数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsChargeTemperatureService extends IService<BmsChargeTemperature> {
|
||||
/**
|
||||
* 查询BMS充电座温度数据
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return BMS充电座温度数据
|
||||
*/
|
||||
public BmsChargeTemperature selectBmsChargeTemperatureById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS充电座温度数据列表
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return BMS充电座温度数据集合
|
||||
*/
|
||||
public List<BmsChargeTemperature> selectBmsChargeTemperatureList(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 新增BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 修改BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature);
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电座温度数据
|
||||
*
|
||||
* @param ids 需要删除的BMS充电座温度数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeTemperatureByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS充电座温度数据信息
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsChargeTemperatureById(Long id);
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.evobms.project.bms.domain.BmsDevice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BMS设备Service接口
|
||||
*
|
||||
* @author evobms
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
public interface IBmsDeviceService extends IService<BmsDevice> {
|
||||
|
||||
/**
|
||||
* 查询BMS设备
|
||||
*
|
||||
* @param deviceId BMS设备主键
|
||||
* @return BMS设备
|
||||
*/
|
||||
BmsDevice selectBmsDeviceByDeviceId(Long deviceId);
|
||||
|
||||
/**
|
||||
* 查询BMS设备列表
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return BMS设备集合
|
||||
*/
|
||||
List<BmsDevice> selectBmsDeviceList(BmsDevice bmsDevice);
|
||||
|
||||
/**
|
||||
* 新增BMS设备
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return 结果
|
||||
*/
|
||||
int insertBmsDevice(BmsDevice bmsDevice);
|
||||
|
||||
/**
|
||||
* 修改BMS设备
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return 结果
|
||||
*/
|
||||
int updateBmsDevice(BmsDevice bmsDevice);
|
||||
|
||||
/**
|
||||
* 批量删除BMS设备
|
||||
*
|
||||
* @param deviceIds 需要删除的BMS设备主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteBmsDeviceByDeviceIds(Long[] deviceIds);
|
||||
|
||||
/**
|
||||
* 删除BMS设备信息
|
||||
*
|
||||
* @param deviceId BMS设备主键
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteBmsDeviceByDeviceId(Long deviceId);
|
||||
|
||||
/**
|
||||
* 根据设备编号查询设备信息
|
||||
*
|
||||
* @param deviceCode 设备编号
|
||||
* @return BMS设备
|
||||
*/
|
||||
BmsDevice selectBmsDeviceByCode(String deviceCode);
|
||||
|
||||
/**
|
||||
* 批量更新设备状态
|
||||
*
|
||||
* @param deviceIds 设备ID数组
|
||||
* @param status 状态
|
||||
* @return 结果
|
||||
*/
|
||||
int updateBmsDeviceStatus(Long[] deviceIds, String status);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsRuntimeData;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS实时运行数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsRuntimeDataService extends IService<BmsRuntimeData> {
|
||||
/**
|
||||
* 查询BMS实时运行数据
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return BMS实时运行数据
|
||||
*/
|
||||
public BmsRuntimeData selectBmsRuntimeDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS实时运行数据列表
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return BMS实时运行数据集合
|
||||
*/
|
||||
public List<BmsRuntimeData> selectBmsRuntimeDataList(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 新增BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsRuntimeData(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 修改BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsRuntimeData(BmsRuntimeData bmsRuntimeData);
|
||||
|
||||
/**
|
||||
* 批量删除BMS实时运行数据
|
||||
*
|
||||
* @param ids 需要删除的BMS实时运行数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsRuntimeDataByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS实时运行数据信息
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsRuntimeDataById(Long id);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsSopData;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS功率能力(SOP)数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsSopDataService extends IService<BmsSopData> {
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return BMS功率能力(SOP)数据
|
||||
*/
|
||||
public BmsSopData selectBmsSopDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据列表
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return BMS功率能力(SOP)数据集合
|
||||
*/
|
||||
public List<BmsSopData> selectBmsSopDataList(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 新增BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsSopData(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 修改BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsSopData(BmsSopData bmsSopData);
|
||||
|
||||
/**
|
||||
* 批量删除BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param ids 需要删除的BMS功率能力(SOP)数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSopDataByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS功率能力(SOP)数据信息
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSopDataById(Long id);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsSystemStatus;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS系统状态数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsSystemStatusService extends IService<BmsSystemStatus> {
|
||||
/**
|
||||
* 查询BMS系统状态数据
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return BMS系统状态数据
|
||||
*/
|
||||
public BmsSystemStatus selectBmsSystemStatusById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS系统状态数据列表
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return BMS系统状态数据集合
|
||||
*/
|
||||
public List<BmsSystemStatus> selectBmsSystemStatusList(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 新增BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsSystemStatus(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 修改BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsSystemStatus(BmsSystemStatus bmsSystemStatus);
|
||||
|
||||
/**
|
||||
* 批量删除BMS系统状态数据
|
||||
*
|
||||
* @param ids 需要删除的BMS系统状态数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSystemStatusByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS系统状态数据信息
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsSystemStatusById(Long id);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.bms.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.bms.domain.BmsVoltageChannelData;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* BMS电压通道数据Service接口
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
public interface IBmsVoltageChannelDataService extends IService<BmsVoltageChannelData> {
|
||||
/**
|
||||
* 查询BMS电压通道数据
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return BMS电压通道数据
|
||||
*/
|
||||
public BmsVoltageChannelData selectBmsVoltageChannelDataById(Long id);
|
||||
|
||||
/**
|
||||
* 查询BMS电压通道数据列表
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return BMS电压通道数据集合
|
||||
*/
|
||||
public List<BmsVoltageChannelData> selectBmsVoltageChannelDataList(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 新增BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 修改BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData);
|
||||
|
||||
/**
|
||||
* 批量删除BMS电压通道数据
|
||||
*
|
||||
* @param ids 需要删除的BMS电压通道数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsVoltageChannelDataByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除BMS电压通道数据信息
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsVoltageChannelDataById(Long id);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsChargeDetailMapper;
|
||||
import com.evobms.project.bms.domain.BmsChargeDetail;
|
||||
import com.evobms.project.bms.service.IBmsChargeDetailService;
|
||||
|
||||
/**
|
||||
* BMS充电过程详细数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsChargeDetailServiceImpl extends ServiceImpl<BmsChargeDetailMapper, BmsChargeDetail> implements IBmsChargeDetailService
|
||||
{
|
||||
@Autowired
|
||||
private BmsChargeDetailMapper bmsChargeDetailMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS充电过程详细数据
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return BMS充电过程详细数据
|
||||
*/
|
||||
@Override
|
||||
public BmsChargeDetail selectBmsChargeDetailById(Long id)
|
||||
{
|
||||
return bmsChargeDetailMapper.selectBmsChargeDetailById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS充电过程详细数据列表
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return BMS充电过程详细数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsChargeDetail> selectBmsChargeDetailList(BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
return bmsChargeDetailMapper.selectBmsChargeDetailList(bmsChargeDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsChargeDetail(BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
bmsChargeDetail.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsChargeDetailMapper.insertBmsChargeDetail(bmsChargeDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS充电过程详细数据
|
||||
*
|
||||
* @param bmsChargeDetail BMS充电过程详细数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsChargeDetail(BmsChargeDetail bmsChargeDetail)
|
||||
{
|
||||
bmsChargeDetail.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsChargeDetailMapper.updateBmsChargeDetail(bmsChargeDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电过程详细数据
|
||||
*
|
||||
* @param ids 需要删除的BMS充电过程详细数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsChargeDetailByIds(Long[] ids)
|
||||
{
|
||||
return bmsChargeDetailMapper.deleteBmsChargeDetailByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS充电过程详细数据信息
|
||||
*
|
||||
* @param id BMS充电过程详细数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsChargeDetailById(Long id)
|
||||
{
|
||||
return bmsChargeDetailMapper.deleteBmsChargeDetailById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsChargeTemperatureMapper;
|
||||
import com.evobms.project.bms.domain.BmsChargeTemperature;
|
||||
import com.evobms.project.bms.service.IBmsChargeTemperatureService;
|
||||
|
||||
/**
|
||||
* BMS充电座温度数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsChargeTemperatureServiceImpl extends ServiceImpl<BmsChargeTemperatureMapper, BmsChargeTemperature> implements IBmsChargeTemperatureService
|
||||
{
|
||||
@Autowired
|
||||
private BmsChargeTemperatureMapper bmsChargeTemperatureMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS充电座温度数据
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return BMS充电座温度数据
|
||||
*/
|
||||
@Override
|
||||
public BmsChargeTemperature selectBmsChargeTemperatureById(Long id)
|
||||
{
|
||||
return bmsChargeTemperatureMapper.selectBmsChargeTemperatureById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS充电座温度数据列表
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return BMS充电座温度数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsChargeTemperature> selectBmsChargeTemperatureList(BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
return bmsChargeTemperatureMapper.selectBmsChargeTemperatureList(bmsChargeTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
bmsChargeTemperature.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsChargeTemperatureMapper.insertBmsChargeTemperature(bmsChargeTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS充电座温度数据
|
||||
*
|
||||
* @param bmsChargeTemperature BMS充电座温度数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsChargeTemperature(BmsChargeTemperature bmsChargeTemperature)
|
||||
{
|
||||
bmsChargeTemperature.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsChargeTemperatureMapper.updateBmsChargeTemperature(bmsChargeTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS充电座温度数据
|
||||
*
|
||||
* @param ids 需要删除的BMS充电座温度数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsChargeTemperatureByIds(Long[] ids)
|
||||
{
|
||||
return bmsChargeTemperatureMapper.deleteBmsChargeTemperatureByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS充电座温度数据信息
|
||||
*
|
||||
* @param id BMS充电座温度数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsChargeTemperatureById(Long id)
|
||||
{
|
||||
return bmsChargeTemperatureMapper.deleteBmsChargeTemperatureById(id);
|
||||
}
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import com.evobms.project.bms.domain.BmsDevice;
|
||||
import com.evobms.project.bms.mapper.BmsDeviceMapper;
|
||||
import com.evobms.project.bms.service.IBmsDeviceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BMS设备Service业务层处理
|
||||
*
|
||||
* @author evobms
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Service
|
||||
public class BmsDeviceServiceImpl extends ServiceImpl<BmsDeviceMapper, BmsDevice> implements IBmsDeviceService {
|
||||
|
||||
@Autowired
|
||||
private BmsDeviceMapper bmsDeviceMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS设备
|
||||
*
|
||||
* @param deviceId BMS设备主键
|
||||
* @return BMS设备
|
||||
*/
|
||||
@Override
|
||||
public BmsDevice selectBmsDeviceByDeviceId(Long deviceId) {
|
||||
return bmsDeviceMapper.selectById(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS设备列表
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return BMS设备
|
||||
*/
|
||||
@Override
|
||||
public List<BmsDevice> selectBmsDeviceList(BmsDevice bmsDevice) {
|
||||
return bmsDeviceMapper.selectBmsDeviceList(bmsDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS设备
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsDevice(BmsDevice bmsDevice) {
|
||||
bmsDevice.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsDeviceMapper.insert(bmsDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS设备
|
||||
*
|
||||
* @param bmsDevice BMS设备
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsDevice(BmsDevice bmsDevice) {
|
||||
bmsDevice.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsDeviceMapper.updateById(bmsDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS设备
|
||||
*
|
||||
* @param deviceIds 需要删除的BMS设备主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsDeviceByDeviceIds(Long[] deviceIds) {
|
||||
return bmsDeviceMapper.deleteBatchIds(java.util.Arrays.asList(deviceIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS设备信息
|
||||
*
|
||||
* @param deviceId BMS设备主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsDeviceByDeviceId(Long deviceId) {
|
||||
return bmsDeviceMapper.deleteById(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备编号查询设备信息
|
||||
*
|
||||
* @param deviceCode 设备编号
|
||||
* @return BMS设备
|
||||
*/
|
||||
@Override
|
||||
public BmsDevice selectBmsDeviceByCode(String deviceCode) {
|
||||
return bmsDeviceMapper.selectBmsDeviceByCode(deviceCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新设备状态
|
||||
*
|
||||
* @param deviceIds 设备ID数组
|
||||
* @param status 状态
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsDeviceStatus(Long[] deviceIds, String status) {
|
||||
return bmsDeviceMapper.updateBmsDeviceStatus(deviceIds, status);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsRuntimeDataMapper;
|
||||
import com.evobms.project.bms.domain.BmsRuntimeData;
|
||||
import com.evobms.project.bms.service.IBmsRuntimeDataService;
|
||||
|
||||
/**
|
||||
* BMS实时运行数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsRuntimeDataServiceImpl extends ServiceImpl<BmsRuntimeDataMapper, BmsRuntimeData> implements IBmsRuntimeDataService
|
||||
{
|
||||
@Autowired
|
||||
private BmsRuntimeDataMapper bmsRuntimeDataMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS实时运行数据
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return BMS实时运行数据
|
||||
*/
|
||||
@Override
|
||||
public BmsRuntimeData selectBmsRuntimeDataById(Long id)
|
||||
{
|
||||
return bmsRuntimeDataMapper.selectBmsRuntimeDataById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS实时运行数据列表
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return BMS实时运行数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsRuntimeData> selectBmsRuntimeDataList(BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
return bmsRuntimeDataMapper.selectBmsRuntimeDataList(bmsRuntimeData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsRuntimeData(BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
bmsRuntimeData.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsRuntimeDataMapper.insertBmsRuntimeData(bmsRuntimeData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS实时运行数据
|
||||
*
|
||||
* @param bmsRuntimeData BMS实时运行数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsRuntimeData(BmsRuntimeData bmsRuntimeData)
|
||||
{
|
||||
bmsRuntimeData.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsRuntimeDataMapper.updateBmsRuntimeData(bmsRuntimeData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS实时运行数据
|
||||
*
|
||||
* @param ids 需要删除的BMS实时运行数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsRuntimeDataByIds(Long[] ids)
|
||||
{
|
||||
return bmsRuntimeDataMapper.deleteBmsRuntimeDataByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS实时运行数据信息
|
||||
*
|
||||
* @param id BMS实时运行数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsRuntimeDataById(Long id)
|
||||
{
|
||||
return bmsRuntimeDataMapper.deleteBmsRuntimeDataById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsSopDataMapper;
|
||||
import com.evobms.project.bms.domain.BmsSopData;
|
||||
import com.evobms.project.bms.service.IBmsSopDataService;
|
||||
|
||||
/**
|
||||
* BMS功率能力(SOP)数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsSopDataServiceImpl extends ServiceImpl<BmsSopDataMapper, BmsSopData> implements IBmsSopDataService
|
||||
{
|
||||
@Autowired
|
||||
private BmsSopDataMapper bmsSopDataMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return BMS功率能力(SOP)数据
|
||||
*/
|
||||
@Override
|
||||
public BmsSopData selectBmsSopDataById(Long id)
|
||||
{
|
||||
return bmsSopDataMapper.selectBmsSopDataById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS功率能力(SOP)数据列表
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return BMS功率能力(SOP)数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsSopData> selectBmsSopDataList(BmsSopData bmsSopData)
|
||||
{
|
||||
return bmsSopDataMapper.selectBmsSopDataList(bmsSopData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsSopData(BmsSopData bmsSopData)
|
||||
{
|
||||
bmsSopData.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsSopDataMapper.insertBmsSopData(bmsSopData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param bmsSopData BMS功率能力(SOP)数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsSopData(BmsSopData bmsSopData)
|
||||
{
|
||||
bmsSopData.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsSopDataMapper.updateBmsSopData(bmsSopData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS功率能力(SOP)数据
|
||||
*
|
||||
* @param ids 需要删除的BMS功率能力(SOP)数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsSopDataByIds(Long[] ids)
|
||||
{
|
||||
return bmsSopDataMapper.deleteBmsSopDataByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS功率能力(SOP)数据信息
|
||||
*
|
||||
* @param id BMS功率能力(SOP)数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsSopDataById(Long id)
|
||||
{
|
||||
return bmsSopDataMapper.deleteBmsSopDataById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsSystemStatusMapper;
|
||||
import com.evobms.project.bms.domain.BmsSystemStatus;
|
||||
import com.evobms.project.bms.service.IBmsSystemStatusService;
|
||||
|
||||
/**
|
||||
* BMS系统状态数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsSystemStatusServiceImpl extends ServiceImpl<BmsSystemStatusMapper, BmsSystemStatus> implements IBmsSystemStatusService
|
||||
{
|
||||
@Autowired
|
||||
private BmsSystemStatusMapper bmsSystemStatusMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS系统状态数据
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return BMS系统状态数据
|
||||
*/
|
||||
@Override
|
||||
public BmsSystemStatus selectBmsSystemStatusById(Long id)
|
||||
{
|
||||
return bmsSystemStatusMapper.selectBmsSystemStatusById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS系统状态数据列表
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return BMS系统状态数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsSystemStatus> selectBmsSystemStatusList(BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
return bmsSystemStatusMapper.selectBmsSystemStatusList(bmsSystemStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsSystemStatus(BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
bmsSystemStatus.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsSystemStatusMapper.insertBmsSystemStatus(bmsSystemStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS系统状态数据
|
||||
*
|
||||
* @param bmsSystemStatus BMS系统状态数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsSystemStatus(BmsSystemStatus bmsSystemStatus)
|
||||
{
|
||||
bmsSystemStatus.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsSystemStatusMapper.updateBmsSystemStatus(bmsSystemStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS系统状态数据
|
||||
*
|
||||
* @param ids 需要删除的BMS系统状态数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsSystemStatusByIds(Long[] ids)
|
||||
{
|
||||
return bmsSystemStatusMapper.deleteBmsSystemStatusByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS系统状态数据信息
|
||||
*
|
||||
* @param id BMS系统状态数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsSystemStatusById(Long id)
|
||||
{
|
||||
return bmsSystemStatusMapper.deleteBmsSystemStatusById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.evobms.project.bms.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.bms.mapper.BmsVoltageChannelDataMapper;
|
||||
import com.evobms.project.bms.domain.BmsVoltageChannelData;
|
||||
import com.evobms.project.bms.service.IBmsVoltageChannelDataService;
|
||||
|
||||
/**
|
||||
* BMS电压通道数据Service业务层处理
|
||||
*
|
||||
* @author tzy
|
||||
* @date 2026-02-23
|
||||
*/
|
||||
@Service
|
||||
public class BmsVoltageChannelDataServiceImpl extends ServiceImpl<BmsVoltageChannelDataMapper, BmsVoltageChannelData> implements IBmsVoltageChannelDataService
|
||||
{
|
||||
@Autowired
|
||||
private BmsVoltageChannelDataMapper bmsVoltageChannelDataMapper;
|
||||
|
||||
/**
|
||||
* 查询BMS电压通道数据
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return BMS电压通道数据
|
||||
*/
|
||||
@Override
|
||||
public BmsVoltageChannelData selectBmsVoltageChannelDataById(Long id)
|
||||
{
|
||||
return bmsVoltageChannelDataMapper.selectBmsVoltageChannelDataById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询BMS电压通道数据列表
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return BMS电压通道数据
|
||||
*/
|
||||
@Override
|
||||
public List<BmsVoltageChannelData> selectBmsVoltageChannelDataList(BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
return bmsVoltageChannelDataMapper.selectBmsVoltageChannelDataList(bmsVoltageChannelData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
bmsVoltageChannelData.setCreateTime(DateUtils.getNowDate());
|
||||
return bmsVoltageChannelDataMapper.insertBmsVoltageChannelData(bmsVoltageChannelData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改BMS电压通道数据
|
||||
*
|
||||
* @param bmsVoltageChannelData BMS电压通道数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsVoltageChannelData(BmsVoltageChannelData bmsVoltageChannelData)
|
||||
{
|
||||
bmsVoltageChannelData.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsVoltageChannelDataMapper.updateBmsVoltageChannelData(bmsVoltageChannelData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除BMS电压通道数据
|
||||
*
|
||||
* @param ids 需要删除的BMS电压通道数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsVoltageChannelDataByIds(Long[] ids)
|
||||
{
|
||||
return bmsVoltageChannelDataMapper.deleteBmsVoltageChannelDataByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除BMS电压通道数据信息
|
||||
*
|
||||
* @param id BMS电压通道数据主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteBmsVoltageChannelDataById(Long id)
|
||||
{
|
||||
return bmsVoltageChannelDataMapper.deleteBmsVoltageChannelDataById(id);
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,18 @@ import com.evobms.project.iot.service.DeviceTokenService;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import com.evobms.project.system.service.IBmsDevicesService;
|
||||
import com.evobms.project.ota.service.IOtaTasksService;
|
||||
import com.evobms.project.ota.domain.OtaTasks;
|
||||
import com.evobms.project.iot.domain.dto.OtaUploadDto;
|
||||
import com.evobms.project.iot.domain.dto.OtaLoginDto;
|
||||
import com.evobms.project.iot.domain.dto.OtaHistoryResultDTO;
|
||||
import com.evobms.project.iot.domain.dto.OtaProgressResultDTO;
|
||||
import com.evobms.project.iot.domain.dto.OtaUploadResultDTO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
@ -25,8 +37,10 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
||||
@ -36,19 +50,18 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 设备鉴权令牌接口
|
||||
* 路径:POST /iot/auth/token
|
||||
*/
|
||||
@RestController
|
||||
@Tag(name = "设备鉴权", description = "设备鉴权令牌接口")
|
||||
@Api(tags = "IoT设备鉴权")
|
||||
@RequestMapping("/iot")
|
||||
@Slf4j
|
||||
public class IotAuthController {
|
||||
private static final Logger log = LoggerFactory.getLogger(IotAuthController.class);
|
||||
|
||||
@Autowired(required = false)
|
||||
private IBmsDevicesService bmsDevicesService;
|
||||
@ -59,9 +72,13 @@ public class IotAuthController {
|
||||
@Value("${token.header:Authorization}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${mqtt.host:tcp://localhost:1883}")
|
||||
@Value("${mqtt.host:tcp://61.182.73.218:11883}")
|
||||
private String mqttHostUri;
|
||||
@Value("${mqtt.username:00000001}")
|
||||
@Value("${mqtt.publicHost:61.182.73.218}")
|
||||
private String mqttPublicHost;
|
||||
@Value("${mqtt.publicPort:11883}")
|
||||
private int mqttPublicPort;
|
||||
@Value("${mqtt.username:`00000001`}")
|
||||
private String mqttUsername;
|
||||
@Value("${mqtt.password:741a03a10f3de6b2}")
|
||||
private String mqttPassword;
|
||||
@ -73,7 +90,7 @@ public class IotAuthController {
|
||||
private String otaCount;
|
||||
|
||||
// OTA文件存储位置:支持 classpath 或 文件系统目录,例如:classpath:/ota 或 /data/ota
|
||||
@Value("${ota.repo:classpath:/ota}")
|
||||
@Value("${ota.repo:./ota}")
|
||||
private String otaRepo;
|
||||
|
||||
// OTA分片大小(字节),规范为1KB=1024字节
|
||||
@ -89,11 +106,14 @@ public class IotAuthController {
|
||||
* 返回:{ code, success, token }
|
||||
*/
|
||||
@PostMapping("/auth/token")
|
||||
@Operation(summary = "设备请求令牌", description = "通过SN码,设备号,版本信息生成TOKEN")
|
||||
@ApiOperation("设备请求令牌")
|
||||
public Map<String, Object> requestToken(@RequestBody Map<String, String> body) {
|
||||
String sn = safeTrim(body.get("sn"));
|
||||
String model = safeTrim(body.get("device"));
|
||||
String version = safeTrim(body.get("version"));
|
||||
|
||||
log.info("设备请求:{}",body.toString());
|
||||
log.info("sn:{}, device:{}, version:{}", sn, model, version);
|
||||
MDC.put("sn", sn);
|
||||
MDC.put("model", model);
|
||||
MDC.put("version", version);
|
||||
@ -113,10 +133,8 @@ public class IotAuthController {
|
||||
BmsDevices query = new BmsDevices();
|
||||
// 依据设备上报的SN,使用系统侧BmsDevices的deviceSn字段进行校验
|
||||
query.setDeviceSn(sn);
|
||||
List<BmsDevices> list = bmsDevicesService.selectBmsDevicesList(query);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
device = list.get(0);
|
||||
}
|
||||
device = bmsDevicesService.selectBmsDevicesList1(query);
|
||||
|
||||
}
|
||||
|
||||
if (device == null) {
|
||||
@ -133,7 +151,7 @@ public class IotAuthController {
|
||||
return resp;
|
||||
}
|
||||
|
||||
// 设备合法,改为自定义非JWT令牌,长度固定65
|
||||
// 设备合法,改为JWT令牌,长度固定65
|
||||
String token = deviceTokenService.issueTokenForSn(sn);
|
||||
log.info("BBOX设备token: {}", token);
|
||||
log.info("设备令牌签发成功: sn={} model={} version={} tokenLen={}", sn, model, version, token != null ? token.length() : 0);
|
||||
@ -162,6 +180,8 @@ public class IotAuthController {
|
||||
* 请求参数:version(可选)
|
||||
* 返回:{ code, success, data(Base64) }
|
||||
*/
|
||||
@Operation(summary = " MQTT 登录", description = "获取设备端 MQTT 登录信息")
|
||||
@ApiOperation(value = "MQTT 登录", notes = "获取设备端 MQTT 登录信息")
|
||||
@GetMapping("/auth/mqtt")
|
||||
public Map<String, Object> getMqttCredentials(@RequestParam(value = "version", required = false) String version,
|
||||
HttpServletRequest request) {
|
||||
@ -175,21 +195,24 @@ public class IotAuthController {
|
||||
return resp;
|
||||
}
|
||||
|
||||
// 解析 MQTT 主机与端口
|
||||
String host = "61.182.73.218";
|
||||
int port = 1883;
|
||||
try {
|
||||
URI uri = new URI(mqttHostUri);
|
||||
if (uri.getHost() != null) {
|
||||
host = uri.getHost();
|
||||
String host = safeTrim(mqttPublicHost);
|
||||
Integer port = mqttPublicPort > 0 ? mqttPublicPort : null;
|
||||
if (StringUtils.isEmpty(host) || port == null) {
|
||||
try {
|
||||
URI uri = new URI(mqttHostUri);
|
||||
if (StringUtils.isEmpty(host) && uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||
host = uri.getHost();
|
||||
}
|
||||
if (port == null && uri.getPort() != -1) {
|
||||
port = uri.getPort();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
if (uri.getPort() != -1) {
|
||||
port = uri.getPort();
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
if (port == null || port <= 0) port = 11883;
|
||||
|
||||
String use = fixLengthRight(mqttUsername, 8);
|
||||
String pass = fixLengthRight(mqttPassword,16);
|
||||
String pass = fixLengthRight(mqttPassword, 16);
|
||||
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("clientid", sn);
|
||||
@ -199,10 +222,20 @@ public class IotAuthController {
|
||||
data.put("passwd", pass);
|
||||
|
||||
String json = JSON.toJSONString(data);
|
||||
log.debug("登录mqtt信息====》{}",json);
|
||||
String key16 = fixLengthRight(sn, 16); // AES密钥:sn后补0到16位
|
||||
String encryptedBase64 = AesEcbPkcs5Utils.encryptToAscII16(json, key16);
|
||||
log.debug("登录mqtt信息加密===================》{}",encryptedBase64);
|
||||
log.debug("登录mqtt信息====》{}", json);
|
||||
// AES密钥:sn后补0到16位
|
||||
String encryptedBase64;
|
||||
if (sn.equals("EVO0001")) {
|
||||
String key161 = fixLengthRight("EVO0001", 16);
|
||||
encryptedBase64 = AesEcbPkcs5Utils.encryptToAscII16(json, key161);
|
||||
} else if (sn.equals("EVO0002")) {
|
||||
String key161 = fixLengthRight("EVO0002", 16);
|
||||
encryptedBase64 = AesEcbPkcs5Utils.encryptToAscII16(json, key161);
|
||||
}else {
|
||||
String keyTail6 = sn.length() >= 16 ? sn.substring(sn.length() - 16) : sn;
|
||||
encryptedBase64 = AesEcbPkcs5Utils.encryptToAscII16(json, keyTail6);
|
||||
}
|
||||
log.debug("登录mqtt信息加密===================》{}", encryptedBase64);
|
||||
resp.put("code", BboxApiConstants.CODE_SUCCESS);
|
||||
resp.put("success", "1");
|
||||
resp.put("data", encryptedBase64);
|
||||
@ -221,6 +254,7 @@ public class IotAuthController {
|
||||
* 请求参数(body):{ "version":"1.0.0" }
|
||||
* 返回:{ code(3位), success(1位), update(1位), version(5位), url(11位), count(3位) }
|
||||
*/
|
||||
@ApiOperation(value = "设备登录", notes = "设备登录并上报固件版本,服务端判断是否需要OTA升级")
|
||||
@PostMapping("/auth/login")
|
||||
public Map<String, Object> deviceLogin(@RequestBody(required = false) String body, @RequestParam(value = "version", required = false) String versionParam, HttpServletRequest request) {
|
||||
Map<String, Object> resp = new HashMap<>();
|
||||
@ -270,10 +304,8 @@ public class IotAuthController {
|
||||
if (bmsDevicesService != null) {
|
||||
BmsDevices query = new BmsDevices();
|
||||
query.setDeviceSn(sn);
|
||||
List<BmsDevices> list = bmsDevicesService.selectBmsDevicesList(query);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
device = list.get(0);
|
||||
}
|
||||
device = bmsDevicesService.selectBmsDevicesList1(query);
|
||||
|
||||
}
|
||||
|
||||
if (device == null) {
|
||||
@ -285,7 +317,8 @@ public class IotAuthController {
|
||||
|
||||
// 目标升级版本:直接取设备记录中的固件版本(跳过 OTA 任务查询)
|
||||
String targetVersion = null;
|
||||
try { targetVersion = device.getFirmwareVersion();
|
||||
try {
|
||||
targetVersion = device.getFirmwareVersion();
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
@ -310,7 +343,7 @@ public class IotAuthController {
|
||||
// 若存在目标版本,对应固件可用时,动态计算分片总数(总长度含 64 字节校验头);否则回退配置值
|
||||
Integer dynamicCount = computeOtaChunkCount(targetVersion);
|
||||
if (dynamicCount != null && dynamicCount > 0) {
|
||||
// 转为 3 位字符串(左侧补零),例如 7 -> "007"
|
||||
// 转为 3 位字符串(左侧补零), 7 -> "007"
|
||||
count = fixLengthLeft(String.valueOf(dynamicCount), 3);
|
||||
} else {
|
||||
// 回退使用配置 `ota.count`,默认 "001"
|
||||
@ -362,13 +395,15 @@ public class IotAuthController {
|
||||
* - 路径:`/iot/ota/{num}`,num 为三位数字字符串(000 起始)
|
||||
* - 参数:`version`(必填,目标固件版本号,例如 `1.0.1`)
|
||||
* - 响应:
|
||||
* 成功:`application/octet-stream` 二进制数据;每次返回最多 1024 字节(最后一片可能不足 1024)
|
||||
* 失败:`{ code, success }` JSON,错误码沿用 `BboxApiConstants`
|
||||
* 成功:`application/octet-stream` 二进制数据;每次返回最多 1024 字节(最后一片可能不足 1024)
|
||||
* 失败:`{ code, success }` JSON,错误码沿用 `BboxApiConstants`
|
||||
* - 首片摘要计算:针对首片1024字节数据生成摘要并作为校验头:32字节SHA-256原始摘要
|
||||
* - 首片结构:`[header] + [首片数据(最多1024)]`,总长 `headerLen + 1024`
|
||||
* - 后续分片:与首片相同,每片前置相同模式的校验头(摘要基于该分片的数据),随后紧跟该分片数据
|
||||
*/
|
||||
@GetMapping("/ota/{num}")
|
||||
@Operation(summary = "OTA固件分片下载", description = " OTA 固件分片下载接口")
|
||||
@ApiOperation("OTA固件分片下载")
|
||||
public Object downloadOtaChunk(@PathVariable("num") String num,
|
||||
@RequestParam(value = "version", required = false) String version,
|
||||
HttpServletRequest request) {
|
||||
@ -425,7 +460,7 @@ public class IotAuthController {
|
||||
try {
|
||||
int previewLen = Math.min(otaChunkSize, firmwareBytes);
|
||||
byte[] preview = Arrays.copyOfRange(firmware, 0, previewLen);
|
||||
// 变更说明:headerSHA256日志打印为“首片1024字节数据”的摘要,而非整包
|
||||
// headerSHA256日志打印为“首片1024字节数据”的摘要,而非整包
|
||||
String headerHex = sha256Hex(preview);
|
||||
log.info("OTA下载开始: sn={} version={} headerSHA256={} headerMode={} chunkSize={} firmwareBytes={} chunks={}", sn, version, headerHex, "binary32", otaChunkSize, firmwareBytes, chunks);
|
||||
} catch (Exception ignore) {
|
||||
@ -453,9 +488,10 @@ public class IotAuthController {
|
||||
log.info("OTA首片头HEX({}): {}", headerLen, toHex(header));
|
||||
int prefixLen = Math.min(64, firstData.length);
|
||||
log.info("OTA首片数据HEX前{}字节: {}", prefixLen, toHex(Arrays.copyOfRange(firstData, 0, prefixLen)));
|
||||
} catch (Exception ignore) {}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
} else {
|
||||
// 后续分片:从首片实际数据(1024)之后开始切片;并在分片前置校验头(摘要基于该分片数据)
|
||||
// 从首片实际数据(1024)之后开始切片;并在分片前置校验头(摘要基于该分片数据)
|
||||
int firstDataLen = Math.min(otaChunkSize, firmwareBytes);
|
||||
int offset = firstDataLen + (idx - 1) * otaChunkSize;
|
||||
if (offset >= firmwareBytes) {
|
||||
@ -486,25 +522,76 @@ public class IotAuthController {
|
||||
log.info("OTA分片头HEX({}): {}", headerLen, toHex(header));
|
||||
int prefixLen = Math.min(64, dataForDigest.length);
|
||||
log.info("OTA分片数据HEX前{}字节: {}", prefixLen, toHex(Arrays.copyOfRange(dataForDigest, 0, prefixLen)));
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
log.debug("OTA分片发送: sn={} version={} num={} chunkLen={}",
|
||||
sn, version, num, chunk.length);
|
||||
|
||||
double progress = (idx + 1) * 100.0 / Math.max(chunks, 1);
|
||||
try {
|
||||
if (otaTasksService != null) {
|
||||
String deviceId = sn;
|
||||
if (bmsDevicesService != null) {
|
||||
try {
|
||||
BmsDevices q = new BmsDevices();
|
||||
q.setDeviceSn(sn);
|
||||
BmsDevices dev = bmsDevicesService.selectBmsDevicesList1(q);
|
||||
if (dev != null && dev.getDeviceId() != null) {
|
||||
deviceId = dev.getDeviceId();
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
OtaTasks filter = new OtaTasks();
|
||||
filter.setDeviceId(deviceId);
|
||||
filter.setFirmwareVersion(version);
|
||||
List<OtaTasks> list = otaTasksService.selectOtaTasksList(filter);
|
||||
OtaTasks task = (list != null && !list.isEmpty()) ? list.get(0) : new OtaTasks();
|
||||
boolean isNew = (task.getId() == null || task.getId().isEmpty());
|
||||
if (isNew) {
|
||||
task.setDeviceId(deviceId);
|
||||
task.setTaskName("OTA-" + version);
|
||||
task.setFirmwareVersion(version);
|
||||
task.setStatus("IN_PROGRESS");
|
||||
task.setProgress((long) Math.round((float) progress));
|
||||
task.setStartTime(new Date());
|
||||
task.setCreateBy(sn);
|
||||
otaTasksService.insertOtaTasks(task);
|
||||
} else {
|
||||
task.setProgress((long) Math.round((float) progress));
|
||||
if (idx == chunks - 1) {
|
||||
task.setStatus("DONE");
|
||||
task.setEndTime(new java.util.Date());
|
||||
} else {
|
||||
task.setStatus("IN_PROGRESS");
|
||||
}
|
||||
task.setUpdateTime(new java.util.Date());
|
||||
otaTasksService.updateOtaTasks(task);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.warn("OTA任务记录更新失败: sn={} version={} err={}", sn, version, ex.getMessage());
|
||||
}
|
||||
return ResponseEntity
|
||||
.ok()
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(chunk.length)
|
||||
.header("X-OTA-Chunk-Index", String.valueOf(idx))
|
||||
.header("X-OTA-Chunk-Total", String.valueOf(chunks))
|
||||
.header("X-OTA-Progress", String.format(java.util.Locale.ROOT, "%.2f", progress))
|
||||
.header("X-OTA-Chunk-Size", String.valueOf(otaChunkSize))
|
||||
.header("X-OTA-Firmware-Bytes", String.valueOf(firmwareBytes))
|
||||
.header("X-OTA-Mode", mode)
|
||||
.body(chunk);
|
||||
} catch (Exception e) {
|
||||
log.error("OTA分片下载异常: {}", e.getMessage(), e);
|
||||
err.put("code", BboxApiConstants.CODE_UNAUTHORIZED);
|
||||
err.put("success", "0");
|
||||
return err;
|
||||
} finally {
|
||||
MDC.clear();
|
||||
log.error("OTA分片下载异常: {}", e.getMessage(), e);
|
||||
err.put("code", BboxApiConstants.CODE_UNAUTHORIZED);
|
||||
err.put("success", "0");
|
||||
return err;
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态计算 OTA 分片总数
|
||||
@ -525,6 +612,240 @@ public class IotAuthController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/ota/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@ApiOperation(value = "上传OTA固件", notes = "上传固件到 ota.repo 指定目录,保存为 <version>.bin", response = OtaUploadResultDTO.class)
|
||||
public OtaUploadResultDTO uploadOta(@RequestParam("version") String version, @RequestParam("file") MultipartFile file) {
|
||||
OtaUploadResultDTO resp = new OtaUploadResultDTO();
|
||||
try {
|
||||
if (StringUtils.isEmpty(version) || file == null || file.isEmpty()) {
|
||||
resp.setCode(BboxApiConstants.CODE_PARAM_INVALID);
|
||||
resp.setSuccess("0");
|
||||
resp.setMsg("version或file缺失");
|
||||
return resp;
|
||||
}
|
||||
if (otaRepo.startsWith("classpath:")) {
|
||||
resp.setCode(BboxApiConstants.CODE_PARAM_INVALID);
|
||||
resp.setSuccess("0");
|
||||
resp.setMsg("classpath仓库不支持上传,请配置文件系统路径");
|
||||
return resp;
|
||||
}
|
||||
Path dir = Paths.get(otaRepo);
|
||||
if (!Files.exists(dir)) {
|
||||
Files.createDirectories(dir);
|
||||
}
|
||||
Path target = dir.resolve(version + ".bin");
|
||||
Files.copy(file.getInputStream(), target, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
resp.setCode(BboxApiConstants.CODE_SUCCESS);
|
||||
resp.setSuccess("1");
|
||||
resp.setPath(target.toString());
|
||||
resp.setSize(Files.size(target));
|
||||
log.info("OTA上传成功: version={} repo={} target={} size={}", version, otaRepo, target.toString(), resp.getSize());
|
||||
// 返回分片元信息
|
||||
Integer chunks = computeOtaChunkCount(version);
|
||||
resp.setChunks(chunks);
|
||||
resp.setChunkSize(otaChunkSize);
|
||||
return resp;
|
||||
} catch (IOException e) {
|
||||
resp.setCode(BboxApiConstants.CODE_FILE_NOT_FOUND);
|
||||
resp.setSuccess("0");
|
||||
resp.setMsg(e.getMessage());
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/ota/meta")
|
||||
@ApiOperation(value = "查询OTA元信息", notes = "返回分片总数、分片大小、固件字节数")
|
||||
public Map<String, Object> otaMeta(@RequestParam("version") String version) {
|
||||
Map<String, Object> resp = new HashMap<>();
|
||||
if (StringUtils.isEmpty(version)) {
|
||||
resp.put("code", BboxApiConstants.CODE_PARAM_INVALID);
|
||||
resp.put("success", "0");
|
||||
return resp;
|
||||
}
|
||||
byte[] fw = loadFirmwareBytes(version);
|
||||
if (fw == null) {
|
||||
resp.put("code", BboxApiConstants.CODE_FILE_NOT_FOUND);
|
||||
resp.put("success", "0");
|
||||
return resp;
|
||||
}
|
||||
resp.put("code", BboxApiConstants.CODE_SUCCESS);
|
||||
resp.put("success", "1");
|
||||
resp.put("firmwareBytes", fw.length);
|
||||
resp.put("chunkSize", otaChunkSize);
|
||||
resp.put("chunks", (fw.length + otaChunkSize - 1) / otaChunkSize);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@GetMapping("/ota/history")
|
||||
@ApiOperation(value = "OTA操作历史", notes = "前端用于展示操作历史列表;sn为空时可从Authorization解析")
|
||||
public OtaHistoryResultDTO otaHistory(@RequestParam(value = "sn", required = false) String sn,
|
||||
@RequestParam(value = "version", required = false) String version,
|
||||
@RequestParam(value = "limit", required = false) Integer limit,
|
||||
HttpServletRequest request) {
|
||||
OtaHistoryResultDTO out = new OtaHistoryResultDTO();
|
||||
String snx = safeTrim(sn);
|
||||
if (StringUtils.isEmpty(snx)) {
|
||||
try {
|
||||
snx = deviceTokenService.resolveSn(request);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(snx)) {
|
||||
out.setCode(BboxApiConstants.CODE_PARAM_INVALID);
|
||||
out.setSuccess("0");
|
||||
out.setMsg("sn不能为空");
|
||||
return out;
|
||||
}
|
||||
if (otaTasksService == null) {
|
||||
out.setCode(BboxApiConstants.CODE_NOT_FOUND);
|
||||
out.setSuccess("0");
|
||||
out.setMsg("otaTasksService未启用");
|
||||
out.setSn(snx);
|
||||
return out;
|
||||
}
|
||||
|
||||
String deviceId = resolveDeviceIdBySn(snx);
|
||||
OtaTasks filter = new OtaTasks();
|
||||
filter.setDeviceId(deviceId);
|
||||
if (StringUtils.isNotEmpty(version)) {
|
||||
filter.setFirmwareVersion(version);
|
||||
}
|
||||
List<OtaTasks> list = otaTasksService.selectOtaTasksList(filter);
|
||||
List<OtaTasks> sorted = list == null ? new ArrayList<>() : new ArrayList<>(list);
|
||||
sorted.sort(Comparator.comparing(this::resolveOtaSortTime, Comparator.nullsLast(Date::compareTo)).reversed());
|
||||
|
||||
int lim = (limit == null || limit <= 0) ? 50 : limit;
|
||||
if (sorted.size() > lim) {
|
||||
sorted = new ArrayList<>(sorted.subList(0, lim));
|
||||
}
|
||||
|
||||
out.setCode(BboxApiConstants.CODE_SUCCESS);
|
||||
out.setSuccess("1");
|
||||
out.setMsg(BboxApiConstants.MSG_SUCCESS);
|
||||
out.setSn(snx);
|
||||
out.setDeviceId(deviceId);
|
||||
out.setTaskList(sorted);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* OTA 任务进度(管理端轮询)
|
||||
* - 路径:GET /iot/ota/progress
|
||||
* - 参数:sn(可选,缺省时从 Authorization 解析设备)、version(可选,缺省时取该设备最新任务)
|
||||
* - 说明:`progress` 为任务整体 0–100;`totalChunks`/`chunkSize` 与设备登录 `count`、分片下载逻辑对齐;
|
||||
* `downloadedChunks` 由 `progress` 与 `totalChunks` 推算,用于可选的「分片进度」文案(与浏览器上传到 /iot/ota/upload 无关)。
|
||||
* - 响应示例:
|
||||
* <pre>
|
||||
* {
|
||||
* "code": 200,
|
||||
* "success": "1",
|
||||
* "msg": "success",
|
||||
* "sn": "137PBP1M11001AFCF0000007",
|
||||
* "deviceId": "BAT_001",
|
||||
* "firmwareVersion": "1.0.1",
|
||||
* "status": "IN_PROGRESS",
|
||||
* "progress": 45,
|
||||
* "totalChunks": 120,
|
||||
* "downloadedChunks": 54,
|
||||
* "chunkSize": 1024,
|
||||
* "startTime": "2026-05-11 10:00:00",
|
||||
* "endTime": null,
|
||||
* "updateTime": "2026-05-11 10:05:00"
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@GetMapping("/ota/progress")
|
||||
@ApiOperation(value = "OTA进度条", notes = "前端轮询展示设备 OTA 任务进度;含 totalChunks/downloadedChunks 供可选分片文案;上传进度请用前端 multipart 的 on-progress")
|
||||
public OtaProgressResultDTO otaProgress(@RequestParam(value = "sn", required = false) String sn,
|
||||
@RequestParam(value = "version", required = false) String version,
|
||||
HttpServletRequest request) {
|
||||
OtaProgressResultDTO out = new OtaProgressResultDTO();
|
||||
String snx = safeTrim(sn);
|
||||
if (StringUtils.isEmpty(snx)) {
|
||||
try {
|
||||
snx = deviceTokenService.resolveSn(request);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(snx)) {
|
||||
out.setCode(BboxApiConstants.CODE_PARAM_INVALID);
|
||||
out.setSuccess("0");
|
||||
out.setMsg("sn不能为空");
|
||||
return out;
|
||||
}
|
||||
if (otaTasksService == null) {
|
||||
out.setCode(BboxApiConstants.CODE_NOT_FOUND);
|
||||
out.setSuccess("0");
|
||||
out.setMsg("otaTasksService未启用");
|
||||
out.setSn(snx);
|
||||
return out;
|
||||
}
|
||||
|
||||
String deviceId = resolveDeviceIdBySn(snx);
|
||||
OtaTasks filter = new OtaTasks();
|
||||
filter.setDeviceId(deviceId);
|
||||
if (StringUtils.isNotEmpty(version)) {
|
||||
filter.setFirmwareVersion(version);
|
||||
}
|
||||
List<OtaTasks> list = otaTasksService.selectOtaTasksList(filter);
|
||||
List<OtaTasks> sorted = list == null ? new ArrayList<>() : new ArrayList<>(list);
|
||||
sorted.sort(Comparator.comparing(this::resolveOtaSortTime, Comparator.nullsLast(Date::compareTo)).reversed());
|
||||
OtaTasks latest = sorted.isEmpty() ? null : sorted.get(0);
|
||||
|
||||
out.setCode(BboxApiConstants.CODE_SUCCESS);
|
||||
out.setSuccess("1");
|
||||
out.setMsg(BboxApiConstants.MSG_SUCCESS);
|
||||
out.setSn(snx);
|
||||
out.setDeviceId(deviceId);
|
||||
if (latest != null) {
|
||||
out.setFirmwareVersion(latest.getFirmwareVersion());
|
||||
out.setStatus(latest.getStatus());
|
||||
out.setProgress(latest.getProgress() == null ? 0L : latest.getProgress());
|
||||
out.setStartTime(latest.getStartTime());
|
||||
out.setEndTime(latest.getEndTime());
|
||||
out.setUpdateTime(latest.getUpdateTime());
|
||||
} else {
|
||||
out.setFirmwareVersion(version);
|
||||
out.setStatus("NONE");
|
||||
out.setProgress(0L);
|
||||
}
|
||||
attachOtaChunkProgressFields(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为进度接口附加分片元数据:totalChunks 与登录接口 count 同源;downloadedChunks 由任务 progress 反推(与分片下载时写回 DB 的规则一致)。
|
||||
*/
|
||||
private void attachOtaChunkProgressFields(OtaProgressResultDTO out) {
|
||||
out.setChunkSize(otaChunkSize);
|
||||
String fv = out.getFirmwareVersion();
|
||||
if (StringUtils.isEmpty(fv)) {
|
||||
return;
|
||||
}
|
||||
Integer total = computeOtaChunkCount(fv);
|
||||
out.setTotalChunks(total);
|
||||
if (total == null || total <= 0) {
|
||||
return;
|
||||
}
|
||||
String st = out.getStatus();
|
||||
if (isOtaFinishedSuccess(st)) {
|
||||
out.setDownloadedChunks(total);
|
||||
return;
|
||||
}
|
||||
long prog = out.getProgress() == null ? 0L : out.getProgress();
|
||||
int est = (int) Math.round(prog * (double) total / 100.0);
|
||||
est = Math.max(0, Math.min(est, total));
|
||||
out.setDownloadedChunks(est);
|
||||
}
|
||||
|
||||
private static boolean isOtaFinishedSuccess(String status) {
|
||||
if (StringUtils.isEmpty(status)) {
|
||||
return false;
|
||||
}
|
||||
String u = status.trim().toUpperCase(Locale.ROOT);
|
||||
return "DONE".equals(u) || "SUCCESS".equals(u) || "COMPLETED".equals(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 OTA 负载(仅 binary32)
|
||||
* - 格式:`[32字节SHA256原始摘要] + [固件]`
|
||||
@ -554,7 +875,8 @@ public class IotAuthController {
|
||||
String rel = base + version + ".bin";
|
||||
Resource res = new ClassPathResource(rel);
|
||||
if (!res.exists()) return null;
|
||||
try (InputStream in = res.getInputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
try (InputStream in = res.getInputStream();
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = in.read(buf)) != -1) bos.write(buf, 0, r);
|
||||
@ -572,6 +894,27 @@ public class IotAuthController {
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveDeviceIdBySn(String sn) {
|
||||
String deviceId = sn;
|
||||
if (bmsDevicesService != null) {
|
||||
try {
|
||||
BmsDevices dev = bmsDevicesService.selectBmsDevicesBySn(sn);
|
||||
if (dev != null && StringUtils.isNotEmpty(dev.getDeviceId())) {
|
||||
deviceId = dev.getDeviceId();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
private Date resolveOtaSortTime(OtaTasks task) {
|
||||
if (task == null) return null;
|
||||
if (task.getUpdateTime() != null) return task.getUpdateTime();
|
||||
if (task.getCreateTime() != null) return task.getCreateTime();
|
||||
return task.getStartTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算 SHA256 的十六进制字符串
|
||||
* - 输出:小写,长度 64 的 ASCII 字符串
|
||||
@ -580,7 +923,7 @@ public class IotAuthController {
|
||||
private static String sha256Hex(byte[] data) throws Exception {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
byte[] digest = md.digest(data);
|
||||
StringBuilder sb = new StringBuilder(digest.length );
|
||||
StringBuilder sb = new StringBuilder(digest.length);
|
||||
for (byte b : digest) {
|
||||
//转为 16 进制字符串
|
||||
String s = Integer.toHexString(0xff & b);
|
||||
@ -608,7 +951,9 @@ public class IotAuthController {
|
||||
|
||||
private static String fixLengthRight(String s, int len) {
|
||||
if (s == null) s = "";
|
||||
if (s.length() >= len) return s.substring(0, len);
|
||||
if (s.length() >= len){
|
||||
return s.substring(0, len);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
sb.append(s);
|
||||
while (sb.length() < len) sb.append('0');
|
||||
|
||||
@ -3,6 +3,8 @@ package com.evobms.project.iot.controller;
|
||||
import com.evobms.common.constant.BboxApiConstants;
|
||||
import com.evobms.common.utils.StringUtils;
|
||||
import com.evobms.project.iot.service.DeviceTokenService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
@ -25,6 +27,7 @@ import java.util.Map;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota")
|
||||
@Api(tags = "IoT OTA状态上报")
|
||||
public class IotOtaController {
|
||||
private static final Logger log = LoggerFactory.getLogger(IotOtaController.class);
|
||||
|
||||
@ -32,6 +35,7 @@ public class IotOtaController {
|
||||
private DeviceTokenService deviceTokenService;
|
||||
|
||||
@PostMapping("/status")
|
||||
@ApiOperation("上报OTA升级状态")
|
||||
public Map<String, Object> reportOtaStatus(@RequestBody Map<String, String> body,
|
||||
HttpServletRequest request) {
|
||||
Map<String, Object> resp = new HashMap<>();
|
||||
@ -48,7 +52,7 @@ public class IotOtaController {
|
||||
MDC.put("sn", sn);
|
||||
MDC.put("version", prevVersion);
|
||||
|
||||
// 规范化状态:仅识别 "1" 为成功,其余按失败处理;仍返回成功表示上报接口调用成功
|
||||
|
||||
String normalizedStatus = "0";
|
||||
if ("1".equals(statusStr)) {
|
||||
normalizedStatus = "1";
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import com.evobms.project.ota.domain.OtaTasks;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "OtaHistoryResultDTO", description = "OTA操作历史查询结果")
|
||||
@Data
|
||||
public class OtaHistoryResultDTO {
|
||||
|
||||
@ApiModelProperty(value = "状态码", example = "200")
|
||||
private Integer code;
|
||||
|
||||
@ApiModelProperty(value = "是否成功,1成功/0失败", example = "1")
|
||||
private String success;
|
||||
|
||||
@ApiModelProperty(value = "提示信息", example = "success")
|
||||
private String msg;
|
||||
|
||||
@ApiModelProperty(value = "设备SN", example = "137PBP1M11001AFCF0000007")
|
||||
private String sn;
|
||||
|
||||
@ApiModelProperty(value = "设备ID(平台侧deviceId)", example = "BAT_001")
|
||||
private String deviceId;
|
||||
|
||||
@ApiModelProperty(value = "任务列表(按最近时间倒序)")
|
||||
private List<OtaTasks> taskList;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备登录DTO
|
||||
*/
|
||||
@ApiModel(value = "OtaLoginDto", description = "设备登录DTO")
|
||||
@Data
|
||||
public class OtaLoginDto {
|
||||
@ApiModelProperty(value = "固件版本")
|
||||
private String version;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel(value = "OtaProgressResultDTO", description = "OTA进度查询结果(用于进度条)")
|
||||
@Data
|
||||
public class OtaProgressResultDTO {
|
||||
|
||||
@ApiModelProperty(value = "状态码", example = "200")
|
||||
private Integer code;
|
||||
|
||||
@ApiModelProperty(value = "是否成功,1成功/0失败", example = "1")
|
||||
private String success;
|
||||
|
||||
@ApiModelProperty(value = "提示信息", example = "success")
|
||||
private String msg;
|
||||
|
||||
@ApiModelProperty(value = "设备SN", example = "137PBP1M11001AFCF0000007")
|
||||
private String sn;
|
||||
|
||||
@ApiModelProperty(value = "设备ID(平台侧deviceId)", example = "BAT_001")
|
||||
private String deviceId;
|
||||
|
||||
@ApiModelProperty(value = "目标固件版本", example = "v1.0.3")
|
||||
private String firmwareVersion;
|
||||
|
||||
@ApiModelProperty(value = "任务状态", example = "IN_PROGRESS")
|
||||
private String status;
|
||||
|
||||
@ApiModelProperty(value = "进度(0-100)", example = "30")
|
||||
private Long progress;
|
||||
|
||||
/** 与设备登录接口返回的 count、GET /iot/ota/meta 的 chunks 同一口径(按固件字节与 ota.chunk-size 计算) */
|
||||
@ApiModelProperty(value = "OTA 分片总数(与设备侧 count 对齐;服务端根据仓库内固件计算,缺文件时为 null)", example = "120")
|
||||
private Integer totalChunks;
|
||||
|
||||
/**
|
||||
* 基于当前任务的 progress 与 totalChunks 推算的已拉取分片数(与 downloadOtaChunk 中按片更新 progress 的规则一致;取整误差 ±1 片属正常)。
|
||||
* 任务状态为 DONE 等终态成功时置为 totalChunks。
|
||||
*/
|
||||
@ApiModelProperty(value = "推算的已下载分片数(来自 progress×totalChunks,仅供展示;无 totalChunks 时为 null)", example = "54")
|
||||
private Integer downloadedChunks;
|
||||
|
||||
@ApiModelProperty(value = "单分片字节数(与 ota.chunk-size 一致)", example = "1024")
|
||||
private Integer chunkSize;
|
||||
|
||||
@ApiModelProperty(value = "开始时间")
|
||||
private Date startTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间")
|
||||
private Date endTime;
|
||||
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* OTA固件上传DTO
|
||||
*/
|
||||
@ApiModel(value = "OtaUploadDto", description = "OTA固件上传DTO")
|
||||
@Data
|
||||
public class OtaUploadDto {
|
||||
@ApiModelProperty(value = "设备SN码")
|
||||
private String deviceSn;
|
||||
|
||||
@ApiModelProperty(value = "固件版本")
|
||||
private String version;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* OTA固件上传响应DTO
|
||||
*/
|
||||
@ApiModel(value = "OtaUploadResponseDto", description = "OTA固件上传响应DTO")
|
||||
@Data
|
||||
public class OtaUploadResponseDto {
|
||||
@ApiModelProperty(value = "状态码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "是否成功")
|
||||
private String success;
|
||||
|
||||
@ApiModelProperty(value = "上传进度")
|
||||
private Integer progress;
|
||||
|
||||
@ApiModelProperty(value = "消息")
|
||||
private String message;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.evobms.project.iot.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel(value = "OtaUploadResultDTO", description = "OTA固件上传结果")
|
||||
@Data
|
||||
public class OtaUploadResultDTO {
|
||||
|
||||
@ApiModelProperty(value = "状态码", example = "200")
|
||||
private Integer code;
|
||||
|
||||
@ApiModelProperty(value = "是否成功,1成功/0失败", example = "1")
|
||||
private String success;
|
||||
|
||||
@ApiModelProperty(value = "提示信息", example = "success")
|
||||
private String msg;
|
||||
|
||||
@ApiModelProperty(value = "固件落盘路径", example = "E:/OTA/v1.0.3.bin")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value = "文件大小(字节)", example = "102400")
|
||||
private Long size;
|
||||
|
||||
@ApiModelProperty(value = "分片总数", example = "100")
|
||||
private Integer chunks;
|
||||
|
||||
@ApiModelProperty(value = "分片大小(字节)", example = "1024")
|
||||
private Integer chunkSize;
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
package com.evobms.project.ota.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -12,14 +15,20 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.common.utils.StringUtils;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.ota.domain.OtaTasks;
|
||||
import com.evobms.project.ota.dto.OtaTaskQueryDTO;
|
||||
import com.evobms.project.ota.service.IOtaTasksService;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import com.evobms.project.system.service.IBmsDevicesService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* OTA任务Controller
|
||||
@ -29,16 +38,21 @@ import com.evobms.framework.web.page.TableDataInfo;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/ota/tasks")
|
||||
@Api(tags = "OTA任务管理")
|
||||
public class OtaTasksController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IOtaTasksService otaTasksService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IBmsDevicesService bmsDevicesService;
|
||||
|
||||
/**
|
||||
* 查询OTA任务列表
|
||||
*/
|
||||
//@PreAuthorize("@ss.hasPermi('OTA:tasks:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询OTA任务列表")
|
||||
public TableDataInfo list(OtaTasks otaTasks)
|
||||
{
|
||||
startPage();
|
||||
@ -46,12 +60,51 @@ public class OtaTasksController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据SN查询设备OTA更新信息
|
||||
*/
|
||||
@GetMapping("/sn/{sn}")
|
||||
@ApiOperation(value = "根据SN查询OTA任务信息", notes = "返回设备对象、最新任务和任务列表,供前端展示设备升级信息")
|
||||
public AjaxResult getBySn(@PathVariable("sn") String sn)
|
||||
{
|
||||
if (StringUtils.isEmpty(sn))
|
||||
{
|
||||
return AjaxResult.error("sn不能为空");
|
||||
}
|
||||
|
||||
BmsDevices device = null;
|
||||
String deviceId = sn;
|
||||
if (bmsDevicesService != null)
|
||||
{
|
||||
device = bmsDevicesService.selectBmsDevicesBySn(sn);
|
||||
if (device != null && StringUtils.isNotEmpty(device.getDeviceId()))
|
||||
{
|
||||
deviceId = device.getDeviceId();
|
||||
}
|
||||
}
|
||||
|
||||
OtaTasks query = new OtaTasks();
|
||||
query.setDeviceId(deviceId);
|
||||
List<OtaTasks> taskList = otaTasksService.selectOtaTasksList(query);
|
||||
List<OtaTasks> sortedTaskList = taskList == null ? new ArrayList<>() : new ArrayList<>(taskList);
|
||||
sortedTaskList.sort(Comparator.comparing(this::resolveSortTime,
|
||||
Comparator.nullsLast(Date::compareTo)).reversed());
|
||||
|
||||
OtaTaskQueryDTO dto = new OtaTaskQueryDTO();
|
||||
dto.setSn(sn);
|
||||
dto.setDevice(device);
|
||||
dto.setTaskList(sortedTaskList);
|
||||
dto.setLatestTask(sortedTaskList.isEmpty() ? null : sortedTaskList.get(0));
|
||||
return success(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出OTA任务列表
|
||||
*/
|
||||
//@PreAuthorize("@ss.hasPermi('OTA:tasks:export')")
|
||||
@Log(title = "OTA任务", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出OTA任务列表")
|
||||
public void export(HttpServletResponse response, OtaTasks otaTasks)
|
||||
{
|
||||
List<OtaTasks> list = otaTasksService.selectOtaTasksList(otaTasks);
|
||||
@ -64,6 +117,7 @@ public class OtaTasksController extends BaseController
|
||||
*/
|
||||
//@PreAuthorize("@ss.hasPermi('OTA:tasks:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取OTA任务详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(otaTasksService.selectOtaTasksById(id));
|
||||
@ -75,6 +129,7 @@ public class OtaTasksController extends BaseController
|
||||
//@PreAuthorize("@ss.hasPermi('OTA:tasks:add')")
|
||||
@Log(title = "OTA任务", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增OTA任务")
|
||||
public AjaxResult add(@RequestBody OtaTasks otaTasks)
|
||||
{
|
||||
return toAjax(otaTasksService.insertOtaTasks(otaTasks));
|
||||
@ -86,6 +141,7 @@ public class OtaTasksController extends BaseController
|
||||
//@PreAuthorize("@ss.hasPermi('OTA:tasks:edit')")
|
||||
@Log(title = "OTA任务", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改OTA任务")
|
||||
public AjaxResult edit(@RequestBody OtaTasks otaTasks)
|
||||
{
|
||||
return toAjax(otaTasksService.updateOtaTasks(otaTasks));
|
||||
@ -96,8 +152,26 @@ public class OtaTasksController extends BaseController
|
||||
*/
|
||||
@Log(title = "OTA任务", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除OTA任务")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(otaTasksService.deleteOtaTasksByIds(ids));
|
||||
}
|
||||
|
||||
private Date resolveSortTime(OtaTasks task)
|
||||
{
|
||||
if (task == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (task.getUpdateTime() != null)
|
||||
{
|
||||
return task.getUpdateTime();
|
||||
}
|
||||
if (task.getCreateTime() != null)
|
||||
{
|
||||
return task.getCreateTime();
|
||||
}
|
||||
return task.getStartTime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
package com.evobms.project.ota.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
@ -9,157 +13,62 @@ import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* OTA任务对象 ota_tasks
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel(description = "OTA任务对象")
|
||||
@Data
|
||||
public class OtaTasks extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 任务ID(UUID) */
|
||||
@ApiModelProperty(value = "任务ID(UUID)")
|
||||
private String id;
|
||||
|
||||
/** 设备ID */
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 任务名称 */
|
||||
@ApiModelProperty(value = "任务名称")
|
||||
@Excel(name = "任务名称")
|
||||
private String taskName;
|
||||
|
||||
/** 目标固件版本 */
|
||||
@ApiModelProperty(value = "目标固件版本")
|
||||
@Excel(name = "目标固件版本")
|
||||
private String firmwareVersion;
|
||||
|
||||
/** 任务状态 */
|
||||
@ApiModelProperty(value = "任务状态")
|
||||
@Excel(name = "任务状态")
|
||||
private String status;
|
||||
|
||||
/** 升级进度(0-100) */
|
||||
@ApiModelProperty(value = "升级进度(0-100)")
|
||||
@Excel(name = "升级进度(0-100)")
|
||||
private Long progress;
|
||||
|
||||
/** 开始时间 */
|
||||
@ApiModelProperty(value = "开始时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date startTime;
|
||||
|
||||
/** 结束时间 */
|
||||
@ApiModelProperty(value = "结束时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
private Date endTime;
|
||||
|
||||
/** 错误信息 */
|
||||
@ApiModelProperty(value = "错误信息")
|
||||
@Excel(name = "错误信息")
|
||||
private String errorMessage;
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName)
|
||||
{
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public String getTaskName()
|
||||
{
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setFirmwareVersion(String firmwareVersion)
|
||||
{
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
}
|
||||
|
||||
public String getFirmwareVersion()
|
||||
{
|
||||
return firmwareVersion;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setProgress(Long progress)
|
||||
{
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public Long getProgress()
|
||||
{
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime)
|
||||
{
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public Date getStartTime()
|
||||
{
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime)
|
||||
{
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public Date getEndTime()
|
||||
{
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage)
|
||||
{
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("deviceId", getDeviceId())
|
||||
.append("taskName", getTaskName())
|
||||
.append("firmwareVersion", getFirmwareVersion())
|
||||
.append("status", getStatus())
|
||||
.append("progress", getProgress())
|
||||
.append("startTime", getStartTime())
|
||||
.append("endTime", getEndTime())
|
||||
.append("errorMessage", getErrorMessage())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("createBy", getCreateBy())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.evobms.project.ota.dto;
|
||||
|
||||
import com.evobms.project.ota.domain.OtaTasks;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ApiModel(value = "OtaTaskQueryDTO", description = "根据SN查询设备OTA任务响应")
|
||||
public class OtaTaskQueryDTO {
|
||||
|
||||
@ApiModelProperty(value = "设备SN", example = "137PBP1M11001AFCF0000007")
|
||||
private String sn;
|
||||
|
||||
@ApiModelProperty(value = "设备对象")
|
||||
private BmsDevices device;
|
||||
|
||||
@ApiModelProperty(value = "最新一条OTA任务")
|
||||
private OtaTasks latestTask;
|
||||
|
||||
@ApiModelProperty(value = "该设备的OTA任务列表,按最近更新时间倒序")
|
||||
private List<OtaTasks> taskList;
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.summary.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.summary.domain.ChargeDischargeSummary;
|
||||
import com.evobms.project.summary.service.IChargeDischargeSummaryService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 累计充放电量Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2026-01-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/summary/summary")
|
||||
@Api(tags = "充放电统计")
|
||||
public class ChargeDischargeSummaryController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IChargeDischargeSummaryService chargeDischargeSummaryService;
|
||||
|
||||
/**
|
||||
* 查询累计充放电量列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询累计充放电量列表")
|
||||
public TableDataInfo list(ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
startPage();
|
||||
List<ChargeDischargeSummary> list = chargeDischargeSummaryService.selectChargeDischargeSummaryList(chargeDischargeSummary);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出累计充放电量列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:export')")
|
||||
@Log(title = "累计充放电量", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出累计充放电量列表")
|
||||
public void export(HttpServletResponse response, ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
List<ChargeDischargeSummary> list = chargeDischargeSummaryService.selectChargeDischargeSummaryList(chargeDischargeSummary);
|
||||
ExcelUtil<ChargeDischargeSummary> util = new ExcelUtil<ChargeDischargeSummary>(ChargeDischargeSummary.class);
|
||||
util.exportExcel(response, list, "累计充放电量数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取累计充放电量详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取累计充放电量详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(chargeDischargeSummaryService.selectChargeDischargeSummaryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增累计充放电量
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:add')")
|
||||
@Log(title = "累计充放电量", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增累计充放电量")
|
||||
public AjaxResult add(@RequestBody ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
return toAjax(chargeDischargeSummaryService.insertChargeDischargeSummary(chargeDischargeSummary));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改累计充放电量
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:edit')")
|
||||
@Log(title = "累计充放电量", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改累计充放电量")
|
||||
public AjaxResult edit(@RequestBody ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
return toAjax(chargeDischargeSummaryService.updateChargeDischargeSummary(chargeDischargeSummary));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除累计充放电量
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('summary:summary:remove')")
|
||||
@Log(title = "累计充放电量", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除累计充放电量")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(chargeDischargeSummaryService.deleteChargeDischargeSummaryByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.evobms.project.summary.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 累计充放电量对象 charge_discharge_summary
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2026-01-09
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel(value = "ChargeDischargeSummary", description = "累计充放电量对象")
|
||||
public class ChargeDischargeSummary extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@Excel(name = "设备ID")
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 时间戳 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss ")
|
||||
@ApiModelProperty(value = "时间戳")
|
||||
@Excel(name = "时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/** 累计放电(kWh) */
|
||||
@ApiModelProperty(value = "累计放电(kWh)")
|
||||
@Excel(name = "累计放电(kWh)")
|
||||
private BigDecimal dischargeKwh;
|
||||
|
||||
/** 累计充电kWh) */
|
||||
@ApiModelProperty(value = "累计充电kWh")
|
||||
@Excel(name = "累计充电(kWh)")
|
||||
private BigDecimal chargeKwh;
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.evobms.project.summary.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.evobms.project.summary.domain.ChargeDischargeSummary;
|
||||
|
||||
/**
|
||||
* 累计充放电量Mapper接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2026-01-09
|
||||
*/
|
||||
public interface ChargeDischargeSummaryMapper extends BaseMapper<ChargeDischargeSummary> {
|
||||
/**
|
||||
* 查询累计充放电量
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 累计充放电量
|
||||
*/
|
||||
public ChargeDischargeSummary selectChargeDischargeSummaryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询累计充放电量列表
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 累计充放电量集合
|
||||
*/
|
||||
public List<ChargeDischargeSummary> selectChargeDischargeSummaryList(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 新增累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 修改累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 删除累计充放电量
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteChargeDischargeSummaryById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除累计充放电量
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteChargeDischargeSummaryByIds(Long[] ids);
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.evobms.project.summary.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.evobms.project.summary.domain.ChargeDischargeSummary;
|
||||
|
||||
/**
|
||||
* 累计充放电量Service接口
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2026-01-09
|
||||
*/
|
||||
public interface IChargeDischargeSummaryService
|
||||
{
|
||||
/**
|
||||
* 查询累计充放电量
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 累计充放电量
|
||||
*/
|
||||
public ChargeDischargeSummary selectChargeDischargeSummaryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询累计充放电量列表
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 累计充放电量集合
|
||||
*/
|
||||
public List<ChargeDischargeSummary> selectChargeDischargeSummaryList(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 新增累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 修改累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary);
|
||||
|
||||
/**
|
||||
* 批量删除累计充放电量
|
||||
*
|
||||
* @param ids 需要删除的累计充放电量主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteChargeDischargeSummaryByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除累计充放电量信息
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteChargeDischargeSummaryById(Long id);
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.evobms.project.summary.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import com.evobms.project.vehicledata.domain.VehicleData;
|
||||
import com.evobms.project.vehicledata.mapper.VehicleDataMapper;
|
||||
import com.evobms.project.vehicledata.service.IVehicleDataService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.evobms.project.summary.mapper.ChargeDischargeSummaryMapper;
|
||||
import com.evobms.project.summary.domain.ChargeDischargeSummary;
|
||||
import com.evobms.project.summary.service.IChargeDischargeSummaryService;
|
||||
|
||||
/**
|
||||
* 累计充放电量Service业务层处理
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2026-01-09
|
||||
*/
|
||||
@Service
|
||||
public class ChargeDischargeSummaryServiceImpl extends ServiceImpl<ChargeDischargeSummaryMapper, ChargeDischargeSummary> implements IChargeDischargeSummaryService
|
||||
{
|
||||
|
||||
@Autowired
|
||||
private ChargeDischargeSummaryMapper chargeDischargeSummaryMapper;
|
||||
|
||||
/**
|
||||
* 查询累计充放电量
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 累计充放电量
|
||||
*/
|
||||
@Override
|
||||
public ChargeDischargeSummary selectChargeDischargeSummaryById(Long id)
|
||||
{
|
||||
return chargeDischargeSummaryMapper.selectChargeDischargeSummaryById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询累计充放电量列表
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 累计充放电量
|
||||
*/
|
||||
@Override
|
||||
public List<ChargeDischargeSummary> selectChargeDischargeSummaryList(ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
return chargeDischargeSummaryMapper.selectChargeDischargeSummaryList(chargeDischargeSummary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
chargeDischargeSummary.setCreateTime(DateUtils.getNowDate());
|
||||
return chargeDischargeSummaryMapper.insertChargeDischargeSummary(chargeDischargeSummary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改累计充放电量
|
||||
*
|
||||
* @param chargeDischargeSummary 累计充放电量
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateChargeDischargeSummary(ChargeDischargeSummary chargeDischargeSummary)
|
||||
{
|
||||
chargeDischargeSummary.setUpdateTime(DateUtils.getNowDate());
|
||||
return chargeDischargeSummaryMapper.updateChargeDischargeSummary(chargeDischargeSummary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除累计充放电量
|
||||
*
|
||||
* @param ids 需要删除的累计充放电量主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteChargeDischargeSummaryByIds(Long[] ids)
|
||||
{
|
||||
return chargeDischargeSummaryMapper.deleteChargeDischargeSummaryByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除累计充放电量信息
|
||||
*
|
||||
* @param id 累计充放电量主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteChargeDischargeSummaryById(Long id)
|
||||
{
|
||||
return chargeDischargeSummaryMapper.deleteChargeDischargeSummaryById(id);
|
||||
}
|
||||
}
|
||||
@ -1,43 +1,89 @@
|
||||
package com.evobms.project.system.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.evobms.project.vehicledata.domain.VehicleLocation;
|
||||
import com.evobms.project.vehicledata.service.IVehicleLocationService;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import com.evobms.project.system.service.IBmsDevicesService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.framework.web.domain.R;
|
||||
import com.evobms.common.constant.HttpStatus;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.evobms.project.vehicledata.dto.DeviceHistoryFlatRowDTO;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeDTO;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeAggregateDTO;
|
||||
import com.evobms.project.vehicledata.dto.NameValueDTO;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeDTO.SystemStatusSection;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeDTO.RunStatusSection;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeDTO.ChargeSection;
|
||||
import com.evobms.project.vehicledata.dto.DeviceRealtimeDTO.StatisticsSection;
|
||||
import com.evobms.project.vehicledata.dto.LineSeriesDTO;
|
||||
import com.evobms.project.vehicledata.dto.TimePointDTO;
|
||||
import com.evobms.project.vehicledata.dto.ChargeDischargeMonthDTO;
|
||||
import com.evobms.project.vehicledata.dto.ChargeDischargeRecordDTO;
|
||||
import com.evobms.project.vehicledata.dto.ChargeDischargeHistoryDTO;
|
||||
import com.evobms.project.vehicledata.service.DeviceRealtimeHistoryAssembler;
|
||||
import com.evobms.project.vehicledata.service.IVehicleDataService;
|
||||
import com.evobms.project.vehicledata.domain.VehicleData;
|
||||
import com.evobms.project.battery.service.IExtremeValuesService;
|
||||
import com.evobms.project.battery.service.ISubsystemVoltageService;
|
||||
import com.evobms.project.battery.service.ISubsystemTemperatureService;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
import com.evobms.project.bms.service.*;
|
||||
import com.evobms.project.bms.domain.*;
|
||||
|
||||
/**
|
||||
* BBOX管理Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-10
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/devices/devices")
|
||||
@Api(tags = "BBOX设备管理")
|
||||
public class BmsDevicesController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IBmsDevicesService bmsDevicesService;
|
||||
|
||||
@Autowired private IVehicleDataService vehicleDataService;
|
||||
@Autowired private IExtremeValuesService extremeValuesService;
|
||||
@Autowired private IBmsSystemStatusService bmsSystemStatusService;
|
||||
@Autowired private IBmsChargeDetailService bmsChargeDetailService;
|
||||
@Autowired private IBmsChargeTemperatureService bmsChargeTemperatureService;
|
||||
@Autowired private IBmsVoltageChannelDataService bmsVoltageChannelDataService;
|
||||
@Autowired private IBmsSopDataService bmsSopDataService;
|
||||
@Autowired private IVehicleLocationService vehicleLocationService;
|
||||
@Autowired private IBmsRuntimeDataService bmsRuntimeDataService;
|
||||
@Autowired private ISubsystemVoltageService subsystemVoltageService;
|
||||
@Autowired private ISubsystemTemperatureService subsystemTemperatureService;
|
||||
@Autowired private DeviceRealtimeHistoryAssembler deviceRealtimeHistoryAssembler;
|
||||
/**
|
||||
* 查询BBOX管理列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询BBOX设备列表")
|
||||
public TableDataInfo list(BmsDevices bmsDevices)
|
||||
{
|
||||
startPage();
|
||||
@ -45,11 +91,131 @@ public class BmsDevicesController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@GetMapping("/history/{deviceId}")
|
||||
@ApiOperation(value = "运行历史计算器(充/放电统计)", response = ChargeDischargeHistoryDTO.class)
|
||||
public R<ChargeDischargeHistoryDTO> history(
|
||||
@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId,
|
||||
@ApiParam(value = "开始时间戳(毫秒)", required = false) @RequestParam(value = "start", required = false) Long startMillis,
|
||||
@ApiParam(value = "结束时间戳(毫秒)", required = false) @RequestParam(value = "end", required = false) Long endMillis
|
||||
) {
|
||||
Date end = endMillis == null ? new Date() : new Date(endMillis);
|
||||
Date start = startMillis == null ? new Date(end.getTime() - 30L * 86400_000L) : new Date(startMillis);
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
SimpleDateFormat mf = new SimpleDateFormat("yyyy-MM");
|
||||
VehicleData q = new VehicleData();
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("beginTime", df.format(start));
|
||||
params.put("endTime", df.format(end));
|
||||
q.setDeviceId(deviceId);
|
||||
q.setParams(params);
|
||||
List<VehicleData> all = vehicleDataService.selectVehicleDataList(q);
|
||||
all.removeIf(v -> v.getTimestamp() == null);
|
||||
all.sort(Comparator.comparing(VehicleData::getTimestamp));
|
||||
|
||||
List<ChargeDischargeRecordDTO> records = new ArrayList<>();
|
||||
String currentStatus = null;
|
||||
int segmentStartIdx = -1;
|
||||
Integer prevSoc = null;
|
||||
for (int i = 0; i < all.size(); i++) {
|
||||
VehicleData v = all.get(i);
|
||||
Integer soc = v.getSoc();
|
||||
BigDecimal cur = v.getTotalCurrent();
|
||||
String status = null;
|
||||
if (cur != null) {
|
||||
int cmp = cur.compareTo(BigDecimal.ZERO);
|
||||
if (cmp > 0) status = "充电";
|
||||
else if (cmp < 0) status = "放电";
|
||||
}
|
||||
if (status == null && prevSoc != null && soc != null) {
|
||||
if (soc > prevSoc) status = "充电";
|
||||
else if (soc < prevSoc) status = "放电";
|
||||
}
|
||||
if (status == null && v.getChargingStatus() != null) {
|
||||
Integer st = v.getChargingStatus();
|
||||
if (st == 1 || st == 2) status = "充电";
|
||||
else if (st == 3) status = "放电";
|
||||
}
|
||||
if (status == null) {
|
||||
prevSoc = soc;
|
||||
continue;
|
||||
}
|
||||
if (currentStatus == null) {
|
||||
currentStatus = status;
|
||||
segmentStartIdx = i;
|
||||
} else if (!currentStatus.equals(status)) {
|
||||
// finalize previous segment
|
||||
ChargeDischargeRecordDTO rec = new ChargeDischargeRecordDTO();
|
||||
rec.setStatus(currentStatus);
|
||||
com.evobms.project.vehicledata.domain.VehicleData sv = all.get(segmentStartIdx);
|
||||
com.evobms.project.vehicledata.domain.VehicleData evd = all.get(i - 1);
|
||||
rec.setStartTime(df.format(sv.getTimestamp()));
|
||||
rec.setEndTime(df.format(evd.getTimestamp()));
|
||||
rec.setStartSoc(sv.getSoc());
|
||||
rec.setEndSoc(evd.getSoc());
|
||||
long seconds = (evd.getTimestamp().getTime() - sv.getTimestamp().getTime()) / 1000L;
|
||||
java.math.BigDecimal hours = new java.math.BigDecimal(seconds).divide(new java.math.BigDecimal(3600), 2, java.math.RoundingMode.HALF_UP);
|
||||
rec.setDurationHours(hours);
|
||||
// 忽略过短区段(小于5分钟)
|
||||
if (seconds >= 300) {
|
||||
records.add(rec);
|
||||
}
|
||||
currentStatus = status;
|
||||
segmentStartIdx = i;
|
||||
}
|
||||
prevSoc = soc;
|
||||
}
|
||||
// finalize last
|
||||
if (currentStatus != null && segmentStartIdx >= 0 && all.size() - 1 >= segmentStartIdx) {
|
||||
ChargeDischargeRecordDTO rec = new ChargeDischargeRecordDTO();
|
||||
rec.setStatus(currentStatus);
|
||||
com.evobms.project.vehicledata.domain.VehicleData sv = all.get(segmentStartIdx);
|
||||
com.evobms.project.vehicledata.domain.VehicleData evd = all.get(all.size() - 1);
|
||||
rec.setStartTime(df.format(sv.getTimestamp()));
|
||||
rec.setEndTime(df.format(evd.getTimestamp()));
|
||||
rec.setStartSoc(sv.getSoc());
|
||||
rec.setEndSoc(evd.getSoc());
|
||||
long seconds = (evd.getTimestamp().getTime() - sv.getTimestamp().getTime()) / 1000L;
|
||||
java.math.BigDecimal hours = new java.math.BigDecimal(seconds).divide(new java.math.BigDecimal(3600), 2, java.math.RoundingMode.HALF_UP);
|
||||
rec.setDurationHours(hours);
|
||||
if (seconds >= 300) {
|
||||
records.add(rec);
|
||||
}
|
||||
}
|
||||
|
||||
java.util.Map<String, java.math.BigDecimal[]> monthAgg = new java.util.HashMap<>();
|
||||
for (ChargeDischargeRecordDTO rec : records) {
|
||||
String m = rec.getStartTime().substring(0, 7);
|
||||
java.math.BigDecimal[] pair = monthAgg.computeIfAbsent(m, k -> new java.math.BigDecimal[]{java.math.BigDecimal.ZERO, java.math.BigDecimal.ZERO});
|
||||
if ("充电".equals(rec.getStatus())) {
|
||||
pair[0] = pair[0].add(rec.getDurationHours());
|
||||
} else {
|
||||
pair[1] = pair[1].add(rec.getDurationHours());
|
||||
}
|
||||
}
|
||||
java.util.List<ChargeDischargeMonthDTO> months = new java.util.ArrayList<>();
|
||||
java.util.List<String> keys = new java.util.ArrayList<>(monthAgg.keySet());
|
||||
keys.sort(String::compareTo);
|
||||
for (String k : keys) {
|
||||
ChargeDischargeMonthDTO m = new ChargeDischargeMonthDTO();
|
||||
m.setMonth(k);
|
||||
java.math.BigDecimal[] pair = monthAgg.get(k);
|
||||
m.setChargeHours(pair[0]);
|
||||
m.setDischargeHours(pair[1]);
|
||||
months.add(m);
|
||||
}
|
||||
|
||||
ChargeDischargeHistoryDTO out = new ChargeDischargeHistoryDTO();
|
||||
out.setMonths(months);
|
||||
out.setRecords(records);
|
||||
return R.ok(out);
|
||||
}
|
||||
/**
|
||||
* 导出BBOX管理列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:export')")
|
||||
@Log(title = "BBOX管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出BBOX设备列表")
|
||||
public void export(HttpServletResponse response, BmsDevices bmsDevices)
|
||||
{
|
||||
List<BmsDevices> list = bmsDevicesService.selectBmsDevicesList(bmsDevices);
|
||||
@ -60,17 +226,135 @@ public class BmsDevicesController extends BaseController
|
||||
/**
|
||||
* 获取BBOX管理详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取BBOX设备详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") String id)
|
||||
{
|
||||
return success(bmsDevicesService.selectBmsDevicesById(id));
|
||||
}
|
||||
|
||||
|
||||
/** 子系统去重预取行数(按 timestamp 倒序,一般远小于子系统数×上报次数) */
|
||||
private static final int REALTIME_SUBSYSTEM_PREFETCH = 32;
|
||||
/** 24h 趋势曲线最多点数 */
|
||||
private static final int REALTIME_TREND_MAX_POINTS = 360;
|
||||
|
||||
@GetMapping("/realtime/{deviceId}")
|
||||
@ApiOperation(value = "设备实时数据", notes = "默认不含 dashboard 趋势(24h),避免超时;趋势请调 includeTrends=true 或 GET .../trends", response = DeviceRealtimeAggregateDTO.class)
|
||||
public R<DeviceRealtimeAggregateDTO> realtime(@PathVariable("deviceId") String deviceId, @ApiParam("是否包含 dashboard 24h 趋势(较慢,易触发前端 10s 超时)") @RequestParam(value = "includeTrends", required = false, defaultValue = "true") boolean includeTrends) {
|
||||
RealtimeSnapshot snap = loadRealtimeSnapshot(deviceId);
|
||||
DeviceRealtimeAggregateDTO agg = new DeviceRealtimeAggregateDTO();
|
||||
agg.setDeviceId(deviceId);
|
||||
fillAggregateFromSnapshot(agg, snap);
|
||||
if (includeTrends) {
|
||||
SimpleDateFormat tf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date now = new Date();
|
||||
Date trendBegin = new Date(now.getTime() - 24L * 3600_000L);
|
||||
agg.setDashboard(buildRealtimeDashboard(deviceId, snap.vehicleData, snap.extremeValues, snap.systemStatus, snap.chargeDetail, snap.chargeTemperatures, snap.voltageChannels, trendBegin, now, tf));
|
||||
}
|
||||
return R.ok(agg);
|
||||
}
|
||||
|
||||
@GetMapping("/realtime/{deviceId}/trends")
|
||||
@ApiOperation(value = "设备实时 24h 趋势(dashboard)", notes = "与 realtime 拆分,避免与快照同请求导致 Axios 10s 超时", response = DeviceRealtimeDTO.class)
|
||||
public R<DeviceRealtimeDTO> realtimeTrends(
|
||||
@PathVariable("deviceId") String deviceId,
|
||||
@ApiParam("向前小时数,默认 24") @RequestParam(value = "hours", required = false, defaultValue = "24") int hours) {
|
||||
RealtimeSnapshot snap = loadRealtimeSnapshot(deviceId);
|
||||
SimpleDateFormat tf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date now = new Date();
|
||||
int h = hours <= 0 ? 24 : Math.min(hours, 168);
|
||||
Date trendBegin = new Date(now.getTime() - (long) h * 3600_000L);
|
||||
return R.ok(buildRealtimeDashboard(deviceId, snap.vehicleData, snap.extremeValues, snap.systemStatus,
|
||||
snap.chargeDetail, snap.chargeTemperatures, snap.voltageChannels, trendBegin, now, tf));
|
||||
}
|
||||
|
||||
/**
|
||||
* 与 {@link #realtime(String)} 同源字段的历史平铺列表:时间范围内全部 vehicle_data 在库内分页(pageNum/pageSize),
|
||||
* 每页再与其它表按时间点合并;pageSize 仅支持 10、20、100、500。
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:query')")
|
||||
@GetMapping("/realtime/history/{deviceId}")
|
||||
@ApiOperation(value = "设备实时同源历史(平铺分页)", notes = "对 beginTime~endTime 内全部整车记录分页;参数 pageNum、pageSize(10|20|100|500);total 为符合条件的总条数", response = DeviceHistoryFlatRowDTO.class)
|
||||
public TableDataInfo realtimeHistoryFlat(
|
||||
@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId,
|
||||
@ApiParam(value = "开始时间戳(毫秒),与 beginTime 二选一") @RequestParam(value = "start", required = false) Long startMillis,
|
||||
@ApiParam(value = "结束时间戳(毫秒),与 endTime 二选一") @RequestParam(value = "end", required = false) Long endMillis,
|
||||
@ApiParam(value = "开始时间 yyyy-MM-dd HH:mm:ss") @RequestParam(value = "beginTime", required = false) String beginTimeStr,
|
||||
@ApiParam(value = "结束时间 yyyy-MM-dd HH:mm:ss") @RequestParam(value = "endTime", required = false) String endTimeStr,
|
||||
@ApiParam(value = "排序:desc 默认最新在前;asc 时间正序") @RequestParam(value = "order", required = false, defaultValue = "desc") String order,
|
||||
@ApiParam(value = "是否查询总条数 COUNT;大数据量可传 false 加快首屏") @RequestParam(value = "count", required = false, defaultValue = "true") boolean countTotal
|
||||
) {
|
||||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date end;
|
||||
Date start;
|
||||
boolean userRange = startMillis != null || (beginTimeStr != null && !beginTimeStr.isEmpty());
|
||||
try {
|
||||
end = parseHistoryEnd(endMillis, endTimeStr, df);
|
||||
start = parseHistoryStart(startMillis, beginTimeStr, df, end);
|
||||
} catch (ParseException e) {
|
||||
TableDataInfo err = new TableDataInfo();
|
||||
err.setCode(HttpStatus.ERROR);
|
||||
err.setMsg("时间解析失败,请使用 yyyy-MM-dd HH:mm:ss 或毫秒时间戳");
|
||||
err.setRows(Collections.emptyList());
|
||||
err.setTotal(0);
|
||||
return err;
|
||||
}
|
||||
boolean desc = !"asc".equalsIgnoreCase(order);
|
||||
if (!userRange) {
|
||||
start = clampHistoryStart(start, end);
|
||||
}
|
||||
int pageSize = com.evobms.common.utils.PageUtils.startHistoryPage(countTotal);
|
||||
List<VehicleData> vehicles = vehicleDataService.selectVehicleDataListForHistory(deviceId, start, end, desc);
|
||||
// total 必须来自 PageHelper 分页查询结果;不能用组装后的 rows(否则 total=当前页条数)
|
||||
long total = new com.github.pagehelper.PageInfo<>(vehicles).getTotal();
|
||||
SimpleDateFormat tf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
List<DeviceHistoryFlatRowDTO> rows = deviceRealtimeHistoryAssembler.build(deviceId, vehicles, tf, pageSize);
|
||||
TableDataInfo table = getDataTable(rows);
|
||||
table.setTotal(total);
|
||||
return table;
|
||||
}
|
||||
|
||||
private static Date parseHistoryEnd(Long endMillis, String endTimeStr, SimpleDateFormat df) throws ParseException {
|
||||
if (endMillis != null) {
|
||||
return new Date(endMillis);
|
||||
}
|
||||
if (endTimeStr != null && !endTimeStr.isEmpty()) {
|
||||
return df.parse(endTimeStr);
|
||||
}
|
||||
return new Date();
|
||||
}
|
||||
|
||||
private static Date parseHistoryStart(Long startMillis, String beginTimeStr, SimpleDateFormat df, Date end) throws ParseException {
|
||||
if (startMillis != null) {
|
||||
return new Date(startMillis);
|
||||
}
|
||||
if (beginTimeStr != null && !beginTimeStr.isEmpty()) {
|
||||
return df.parse(beginTimeStr);
|
||||
}
|
||||
return new Date(end.getTime() - 7L * 86400_000L);
|
||||
}
|
||||
|
||||
/** 单次查询时间窗上限 7 天,避免一次扫过多行 */
|
||||
private static Date clampHistoryStart(Date start, Date end) {
|
||||
if (start == null || end == null) {
|
||||
return start;
|
||||
}
|
||||
long maxWindow = 7L * 86400_000L;
|
||||
if (end.getTime() - start.getTime() > maxWindow) {
|
||||
return new Date(end.getTime() - maxWindow);
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BBOX管理
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:add')")
|
||||
@Log(title = "BBOX管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增BBOX设备")
|
||||
public AjaxResult add(@RequestBody BmsDevices bmsDevices)
|
||||
{
|
||||
return toAjax(bmsDevicesService.insertBmsDevices(bmsDevices));
|
||||
@ -79,8 +363,10 @@ public class BmsDevicesController extends BaseController
|
||||
/**
|
||||
* 修改BBOX管理
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:edit')")
|
||||
@Log(title = "BBOX管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改BBOX设备")
|
||||
public AjaxResult edit(@RequestBody BmsDevices bmsDevices)
|
||||
{
|
||||
return toAjax(bmsDevicesService.updateBmsDevices(bmsDevices));
|
||||
@ -89,10 +375,400 @@ public class BmsDevicesController extends BaseController
|
||||
/**
|
||||
* 删除BBOX管理
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:devices:remove')")
|
||||
@Log(title = "BBOX管理", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除BBOX设备")
|
||||
public AjaxResult remove(@PathVariable String[] ids)
|
||||
{
|
||||
return toAjax(bmsDevicesService.deleteBmsDevicesByIds(ids));
|
||||
}
|
||||
|
||||
/** 扁平视图:与原始列表共用同一批查询结果,避免重复组装且趋势只在 dashboard 中暴露一份 */
|
||||
private DeviceRealtimeDTO buildRealtimeDashboard(
|
||||
String deviceId,
|
||||
VehicleData vd,
|
||||
ExtremeValues ev,
|
||||
BmsSystemStatus ss,
|
||||
BmsChargeDetail cd,
|
||||
List<BmsChargeTemperature> chargeTemps,
|
||||
List<BmsVoltageChannelData> voltageChs,
|
||||
Date trendBegin,
|
||||
Date trendEnd,
|
||||
SimpleDateFormat tf) {
|
||||
DeviceRealtimeDTO dto = new DeviceRealtimeDTO();
|
||||
dto.setDeviceId(deviceId);
|
||||
|
||||
SystemStatusSection sys = new SystemStatusSection();
|
||||
if (vd != null) {
|
||||
sys.setTotalVoltage(vd.getTotalVoltage());
|
||||
sys.setTotalCurrent(vd.getTotalCurrent());
|
||||
sys.setSoc(vd.getSoc());
|
||||
}
|
||||
if (ev != null) {
|
||||
sys.setMaxCellVoltage(ev.getMaxVoltageValue());
|
||||
sys.setMaxCellPos(joinSubsysIndex(ev.getMaxVoltageSubsystemNo(), ev.getMaxVoltageBatteryNo()));
|
||||
sys.setMinCellVoltage(ev.getMinVoltageValue());
|
||||
sys.setMinCellPos(joinSubsysIndex(ev.getMinVoltageSubsystemNo(), ev.getMinVoltageBatteryNo()));
|
||||
sys.setMaxTemp(ev.getMaxTempValue());
|
||||
sys.setMaxTempPos(joinSubsysIndex(ev.getMaxTempSubsystemNo(), ev.getMaxTempProbeNo()));
|
||||
sys.setMinTemp(ev.getMinTempValue());
|
||||
sys.setMinTempPos(joinSubsysIndex(ev.getMinTempSubsystemNo(), ev.getMinTempProbeNo()));
|
||||
}
|
||||
dto.setSystemStatus(sys);
|
||||
|
||||
RunStatusSection run = new RunStatusSection();
|
||||
if (vd != null) {
|
||||
run.setChargingStatus(vd.getChargingStatus());
|
||||
}
|
||||
if (ss != null) {
|
||||
run.setRelayStatus(ss.getRelayStatus());
|
||||
run.setOnaaccStatus(ss.getOnaaccStatus());
|
||||
run.setResetCount(ss.getResetCount());
|
||||
run.setCycleCount(ss.getCycleCount());
|
||||
run.setSample25v(ss.getSample25v());
|
||||
run.setSample5v(ss.getSample5v());
|
||||
}
|
||||
dto.setRunStatus(run);
|
||||
|
||||
ChargeSection chg = new ChargeSection();
|
||||
if (cd != null) {
|
||||
chg.setAcChargeCurrent(cd.getAcChargeCurrent());
|
||||
chg.setAcChargeVoltage(cd.getAcChargeVoltage());
|
||||
chg.setDcChargeCurrent(cd.getDcChargeCurrent());
|
||||
chg.setDcChargeVoltage(cd.getDcChargeVoltage());
|
||||
chg.setChargeTime(cd.getChargeTime());
|
||||
chg.setAcStopCode(cd.getAcStopCode());
|
||||
chg.setDcStopCode(cd.getDcStopCode());
|
||||
chg.setAcCpValue(cd.getAcCpValue());
|
||||
chg.setAcGunResistance(cd.getAcGunResistance());
|
||||
chg.setChargingStage(cd.getChargingStage());
|
||||
chg.setAcStage(cd.getAcStage());
|
||||
chg.setDcStage(cd.getDcStage());
|
||||
}
|
||||
dto.setCharge(chg);
|
||||
|
||||
StatisticsSection stat = new StatisticsSection();
|
||||
if (ss != null) {
|
||||
stat.setCycleCount(ss.getCycleCount());
|
||||
}
|
||||
stat.setTotalRunHours(0L);
|
||||
stat.setTotalChargeHours(0L);
|
||||
stat.setTotalDischargeHours(0L);
|
||||
dto.setStatistics(stat);
|
||||
|
||||
dto.setTemperatures(toChargeTemperatureNameValues(chargeTemps, tf));
|
||||
dto.setVoltages(toVoltageChannelNameValues(voltageChs, tf));
|
||||
dto.setFaults(new ArrayList<>());
|
||||
dto.setVoltageTrend(buildRtp1VoltageTrendSeries(deviceId, trendBegin, trendEnd, tf));
|
||||
dto.setTemperatureTrend(buildT1TemperatureTrendSeries(deviceId, trendBegin, trendEnd, tf));
|
||||
|
||||
List<VehicleData> vehicleTrendRows = listVehicleDataForTrend(deviceId, trendBegin, trendEnd);
|
||||
dto.setTotalVoltageTrend(Collections.singletonList(
|
||||
buildVehicleNumericTrendSeries(vehicleTrendRows, "总电压(V)", trendBegin, trendEnd, tf, VehicleData::getTotalVoltage)));
|
||||
dto.setTotalCurrentTrend(Collections.singletonList(
|
||||
buildVehicleNumericTrendSeries(vehicleTrendRows, "总电流(A)", trendBegin, trendEnd, tf, VehicleData::getTotalCurrent)));
|
||||
dto.setSocTrend(Collections.singletonList(
|
||||
buildVehicleNumericTrendSeries(vehicleTrendRows, "SOC(%)", trendBegin, trendEnd, tf,
|
||||
v -> v.getSoc() == null ? null : BigDecimal.valueOf(v.getSoc()))));
|
||||
return dto;
|
||||
}
|
||||
|
||||
/** 趋势图:DB 侧限量采样,避免 24h 全量拉取 */
|
||||
private List<VehicleData> listVehicleDataForTrend(String deviceId, Date begin, Date end) {
|
||||
return vehicleDataService.selectVehicleDataTrendInRange(deviceId, begin, end, REALTIME_TREND_MAX_POINTS);
|
||||
}
|
||||
|
||||
private static Date vehicleTrendPointTime(VehicleData v) {
|
||||
if (v == null) {
|
||||
return null;
|
||||
}
|
||||
return v.getTimestamp() != null ? v.getTimestamp() : v.getCreateTime();
|
||||
}
|
||||
|
||||
private static LineSeriesDTO buildVehicleNumericTrendSeries(
|
||||
List<VehicleData> rows,
|
||||
String seriesName,
|
||||
Date rangeBegin,
|
||||
Date rangeEnd,
|
||||
SimpleDateFormat tf,
|
||||
Function<VehicleData, BigDecimal> valueFn) {
|
||||
List<TimePointDTO> points = new ArrayList<>();
|
||||
if (rows != null) {
|
||||
for (VehicleData v : rows) {
|
||||
Date t = vehicleTrendPointTime(v);
|
||||
if (t == null || t.before(rangeBegin) || t.after(rangeEnd)) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal val = valueFn.apply(v);
|
||||
if (val == null) {
|
||||
continue;
|
||||
}
|
||||
TimePointDTO p = new TimePointDTO();
|
||||
p.setTime(tf.format(t));
|
||||
p.setValue(val);
|
||||
points.add(p);
|
||||
}
|
||||
}
|
||||
LineSeriesDTO series = new LineSeriesDTO();
|
||||
series.setName(seriesName);
|
||||
series.setPoints(points);
|
||||
return series;
|
||||
}
|
||||
|
||||
private static String joinSubsysIndex(Integer a, Integer b) {
|
||||
if (a == null || b == null) {
|
||||
return null;
|
||||
}
|
||||
return a + "-" + b;
|
||||
}
|
||||
|
||||
private static List<NameValueDTO> toChargeTemperatureNameValues(List<BmsChargeTemperature> temps, SimpleDateFormat tf) {
|
||||
if (temps == null || temps.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<NameValueDTO> out = new ArrayList<>(temps.size());
|
||||
for (BmsChargeTemperature t : temps) {
|
||||
NameValueDTO nv = new NameValueDTO();
|
||||
nv.setName("T" + t.getTempIndex());
|
||||
nv.setValue(t.getTemperature() == null ? 0 : t.getTemperature().longValue());
|
||||
nv.setCreateTime(formatTime(t.getCreateTime(), tf));
|
||||
out.add(nv);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static List<NameValueDTO> toVoltageChannelNameValues(List<BmsVoltageChannelData> chs, SimpleDateFormat tf) {
|
||||
if (chs == null || chs.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<NameValueDTO> out = new ArrayList<>(chs.size());
|
||||
for (BmsVoltageChannelData c : chs) {
|
||||
NameValueDTO nv = new NameValueDTO();
|
||||
nv.setName((c.getChannelType() == null ? "CH" : c.getChannelType()) + "-" + c.getChannelIndex());
|
||||
nv.setValue(c.getVoltage() == null ? 0 : c.getVoltage().longValue());
|
||||
nv.setCreateTime(formatTime(c.getCreateTime(), tf));
|
||||
out.add(nv);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static String formatTime(Date d, SimpleDateFormat tf) {
|
||||
return d == null ? null : tf.format(d);
|
||||
}
|
||||
|
||||
private List<LineSeriesDTO> buildRtp1VoltageTrendSeries(String deviceId, Date begin, Date end, SimpleDateFormat tf) {
|
||||
List<BmsVoltageChannelData> rows = bmsVoltageChannelDataService.lambdaQuery()
|
||||
.eq(BmsVoltageChannelData::getDeviceId, deviceId)
|
||||
.eq(BmsVoltageChannelData::getChannelType, "RTP")
|
||||
.eq(BmsVoltageChannelData::getChannelIndex, 1)
|
||||
.isNotNull(BmsVoltageChannelData::getTimestamp)
|
||||
.ge(BmsVoltageChannelData::getTimestamp, begin)
|
||||
.le(BmsVoltageChannelData::getTimestamp, end)
|
||||
.orderByDesc(BmsVoltageChannelData::getTimestamp)
|
||||
.last("limit " + REALTIME_TREND_MAX_POINTS)
|
||||
.list();
|
||||
Collections.reverse(rows);
|
||||
List<TimePointDTO> points = new ArrayList<>(rows.size());
|
||||
for (BmsVoltageChannelData it : rows) {
|
||||
TimePointDTO p = new TimePointDTO();
|
||||
Date t = it.getTimestamp() != null ? it.getTimestamp() : it.getCreateTime();
|
||||
p.setTime(formatTime(t, tf));
|
||||
p.setValue(it.getVoltage());
|
||||
points.add(p);
|
||||
}
|
||||
LineSeriesDTO series = new LineSeriesDTO();
|
||||
series.setName("RTP-1");
|
||||
series.setPoints(points);
|
||||
return Collections.singletonList(series);
|
||||
}
|
||||
|
||||
private List<LineSeriesDTO> buildT1TemperatureTrendSeries(String deviceId, Date begin, Date end, SimpleDateFormat tf) {
|
||||
List<BmsChargeTemperature> rows = bmsChargeTemperatureService.lambdaQuery()
|
||||
.eq(BmsChargeTemperature::getDeviceId, deviceId)
|
||||
.isNotNull(BmsChargeTemperature::getTimestamp)
|
||||
.ge(BmsChargeTemperature::getTimestamp, begin)
|
||||
.le(BmsChargeTemperature::getTimestamp, end)
|
||||
.eq(BmsChargeTemperature::getTempIndex, 1)
|
||||
.orderByDesc(BmsChargeTemperature::getTimestamp)
|
||||
.last("limit " + REALTIME_TREND_MAX_POINTS)
|
||||
.list();
|
||||
Collections.reverse(rows);
|
||||
List<TimePointDTO> points = new ArrayList<>(rows.size());
|
||||
for (BmsChargeTemperature it : rows) {
|
||||
TimePointDTO p = new TimePointDTO();
|
||||
Date t = it.getTimestamp() != null ? it.getTimestamp() : it.getCreateTime();
|
||||
p.setTime(formatTime(t, tf));
|
||||
p.setValue(it.getTemperature());
|
||||
points.add(p);
|
||||
}
|
||||
LineSeriesDTO series = new LineSeriesDTO();
|
||||
series.setName("T1");
|
||||
series.setPoints(points);
|
||||
return Collections.singletonList(series);
|
||||
}
|
||||
|
||||
/** 并行加载实时快照各表最新数据(默认不含 24h 趋势 SQL) */
|
||||
private RealtimeSnapshot loadRealtimeSnapshot(String deviceId) {
|
||||
CompletableFuture<VehicleData> vehicleF = CompletableFuture.supplyAsync(
|
||||
() -> vehicleDataService.selectLatestByDeviceId(deviceId));
|
||||
CompletableFuture<ExtremeValues> extremeF = CompletableFuture.supplyAsync(
|
||||
() -> extremeValuesService.selectLatestByDeviceId(deviceId));
|
||||
CompletableFuture<VehicleLocation> locationF = CompletableFuture.supplyAsync(
|
||||
() -> vehicleLocationService.selectLatestByDeviceId(deviceId));
|
||||
CompletableFuture<BmsSystemStatus> systemF = CompletableFuture.supplyAsync(
|
||||
() -> latestSystemStatus(deviceId));
|
||||
CompletableFuture<BmsChargeDetail> chargeDetailF = CompletableFuture.supplyAsync(
|
||||
() -> latestChargeDetail(deviceId));
|
||||
CompletableFuture<BmsRuntimeData> runtimeF = CompletableFuture.supplyAsync(
|
||||
() -> latestRuntimeData(deviceId));
|
||||
CompletableFuture<BmsSopData> sopF = CompletableFuture.supplyAsync(
|
||||
() -> latestSopData(deviceId));
|
||||
CompletableFuture<List<SubsystemVoltage>> svF = CompletableFuture.supplyAsync(
|
||||
() -> listLatestSubsystemVoltages(deviceId));
|
||||
CompletableFuture<List<SubsystemTemperature>> stF = CompletableFuture.supplyAsync(
|
||||
() -> listLatestSubsystemTemperatures(deviceId));
|
||||
CompletableFuture<List<BmsChargeTemperature>> chargeTempF = CompletableFuture.supplyAsync(
|
||||
() -> listLatestChargeTemperatures(deviceId));
|
||||
CompletableFuture<List<BmsVoltageChannelData>> voltageChF = CompletableFuture.supplyAsync(
|
||||
() -> listLatestVoltageChannels(deviceId));
|
||||
|
||||
CompletableFuture.allOf(vehicleF, extremeF, locationF, systemF, chargeDetailF, runtimeF, sopF,
|
||||
svF, stF, chargeTempF, voltageChF).join();
|
||||
|
||||
RealtimeSnapshot snap = new RealtimeSnapshot();
|
||||
snap.vehicleData = vehicleF.join();
|
||||
snap.extremeValues = extremeF.join();
|
||||
snap.latestLocation = locationF.join();
|
||||
snap.systemStatus = systemF.join();
|
||||
snap.chargeDetail = chargeDetailF.join();
|
||||
snap.runtimeData = runtimeF.join();
|
||||
snap.sopData = sopF.join();
|
||||
snap.subsystemVoltageRows = svF.join();
|
||||
snap.subsystemTemperatureRows = stF.join();
|
||||
snap.chargeTemperatures = chargeTempF.join();
|
||||
snap.voltageChannels = voltageChF.join();
|
||||
return snap;
|
||||
}
|
||||
|
||||
private static void fillAggregateFromSnapshot(DeviceRealtimeAggregateDTO agg, RealtimeSnapshot snap) {
|
||||
agg.setVehicleData(snap.vehicleData);
|
||||
agg.setLatestLocation(snap.latestLocation);
|
||||
agg.setExtremeValues(snap.extremeValues);
|
||||
agg.setSystemStatus(snap.systemStatus);
|
||||
agg.setChargeDetail(snap.chargeDetail);
|
||||
agg.setRuntimeData(snap.runtimeData);
|
||||
agg.setSopData(snap.sopData);
|
||||
agg.setChargeTemperatures(snap.chargeTemperatures);
|
||||
agg.setVoltageChannels(snap.voltageChannels);
|
||||
List<SubsystemVoltage> svRows = snap.subsystemVoltageRows;
|
||||
agg.setSubsystemVoltage(svRows == null || svRows.isEmpty() ? null : svRows.get(0));
|
||||
agg.setSubsystemVoltages(latestOnePerSubsystem(svRows, SubsystemVoltage::getSubsystemNo));
|
||||
List<SubsystemTemperature> stRows = snap.subsystemTemperatureRows;
|
||||
agg.setSubsystemTemperature(stRows == null || stRows.isEmpty() ? null : stRows.get(0));
|
||||
agg.setSubsystemTemperatures(latestOnePerSubsystem(stRows, SubsystemTemperature::getSubsystemNo));
|
||||
}
|
||||
|
||||
private BmsSystemStatus latestSystemStatus(String deviceId) {
|
||||
return bmsSystemStatusService.lambdaQuery()
|
||||
.eq(BmsSystemStatus::getDeviceId, deviceId)
|
||||
.isNotNull(BmsSystemStatus::getTimestamp)
|
||||
.orderByDesc(BmsSystemStatus::getTimestamp)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
}
|
||||
|
||||
private BmsChargeDetail latestChargeDetail(String deviceId) {
|
||||
return bmsChargeDetailService.lambdaQuery()
|
||||
.eq(BmsChargeDetail::getDeviceId, deviceId)
|
||||
.isNotNull(BmsChargeDetail::getTimestamp)
|
||||
.orderByDesc(BmsChargeDetail::getTimestamp)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
}
|
||||
|
||||
private BmsRuntimeData latestRuntimeData(String deviceId) {
|
||||
return bmsRuntimeDataService.lambdaQuery()
|
||||
.eq(BmsRuntimeData::getDeviceId, deviceId)
|
||||
.isNotNull(BmsRuntimeData::getTimestamp)
|
||||
.orderByDesc(BmsRuntimeData::getTimestamp)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
}
|
||||
|
||||
private BmsSopData latestSopData(String deviceId) {
|
||||
return bmsSopDataService.lambdaQuery()
|
||||
.eq(BmsSopData::getDeviceId, deviceId)
|
||||
.isNotNull(BmsSopData::getTimestamp)
|
||||
.orderByDesc(BmsSopData::getTimestamp)
|
||||
.last("limit 1")
|
||||
.one();
|
||||
}
|
||||
|
||||
private List<SubsystemVoltage> listLatestSubsystemVoltages(String deviceId) {
|
||||
return subsystemVoltageService.lambdaQuery()
|
||||
.eq(SubsystemVoltage::getDeviceId, deviceId)
|
||||
.isNotNull(SubsystemVoltage::getTimestamp)
|
||||
.orderByDesc(SubsystemVoltage::getTimestamp)
|
||||
.last("limit " + REALTIME_SUBSYSTEM_PREFETCH)
|
||||
.list();
|
||||
}
|
||||
|
||||
private List<SubsystemTemperature> listLatestSubsystemTemperatures(String deviceId) {
|
||||
return subsystemTemperatureService.lambdaQuery()
|
||||
.eq(SubsystemTemperature::getDeviceId, deviceId)
|
||||
.isNotNull(SubsystemTemperature::getTimestamp)
|
||||
.orderByDesc(SubsystemTemperature::getTimestamp)
|
||||
.last("limit " + REALTIME_SUBSYSTEM_PREFETCH)
|
||||
.list();
|
||||
}
|
||||
|
||||
private List<BmsChargeTemperature> listLatestChargeTemperatures(String deviceId) {
|
||||
return bmsChargeTemperatureService.lambdaQuery()
|
||||
.eq(BmsChargeTemperature::getDeviceId, deviceId)
|
||||
.isNotNull(BmsChargeTemperature::getTimestamp)
|
||||
.orderByDesc(BmsChargeTemperature::getTimestamp)
|
||||
.last("limit 8")
|
||||
.list();
|
||||
}
|
||||
|
||||
private List<BmsVoltageChannelData> listLatestVoltageChannels(String deviceId) {
|
||||
return bmsVoltageChannelDataService.lambdaQuery()
|
||||
.eq(BmsVoltageChannelData::getDeviceId, deviceId)
|
||||
.isNotNull(BmsVoltageChannelData::getTimestamp)
|
||||
.orderByDesc(BmsVoltageChannelData::getTimestamp)
|
||||
.last("limit 16")
|
||||
.list();
|
||||
}
|
||||
|
||||
private static final class RealtimeSnapshot {
|
||||
VehicleData vehicleData;
|
||||
ExtremeValues extremeValues;
|
||||
VehicleLocation latestLocation;
|
||||
BmsSystemStatus systemStatus;
|
||||
BmsChargeDetail chargeDetail;
|
||||
BmsRuntimeData runtimeData;
|
||||
BmsSopData sopData;
|
||||
List<SubsystemVoltage> subsystemVoltageRows;
|
||||
List<SubsystemTemperature> subsystemTemperatureRows;
|
||||
List<BmsChargeTemperature> chargeTemperatures;
|
||||
List<BmsVoltageChannelData> voltageChannels;
|
||||
}
|
||||
|
||||
/** 从按时间倒序的结果中取每个子系统号的第一条(即该子系统最新数据) */
|
||||
private static <T> List<T> latestOnePerSubsystem(List<T> orderedNewestFirst, Function<T, Integer> subsystemNoFn) {
|
||||
if (orderedNewestFirst == null || orderedNewestFirst.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<Integer, T> seen = new LinkedHashMap<>();
|
||||
for (T row : orderedNewestFirst) {
|
||||
Integer no = subsystemNoFn.apply(row);
|
||||
if (no != null && !seen.containsKey(no)) {
|
||||
seen.put(no, row);
|
||||
}
|
||||
}
|
||||
List<T> out = new ArrayList<>(seen.values());
|
||||
out.sort(Comparator.comparing(subsystemNoFn, Comparator.nullsLast(Integer::compareTo)));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ package com.evobms.project.system.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
@ -17,43 +19,53 @@ import com.evobms.framework.web.domain.BaseEntity;
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@ApiModel(value = "BmsDevices", description = "BBOX设备管理对象")
|
||||
public class BmsDevices extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@ApiModelProperty("主键ID")
|
||||
private String id;
|
||||
|
||||
/** 设备唯一编号 */
|
||||
@ApiModelProperty("设备唯一编号")
|
||||
@Excel(name = "设备唯一编号")
|
||||
private String deviceId;
|
||||
|
||||
/** 设备名称 */
|
||||
@ApiModelProperty("设备名称")
|
||||
@Excel(name = "设备名称")
|
||||
private String deviceName;
|
||||
/** 设备名称 */
|
||||
@ApiModelProperty("设备SN码")
|
||||
@Excel(name = "设备SN码")
|
||||
private String deviceSn;
|
||||
|
||||
/** 设备类型 */
|
||||
@ApiModelProperty("设备类型")
|
||||
@Excel(name = "设备类型")
|
||||
private String deviceType;
|
||||
|
||||
/** 设备状态 */
|
||||
@ApiModelProperty("设备状态")
|
||||
@Excel(name = "设备状态")
|
||||
private String status;
|
||||
|
||||
/** 设备IP地址 */
|
||||
@ApiModelProperty("设备IP地址")
|
||||
@Excel(name = "设备IP地址")
|
||||
private String ipAddress;
|
||||
|
||||
/** 固件版本号 */
|
||||
/** 服务器固件版本号 */
|
||||
@ApiModelProperty("固件版本号")
|
||||
@Excel(name = "固件版本号")
|
||||
private String firmwareVersion;
|
||||
|
||||
/** 最后在线时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "最后在线时间", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty("最后在线时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "最后在线时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date lastOnline;
|
||||
|
||||
}
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
package com.evobms.project.system.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
|
||||
/**
|
||||
* BBOX管理Mapper接口
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-10
|
||||
*/
|
||||
public interface BmsDevicesMapper
|
||||
{
|
||||
public interface BmsDevicesMapper extends BaseMapper<BmsDevices> {
|
||||
/**
|
||||
* 查询BBOX管理
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return BBOX管理
|
||||
*/
|
||||
@ -21,7 +22,7 @@ public interface BmsDevicesMapper
|
||||
|
||||
/**
|
||||
* 查询BBOX管理列表
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return BBOX管理集合
|
||||
*/
|
||||
@ -29,7 +30,7 @@ public interface BmsDevicesMapper
|
||||
|
||||
/**
|
||||
* 新增BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@ -37,7 +38,7 @@ public interface BmsDevicesMapper
|
||||
|
||||
/**
|
||||
* 修改BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@ -45,7 +46,7 @@ public interface BmsDevicesMapper
|
||||
|
||||
/**
|
||||
* 删除BBOX管理
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -53,7 +54,7 @@ public interface BmsDevicesMapper
|
||||
|
||||
/**
|
||||
* 批量删除BBOX管理
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
|
||||
@ -5,15 +5,15 @@ import com.evobms.project.system.domain.BmsDevices;
|
||||
|
||||
/**
|
||||
* BBOX管理Service接口
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-10
|
||||
*/
|
||||
public interface IBmsDevicesService
|
||||
public interface IBmsDevicesService
|
||||
{
|
||||
/**
|
||||
* 查询BBOX管理
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return BBOX管理
|
||||
*/
|
||||
@ -21,7 +21,7 @@ public interface IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 查询BBOX管理列表
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return BBOX管理集合
|
||||
*/
|
||||
@ -29,7 +29,7 @@ public interface IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 新增BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@ -37,7 +37,7 @@ public interface IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 修改BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@ -45,7 +45,7 @@ public interface IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 批量删除BBOX管理
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的BBOX管理主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
@ -53,9 +53,13 @@ public interface IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 删除BBOX管理信息
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteBmsDevicesById(String id);
|
||||
|
||||
BmsDevices selectBmsDevicesBySn(String deviceSn);
|
||||
|
||||
BmsDevices selectBmsDevicesList1(BmsDevices query);
|
||||
}
|
||||
|
||||
@ -1,28 +1,33 @@
|
||||
package com.evobms.project.system.service.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.evobms.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.evobms.project.system.mapper.BmsDevicesMapper;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import com.evobms.project.system.service.IBmsDevicesService;
|
||||
|
||||
/**
|
||||
* BBOX管理Service业务层处理
|
||||
*
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-10-10
|
||||
*/
|
||||
@Service
|
||||
public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
public class BmsDevicesServiceImpl extends ServiceImpl<BmsDevicesMapper, BmsDevices> implements IBmsDevicesService
|
||||
{
|
||||
@Autowired
|
||||
private BmsDevicesMapper bmsDevicesMapper;
|
||||
|
||||
/**
|
||||
* 查询BBOX管理
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return BBOX管理
|
||||
*/
|
||||
@ -34,19 +39,37 @@ public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 查询BBOX管理列表
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return BBOX管理
|
||||
*/
|
||||
@Override
|
||||
public List<BmsDevices> selectBmsDevicesList(BmsDevices bmsDevices)
|
||||
{
|
||||
return bmsDevicesMapper.selectBmsDevicesList(bmsDevices);
|
||||
LambdaQueryWrapper<BmsDevices> qw = new LambdaQueryWrapper<>();
|
||||
if (bmsDevices != null) {
|
||||
if (bmsDevices.getDeviceId() != null && !bmsDevices.getDeviceId().isEmpty()) {
|
||||
qw.eq(BmsDevices::getDeviceId, bmsDevices.getDeviceId());
|
||||
}
|
||||
Map<String, Object> params = bmsDevices.getParams();
|
||||
if (params != null) {
|
||||
Date begin = DateUtils.parseDate(params.get("beginTime"));
|
||||
Date end = DateUtils.parseDate(params.get("endTime"));
|
||||
if (begin != null) {
|
||||
qw.and(w -> w.ge(BmsDevices::getUpdateTime, begin).or().ge(BmsDevices::getCreateTime, begin));
|
||||
}
|
||||
if (end != null) {
|
||||
qw.and(w -> w.le(BmsDevices::getUpdateTime, end).or().le(BmsDevices::getCreateTime, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
qw.orderByDesc(BmsDevices::getUpdateTime).orderByDesc(BmsDevices::getCreateTime);
|
||||
return bmsDevicesMapper.selectList(qw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@ -59,12 +82,12 @@ public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 修改BBOX管理
|
||||
*
|
||||
*
|
||||
* @param bmsDevices BBOX管理
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateBmsDevices(BmsDevices bmsDevices)
|
||||
public int updateBmsDevices(BmsDevices bmsDevices)
|
||||
{
|
||||
bmsDevices.setUpdateTime(DateUtils.getNowDate());
|
||||
return bmsDevicesMapper.updateBmsDevices(bmsDevices);
|
||||
@ -72,7 +95,7 @@ public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 批量删除BBOX管理
|
||||
*
|
||||
*
|
||||
* @param ids 需要删除的BBOX管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -84,7 +107,7 @@ public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
|
||||
/**
|
||||
* 删除BBOX管理信息
|
||||
*
|
||||
*
|
||||
* @param id BBOX管理主键
|
||||
* @return 结果
|
||||
*/
|
||||
@ -93,4 +116,22 @@ public class BmsDevicesServiceImpl implements IBmsDevicesService
|
||||
{
|
||||
return bmsDevicesMapper.deleteBmsDevicesById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BmsDevices selectBmsDevicesBySn(String deviceSn) {
|
||||
LambdaQueryWrapper<BmsDevices> bmslq = new LambdaQueryWrapper<>();
|
||||
bmslq.eq(BmsDevices::getDeviceSn, deviceSn);
|
||||
return baseMapper.selectOne(bmslq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BmsDevices selectBmsDevicesList1(BmsDevices bmsDevices) {
|
||||
LambdaQueryWrapper<BmsDevices> eq = new LambdaQueryWrapper<>();
|
||||
if (bmsDevices != null) {
|
||||
eq.eq(BmsDevices::getDeviceSn, bmsDevices.getDeviceSn());
|
||||
return baseMapper.selectOne(eq);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,476 @@
|
||||
package com.evobms.project.vehicledata.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.evobms.framework.web.domain.R;
|
||||
import com.evobms.project.battery.domain.ExtremeValues;
|
||||
import com.evobms.project.battery.domain.SubsystemTemperature;
|
||||
import com.evobms.project.battery.domain.SubsystemVoltage;
|
||||
import com.evobms.project.battery.service.IExtremeValuesService;
|
||||
import com.evobms.project.battery.service.ISubsystemTemperatureService;
|
||||
import com.evobms.project.battery.service.ISubsystemVoltageService;
|
||||
import com.evobms.project.system.domain.BmsDevices;
|
||||
import com.evobms.project.system.mapper.BmsDevicesMapper;
|
||||
import com.evobms.project.vehicledata.domain.HomeDashboardDTO;
|
||||
import com.evobms.project.vehicledata.domain.VehicleData;
|
||||
import com.evobms.project.vehicledata.domain.VehicleLocation;
|
||||
import com.evobms.project.vehicledata.dto.*;
|
||||
import com.evobms.project.vehicledata.service.IVehicleDataService;
|
||||
import com.evobms.project.vehicledata.service.IVehicleLocationService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 首页数据Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@Api(tags = "首页数据统计")
|
||||
public class BatteryChartController {
|
||||
|
||||
@Autowired
|
||||
private IVehicleDataService vehicleDataService;
|
||||
|
||||
@Autowired
|
||||
private IVehicleLocationService vehicleLocationService;
|
||||
|
||||
@Autowired
|
||||
private ISubsystemVoltageService subsystemVoltageService;
|
||||
|
||||
@Autowired
|
||||
private ISubsystemTemperatureService subsystemTemperatureService;
|
||||
|
||||
@Autowired
|
||||
private IExtremeValuesService extremeValuesService;
|
||||
|
||||
@Autowired
|
||||
private BmsDevicesMapper bmsDevicesMapper;
|
||||
|
||||
// 图表数据:按最近 hours 小时返回整车电压/电流/SOC 的时间序列
|
||||
@GetMapping("/battery-data/{deviceId}/chart")
|
||||
@ApiOperation(value = "-整车电压电流SOC时间序列", notes = "按最近hours小时返回时间序列")
|
||||
public List<ChartDataPoint> getChartData(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "最近多少小时的数据", defaultValue = "24") @RequestParam(value = "hours", required = false, defaultValue = "24") int hours) {
|
||||
long millis = System.currentTimeMillis() - (long) hours * 3600_000L;
|
||||
Date startTime = new Date(millis);
|
||||
List<VehicleData> rows = vehicleDataService.selectByDeviceAndStartTime(deviceId, startTime);
|
||||
return rows.stream().map(v -> new ChartDataPoint(v.getTimestamp(), v.getTotalVoltage() == null ? 0 : v.getTotalVoltage().doubleValue(), v.getTotalCurrent() == null ? 0 : v.getTotalCurrent().doubleValue(), v.getSoc() == null ? 0 : v.getSoc())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 整车最新:返回 deviceId 最新的一条整车数据
|
||||
@GetMapping("/vehicle-data/{deviceId}/latest")
|
||||
@ApiOperation(value = "-整车最新数据", notes = "返回指定设备最新整车数据")
|
||||
public VehicleData latestVehicleData(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId) {
|
||||
return vehicleDataService.selectLatestByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
// 位置最新:返回 deviceId 最新的一条位置数据
|
||||
@GetMapping("/vehicle-location/{deviceId}/latest")
|
||||
@ApiOperation(value = "-车辆最新位置", notes = "返回指定设备最新位置数据")
|
||||
public VehicleLocation latestVehicleLocation(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId) {
|
||||
return vehicleLocationService.selectLatestByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
// 位置轨迹:按时间范围返回位置列表,start/end 为毫秒时间戳,可选 limit 限制条数
|
||||
@GetMapping("/vehicle-location/{deviceId}")
|
||||
@ApiOperation(value = "-车辆位置轨迹", notes = "按时间范围返回位置列表")
|
||||
public List<VehicleLocation> locationRange(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "开始时间戳(毫秒)", required = true) @RequestParam("start") long startMillis, @ApiParam(value = "结束时间戳(毫秒)", required = true) @RequestParam("end") long endMillis, @ApiParam(value = "限制返回条数") @RequestParam(value = "limit", required = false) Integer limit) {
|
||||
Date start = new Date(startMillis);
|
||||
Date end = new Date(endMillis);
|
||||
return vehicleLocationService.selectByDeviceAndRange(deviceId, start, end, limit);
|
||||
}
|
||||
|
||||
// 子系统最新帧(电压):返回指定子系统号最新的一帧电压数据
|
||||
@GetMapping("/subsystem-voltage/{deviceId}/{subsystemNo}/latest")
|
||||
@ApiOperation(value = "-子系统最新电压帧", notes = "返回指定子系统最新电压数据")
|
||||
public SubsystemVoltage latestVoltage(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "子系统号", required = true) @PathVariable("subsystemNo") Integer subsystemNo) {
|
||||
return subsystemVoltageService.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
|
||||
}
|
||||
|
||||
// 子系统最新帧(温度):返回指定子系统号最新的一帧温度数据
|
||||
@GetMapping("/subsystem-temperature/{deviceId}/{subsystemNo}/latest")
|
||||
@ApiOperation(value = "-子系统最新温度帧", notes = "返回指定子系统最新温度数据")
|
||||
public SubsystemTemperature latestTemperature(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "子系统号", required = true) @PathVariable("subsystemNo") Integer subsystemNo) {
|
||||
return subsystemTemperatureService.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
|
||||
}
|
||||
|
||||
@GetMapping("/extreme-values/{deviceId}/latest")
|
||||
@ApiOperation(value = "-极值最新数据", notes = "返回指定设备极值数据,支持before筛选")
|
||||
public ExtremeValues latestExtremeValues(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "筛选指定时间之前的数据(yyyy-MM-dd HH:mm:ss 或 毫秒时间戳)") @RequestParam(value = "before", required = false) String before) {
|
||||
if (before == null || before.isEmpty()) {
|
||||
return extremeValuesService.selectLatestByDeviceId(deviceId);
|
||||
}
|
||||
Date beforeTime = null;
|
||||
if (before.matches("\\d+")) {
|
||||
beforeTime = new Date(Long.parseLong(before));
|
||||
} else {
|
||||
try {
|
||||
beforeTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(before);
|
||||
} catch (ParseException e) {
|
||||
return extremeValuesService.selectLatestByDeviceId(deviceId);
|
||||
}
|
||||
}
|
||||
return extremeValuesService.selectLatestByDeviceIdBefore(deviceId, beforeTime);
|
||||
}
|
||||
|
||||
@GetMapping("/api/dashboard/home")
|
||||
@ApiOperation(value = "-首页所有分布数据", notes = "获取首页大屏的分布统计数据")
|
||||
public R<HomeDashboardDTO> home() {
|
||||
HomeDashboardDTO dto = vehicleDataService.getHomeDashboard();
|
||||
return R.ok(dto);
|
||||
}
|
||||
|
||||
/* @GetMapping("/monitor/dashboard/summary")
|
||||
@ApiOperation(value = "首页卡片统计", notes = "返回项目数、设备数、在线数、故障数")
|
||||
public R<DashboardSummaryDTO> summary() {
|
||||
long deviceCount = bmsDevicesMapper.selectCount(null);
|
||||
long onlineCount = bmsDevicesMapper.selectCount(new QueryWrapper<BmsDevices>().eq("status", "online"));
|
||||
long projectCount = 22L;
|
||||
long faultCount = 12L;
|
||||
DashboardSummaryDTO dto = new DashboardSummaryDTO();
|
||||
dto.setProjectCount(projectCount);
|
||||
dto.setDeviceCount(deviceCount);
|
||||
dto.setOnlineCount(onlineCount);
|
||||
dto.setFaultCount(faultCount);
|
||||
return R.ok(dto);
|
||||
}*/
|
||||
|
||||
/* @GetMapping("/monitor/dashboard/soc-distribution")
|
||||
@ApiOperation(value = "设备SOC分布", notes = "按每台设备最新SOC值统计")
|
||||
public R<List<NameValueDTO>> socDistribution(@ApiParam(value = "分桶边界,逗号分隔,例:0,20,40,60,80,100") @RequestParam(value = "bins", required = false, defaultValue = "0,20,40,60,80,100") String bins, @ApiParam(value = "是否包含离线设备", defaultValue = "false") @RequestParam(value = "includeOffline", required = false, defaultValue = "false") boolean includeOffline) {
|
||||
List<Integer> edges = Stream.of(bins.split(",")).map(String::trim).filter(s -> !s.isEmpty()).map(Integer::parseInt).sorted().toList();
|
||||
if (edges.size() < 2) {
|
||||
return R.ok(new ArrayList<>());
|
||||
}
|
||||
long[] counts = new long[edges.size() - 1];
|
||||
QueryWrapper<BmsDevices> qw = new QueryWrapper<>();
|
||||
if (!includeOffline) {
|
||||
//查询在线设备
|
||||
qw.eq("status", "online");
|
||||
}
|
||||
List<BmsDevices> devices = bmsDevicesMapper.selectList(qw);
|
||||
|
||||
for (BmsDevices d : devices) {
|
||||
String deviceId = d.getDeviceId();
|
||||
if (deviceId == null || deviceId.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
VehicleData latest = vehicleDataService.selectLatestByDeviceId(deviceId);
|
||||
Integer soc = latest == null ? null : latest.getSoc();
|
||||
//过滤
|
||||
if (soc == null || soc < 0 || soc > 100) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
int min = edges.get(i);
|
||||
int max = edges.get(i + 1);
|
||||
boolean isLast = (i == counts.length - 1);
|
||||
boolean inRange = isLast ? (soc >= min && soc <= max) : (soc >= min && soc < max);
|
||||
if (inRange) {
|
||||
counts[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<NameValueDTO> items = new ArrayList<>(counts.length);
|
||||
String ts = Instant.now().toString();
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
int min = edges.get(i);
|
||||
int max = edges.get(i + 1);
|
||||
NameValueDTO nv = new NameValueDTO();
|
||||
nv.setName(min + "-" + max + "%");
|
||||
nv.setValue(counts[i]);
|
||||
nv.setCreateTime(ts);
|
||||
items.add(nv);
|
||||
}
|
||||
|
||||
return R.ok(items);
|
||||
}
|
||||
*/
|
||||
@GetMapping("/monitor/dashboard/overview")
|
||||
@ApiOperation(value = "首页概览聚合", notes = "返回基础统计、SOC分布、日充放电趋势")
|
||||
public R<DashboardOverviewDTO> overview(@ApiParam(value = "SOC分桶,默认 0,20,40,60,80,100") @RequestParam(value = "bins", required = false, defaultValue = "0,20,40,60,80,100") String bins, @ApiParam(value = "趋势统计天数", defaultValue = "7") @RequestParam(value = "days", required = false, defaultValue = "7") int days, @ApiParam(value = "运行时长档位(小时)", defaultValue = "10,50,100,150,200,250,300") @RequestParam(value = "runtimeBins", required = false, defaultValue = "10,50,100,150,200,250,300") String runtimeBins) {
|
||||
DashboardOverviewDTO out = new DashboardOverviewDTO();
|
||||
// summary
|
||||
long deviceCount = bmsDevicesMapper.selectCount(null);
|
||||
long onlineCount = bmsDevicesMapper.selectCount(new QueryWrapper<BmsDevices>().eq("status", "online"));
|
||||
long projectCount = 22L;
|
||||
long faultCount = 12L;
|
||||
DashboardSummaryDTO s = new DashboardSummaryDTO();
|
||||
s.setProjectCount(projectCount);
|
||||
s.setDeviceCount(deviceCount);
|
||||
s.setOnlineCount(onlineCount);
|
||||
s.setFaultCount(faultCount);
|
||||
out.setSummary(s);
|
||||
// soc distribution
|
||||
List<Integer> edges = Stream.of(bins.split(",")).map(String::trim).filter(x -> !x.isEmpty()).map(Integer::parseInt).sorted().toList();
|
||||
long[] counts = new long[Math.max(0, edges.size() - 1)];
|
||||
if (counts.length > 0) {
|
||||
List<BmsDevices> devices = bmsDevicesMapper.selectList(new QueryWrapper<BmsDevices>().eq("status", "online"));
|
||||
for (BmsDevices d : devices) {
|
||||
String did = d.getDeviceId();
|
||||
if (did == null || did.isEmpty()) continue;
|
||||
VehicleData latest = vehicleDataService.selectLatestByDeviceId(did);
|
||||
Integer soc = latest == null ? null : latest.getSoc();
|
||||
if (soc == null || soc < 0 || soc > 100) continue;
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
int min = edges.get(i), max = edges.get(i + 1);
|
||||
boolean last = i == counts.length - 1;
|
||||
boolean in = last ? soc >= min && soc <= max : soc >= min && soc < max;
|
||||
if (in) {
|
||||
counts[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String ts = Instant.now().toString();
|
||||
List<NameValueDTO> pie = new ArrayList<>();
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
int min = edges.get(i), max = edges.get(i + 1);
|
||||
NameValueDTO nv = new NameValueDTO();
|
||||
nv.setName(min + "-" + max + "%");
|
||||
nv.setValue(counts[i]);
|
||||
nv.setCreateTime(ts);
|
||||
pie.add(nv);
|
||||
}
|
||||
out.setSocDistribution(pie);
|
||||
// trend (simple heuristic by VehicleData records)
|
||||
int safeDays = Math.max(1, Math.min(31, days));
|
||||
Date endTime = new Date();
|
||||
Date startTime = Date.from(Instant.ofEpochMilli(endTime.getTime()).minusSeconds(safeDays * 86400L));
|
||||
// 复用 selectVehicleDataList 进行时间范围查询
|
||||
VehicleData q = new VehicleData();
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("beginTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTime));
|
||||
params.put("endTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endTime));
|
||||
q.setParams(params);
|
||||
List<VehicleData> all = vehicleDataService.selectVehicleDataList(q);
|
||||
all.sort((a, b) -> {
|
||||
if (a.getDeviceId() == null)
|
||||
return -1;
|
||||
if (b.getDeviceId() == null)
|
||||
return 1;
|
||||
int c = a.getDeviceId().compareTo(b.getDeviceId());
|
||||
if (c != 0) return c;
|
||||
return a.getTimestamp().compareTo(b.getTimestamp());
|
||||
});
|
||||
Map<String, DashboardTrendItemDTO> byDate = new HashMap<>();
|
||||
SimpleDateFormat dayFmt = new SimpleDateFormat("yyyy-MM-dd");
|
||||
// 初始化天数
|
||||
LocalDate today = LocalDate.now();
|
||||
for (int i = safeDays - 1; i >= 0; i--) {
|
||||
LocalDate d = today.minusDays(i);
|
||||
DashboardTrendItemDTO item = new DashboardTrendItemDTO();
|
||||
item.setDate(d.toString());
|
||||
item.setChargeDuration(0);
|
||||
item.setDischargeDuration(0);
|
||||
byDate.put(d.toString(), item);
|
||||
}
|
||||
// 累加相邻样本间隔(秒)
|
||||
for (int i = 0; i < all.size() - 1; i++) {
|
||||
VehicleData cur = all.get(i);
|
||||
VehicleData nex = all.get(i + 1);
|
||||
if (cur.getDeviceId() == null || !cur.getDeviceId().equals(nex.getDeviceId())) continue;
|
||||
if (cur.getTimestamp() == null || nex.getTimestamp() == null) continue;
|
||||
long delta = (nex.getTimestamp().getTime() - cur.getTimestamp().getTime()) / 1000L;
|
||||
if (delta <= 0 || delta > 6 * 3600) continue; // 限制单段不超过6小时
|
||||
String key = dayFmt.format(cur.getTimestamp());
|
||||
DashboardTrendItemDTO item = byDate.get(key);
|
||||
if (item == null) continue;
|
||||
Integer st = cur.getChargingStatus();
|
||||
if (st != null && (st == 1 || st == 2)) {
|
||||
item.setChargeDuration(item.getChargeDuration() + delta);
|
||||
} else if (st != null && st == 3) {
|
||||
item.setDischargeDuration(item.getDischargeDuration() + delta);
|
||||
}
|
||||
}
|
||||
List<DashboardTrendItemDTO> trend = byDate.values().stream().sorted(java.util.Comparator.comparing(DashboardTrendItemDTO::getDate)).collect(Collectors.toList());
|
||||
out.setTrend(trend);
|
||||
// runtime summary + distribution
|
||||
long sumChargeSec = trend.stream().mapToLong(DashboardTrendItemDTO::getChargeDuration).sum();
|
||||
long sumDischargeSec = trend.stream().mapToLong(DashboardTrendItemDTO::getDischargeDuration).sum();
|
||||
RuntimeSummaryDTO rsum = new RuntimeSummaryDTO();
|
||||
rsum.setTotalChargeHours(sumChargeSec / 3600);
|
||||
rsum.setTotalDischargeHours(sumDischargeSec / 3600);
|
||||
rsum.setTotalRunHours((sumChargeSec + sumDischargeSec) / 3600);
|
||||
rsum.setTotalChargeEnergyKWh(0);
|
||||
rsum.setTotalDischargeEnergyKWh(0);
|
||||
rsum.setTotalChargeCapacityAh(0);
|
||||
rsum.setTotalDischargeCapacityAh(0);
|
||||
out.setRuntimeSummary(rsum);
|
||||
// 每设备运行小时(近 days),按 chargingStatus in (1,2,3) 累加
|
||||
Map<String, Long> runSecByDevice = new HashMap<>();
|
||||
for (int i = 0; i < all.size() - 1; i++) {
|
||||
VehicleData cur = all.get(i);
|
||||
VehicleData nex = all.get(i + 1);
|
||||
if (cur.getDeviceId() == null || !cur.getDeviceId().equals(nex.getDeviceId())) continue;
|
||||
if (cur.getTimestamp() == null || nex.getTimestamp() == null) continue;
|
||||
long delta = (nex.getTimestamp().getTime() - cur.getTimestamp().getTime()) / 1000L;
|
||||
if (delta <= 0 || delta > 6 * 3600) continue;
|
||||
Integer st = cur.getChargingStatus();
|
||||
if (st != null && (st == 1 || st == 2 || st == 3)) {
|
||||
runSecByDevice.merge(cur.getDeviceId(), delta, Long::sum);
|
||||
}
|
||||
}
|
||||
List<Integer> hb = Stream.of(runtimeBins.split(",")).map(String::trim).filter(x -> !x.isEmpty()).map(Integer::parseInt).sorted().toList();
|
||||
long[] hCounts = new long[Math.max(0, hb.size() - 1)];
|
||||
for (Map.Entry<String, Long> e : runSecByDevice.entrySet()) {
|
||||
long hours = e.getValue() / 3600;
|
||||
for (int i = 0; i < hCounts.length; i++) {
|
||||
int min = hb.get(i), max = hb.get(i + 1);
|
||||
boolean last = i == hCounts.length - 1;
|
||||
boolean in = last ? hours >= min && hours <= max : hours >= min && hours < max;
|
||||
if (in) { hCounts[i]++; break; }
|
||||
}
|
||||
}
|
||||
List<NameValueDTO> runtimeDist = new ArrayList<>();
|
||||
String now = Instant.now().toString();
|
||||
for (int i = 0; i < hCounts.length; i++) {
|
||||
int min = hb.get(i), max = hb.get(i + 1);
|
||||
NameValueDTO nv = new NameValueDTO();
|
||||
nv.setName(min + "h");
|
||||
nv.setValue(hCounts[i]);
|
||||
nv.setCreateTime(now);
|
||||
runtimeDist.add(nv);
|
||||
}
|
||||
out.setRuntimeDuration(runtimeDist);
|
||||
return R.ok(out);
|
||||
}
|
||||
|
||||
@GetMapping("/monitor/device/latest-locations")
|
||||
@ApiOperation(value = "所有设备最新位置", notes = "返回每个设备的设备对象与其最新位置")
|
||||
public R<List<DeviceLatestLocationDTO>> latestLocations(@ApiParam(value = "是否仅包含在线设备", defaultValue = "false") @RequestParam(value = "onlineOnly", required = false, defaultValue = "false") boolean onlineOnly) {
|
||||
QueryWrapper<BmsDevices> qw = new QueryWrapper<>();
|
||||
if (onlineOnly) {
|
||||
qw.eq("status", "online");
|
||||
}
|
||||
List<BmsDevices> devices = bmsDevicesMapper.selectList(qw);
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
List<DeviceLatestLocationDTO> result = new ArrayList<>(devices.size());
|
||||
for (BmsDevices d : devices) {
|
||||
String did = d.getDeviceId();
|
||||
VehicleLocation loc = did == null ? null : vehicleLocationService.selectLatestByDeviceId(did);
|
||||
TrackPointDTO p = null;
|
||||
if (loc != null) {
|
||||
p = new TrackPointDTO();
|
||||
p.setTimestamp(loc.getTimestamp() == null ? null : fmt.format(loc.getTimestamp()));
|
||||
p.setLongitude(loc.getLongitude() == null ? null : loc.getLongitude().doubleValue());
|
||||
p.setLatitude(loc.getLatitude() == null ? null : loc.getLatitude().doubleValue());
|
||||
p.setPositioningStatus(loc.getPositioningStatus());
|
||||
}
|
||||
DeviceLatestLocationDTO dto = new DeviceLatestLocationDTO();
|
||||
dto.setDevice(d);
|
||||
dto.setLocation(p);
|
||||
result.add(dto);
|
||||
}
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@GetMapping("/monitor/device/{deviceId}/track")
|
||||
@ApiOperation(value = "设备轨迹", notes = "返回指定时间范围内的轨迹")
|
||||
public R<DeviceTrackDTO> deviceTrack(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId, @ApiParam(value = "开始时间戳(毫秒)", required = true) @RequestParam("start") long startMillis, @ApiParam(value = "结束时间戳(毫秒)", required = true) @RequestParam("end") long endMillis, @ApiParam(value = "限制返回条数", defaultValue = "1000") @RequestParam(value = "limit", required = false, defaultValue = "1000") Integer limit, @ApiParam(value = "是否包含无效定位", defaultValue = "false") @RequestParam(value = "includeInvalid", required = false, defaultValue = "false") boolean includeInvalid) {
|
||||
Date start = new Date(startMillis);
|
||||
Date end = new Date(endMillis);
|
||||
//查询车辆位置信息
|
||||
List<VehicleLocation> rows = vehicleLocationService.selectByDeviceAndRange(deviceId, start, end, limit);
|
||||
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
//位置列表按 timestamp 升序排序,空时间的记录排在最后。
|
||||
List<TrackPointDTO> list = rows.stream()
|
||||
.filter(v -> includeInvalid || (v.getPositioningStatus() != null && v.getPositioningStatus() == 1))
|
||||
.sorted((a, b) -> {
|
||||
Date ta = a.getTimestamp(), tb = b.getTimestamp();
|
||||
if (ta == null && tb == null) return 0;
|
||||
if (ta == null) return 1;
|
||||
if (tb == null) return -1;
|
||||
return ta.compareTo(tb);
|
||||
})
|
||||
.map(v -> {
|
||||
TrackPointDTO p = new TrackPointDTO();
|
||||
p.setTimestamp(v.getTimestamp() == null ? null : fmt.format(v.getTimestamp()));
|
||||
p.setLongitude(v.getLongitude() == null ? null : v.getLongitude().doubleValue());
|
||||
p.setLatitude(v.getLatitude() == null ? null : v.getLatitude().doubleValue());
|
||||
p.setPositioningStatus(v.getPositioningStatus());
|
||||
return p;
|
||||
}).collect(Collectors.toList());
|
||||
DeviceTrackDTO dto = new DeviceTrackDTO();
|
||||
dto.setDeviceId(deviceId);
|
||||
// 基本设备信息
|
||||
BmsDevices dev = bmsDevicesMapper.selectOne(new QueryWrapper<BmsDevices>().eq("device_id", deviceId));
|
||||
if (dev != null) {
|
||||
dto.setDeviceName(dev.getDeviceName());
|
||||
dto.setDeviceSn(dev.getDeviceSn());
|
||||
dto.setDeviceType(dev.getDeviceType());
|
||||
dto.setStatus(dev.getStatus());
|
||||
dto.setFirmwareVersion(dev.getFirmwareVersion());
|
||||
dto.setLastOnline(dev.getLastOnline() == null ? null : fmt.format(dev.getLastOnline()));
|
||||
}
|
||||
// 运行时指标(取最新整车数据)
|
||||
VehicleData latest = vehicleDataService.selectLatestByDeviceId(deviceId);
|
||||
if (latest != null) {
|
||||
dto.setVehicleSpeed(latest.getVehicleSpeed());
|
||||
dto.setTotalMileage(latest.getTotalMileage());
|
||||
dto.setTotalVoltage(latest.getTotalVoltage());
|
||||
dto.setTotalCurrent(latest.getTotalCurrent());
|
||||
dto.setSoc(latest.getSoc());
|
||||
}
|
||||
dto.setTrackList(list);
|
||||
return R.ok(dto);
|
||||
}
|
||||
|
||||
@GetMapping("/monitor/device/{deviceId}/detail")
|
||||
@ApiOperation(value = "设备详细信息", notes = "聚合设备、整车、位置等信息")
|
||||
public R<DeviceDetailDTO> deviceDetail(@ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String deviceId) {
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
DeviceDetailDTO out = new DeviceDetailDTO();
|
||||
out.setDeviceId(deviceId);
|
||||
BmsDevices dev = bmsDevicesMapper.selectOne(new QueryWrapper<BmsDevices>().eq("device_id", deviceId));
|
||||
if (dev != null) {
|
||||
out.setDeviceName(dev.getDeviceName());
|
||||
out.setDeviceSn(dev.getDeviceSn());
|
||||
out.setDeviceType(dev.getDeviceType());
|
||||
out.setStatus(dev.getStatus());
|
||||
out.setFirmwareVersion(dev.getFirmwareVersion());
|
||||
out.setLastOnline(dev.getLastOnline() == null ? null : fmt.format(dev.getLastOnline()));
|
||||
}
|
||||
VehicleData v = vehicleDataService.selectLatestByDeviceId(deviceId);
|
||||
if (v != null) {
|
||||
out.setTotalVoltage(v.getTotalVoltage());
|
||||
out.setTotalCurrent(v.getTotalCurrent());
|
||||
out.setSoc(v.getSoc());
|
||||
out.setVehicleStatus(v.getVehicleStatus());
|
||||
out.setChargingStatus(v.getChargingStatus());
|
||||
out.setOperationMode(v.getOperationMode());
|
||||
out.setDcdcStatus(v.getDcdcStatus());
|
||||
out.setGearPosition(v.getGearPosition());
|
||||
out.setInsulationResistance(v.getInsulationResistance());
|
||||
}
|
||||
VehicleLocation loc = vehicleLocationService.selectLatestByDeviceId(deviceId);
|
||||
if (loc != null) {
|
||||
out.setLongitude(loc.getLongitude() == null ? null : loc.getLongitude().doubleValue());
|
||||
out.setLatitude(loc.getLatitude() == null ? null : loc.getLatitude().doubleValue());
|
||||
out.setLocationTime(loc.getTimestamp() == null ? null : fmt.format(loc.getTimestamp()));
|
||||
out.setPositioningStatus(loc.getPositioningStatus());
|
||||
}
|
||||
out.setLastMaintenanceTime(null);
|
||||
out.setLastUpgradeTime(null);
|
||||
return R.ok(out);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.vehicledata.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.vehicledata.domain.VehicleData;
|
||||
import com.evobms.project.vehicledata.service.IVehicleDataService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 整车数据Controller
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/VehicleData/VehicleData")
|
||||
@Api(tags = "整车数据管理")
|
||||
public class VehicleDataController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IVehicleDataService vehicleDataService;
|
||||
|
||||
/**
|
||||
* 查询整车数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询整车数据列表")
|
||||
public TableDataInfo list(VehicleData vehicleData)
|
||||
{
|
||||
startPage();
|
||||
List<VehicleData> list = vehicleDataService.selectVehicleDataList(vehicleData);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出整车数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:export')")
|
||||
@Log(title = "整车数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出整车数据列表")
|
||||
public void export(HttpServletResponse response, VehicleData vehicleData)
|
||||
{
|
||||
List<VehicleData> list = vehicleDataService.selectVehicleDataList(vehicleData);
|
||||
ExcelUtil<VehicleData> util = new ExcelUtil<VehicleData>(VehicleData.class);
|
||||
util.exportExcel(response, list, "整车数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取整车数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取整车数据详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(vehicleDataService.selectVehicleDataById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增整车数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:add')")
|
||||
@Log(title = "整车数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增整车数据")
|
||||
public AjaxResult add(@RequestBody VehicleData vehicleData)
|
||||
{
|
||||
return toAjax(vehicleDataService.insertVehicleData(vehicleData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改整车数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:edit')")
|
||||
@Log(title = "整车数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改整车数据")
|
||||
public AjaxResult edit(@RequestBody VehicleData vehicleData)
|
||||
{
|
||||
return toAjax(vehicleDataService.updateVehicleData(vehicleData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除整车数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:remove')")
|
||||
@Log(title = "整车数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除整车数据")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(vehicleDataService.deleteVehicleDataByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.evobms.project.vehicledata.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Log;
|
||||
import com.evobms.framework.aspectj.lang.enums.BusinessType;
|
||||
import com.evobms.project.vehicledata.domain.VehicleLocation;
|
||||
import com.evobms.project.vehicledata.service.IVehicleLocationService;
|
||||
import com.evobms.framework.web.controller.BaseController;
|
||||
import com.evobms.framework.web.domain.AjaxResult;
|
||||
import com.evobms.common.utils.poi.ExcelUtil;
|
||||
import com.evobms.framework.web.page.TableDataInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
/**
|
||||
* 车辆位置数据Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/location/location")
|
||||
@Api(tags = "车辆位置管理")
|
||||
public class VehicleLocationController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IVehicleLocationService vehicleLocationService;
|
||||
|
||||
/**
|
||||
* 查询车辆位置数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:list')")
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("查询车辆位置列表")
|
||||
public TableDataInfo list(VehicleLocation vehicleLocation)
|
||||
{
|
||||
startPage();
|
||||
List<VehicleLocation> list = vehicleLocationService.selectVehicleLocationList(vehicleLocation);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出车辆位置数据列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:export')")
|
||||
@Log(title = "车辆位置数据", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ApiOperation("导出车辆位置列表")
|
||||
public void export(HttpServletResponse response, VehicleLocation vehicleLocation)
|
||||
{
|
||||
List<VehicleLocation> list = vehicleLocationService.selectVehicleLocationList(vehicleLocation);
|
||||
ExcelUtil<VehicleLocation> util = new ExcelUtil<VehicleLocation>(VehicleLocation.class);
|
||||
util.exportExcel(response, list, "车辆位置数据数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取车辆位置数据详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
@ApiOperation("获取车辆位置详细信息")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(vehicleLocationService.selectVehicleLocationById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增车辆位置数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:add')")
|
||||
@Log(title = "车辆位置数据", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@ApiOperation("新增车辆位置")
|
||||
public AjaxResult add(@RequestBody VehicleLocation vehicleLocation)
|
||||
{
|
||||
return toAjax(vehicleLocationService.insertVehicleLocation(vehicleLocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改车辆位置数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:edit')")
|
||||
@Log(title = "车辆位置数据", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@ApiOperation("修改车辆位置")
|
||||
public AjaxResult edit(@RequestBody VehicleLocation vehicleLocation)
|
||||
{
|
||||
return toAjax(vehicleLocationService.updateVehicleLocation(vehicleLocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除车辆位置数据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('location:location:remove')")
|
||||
@Log(title = "车辆位置数据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
@ApiOperation("删除车辆位置")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(vehicleLocationService.deleteVehicleLocationByIds(ids));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.evobms.project.vehicledata.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@ApiModel(description = "首页仪表盘数据传输对象")
|
||||
public class HomeDashboardDTO {
|
||||
@ApiModelProperty(value = "设备总数")
|
||||
private Long deviceCount; // 设备总数
|
||||
@ApiModelProperty(value = "在线设备数")
|
||||
private Integer onlineCount; // 在线设备数
|
||||
@ApiModelProperty(value = "平均 SOC")
|
||||
private Double avgSoc; // 平均 SOC
|
||||
@ApiModelProperty(value = "当前最高温度")
|
||||
private Double maxTemp; // 当前最高温度
|
||||
@ApiModelProperty(value = "最大单体压差")
|
||||
private Double maxVoltageDiff; // 最大单体压差
|
||||
@ApiModelProperty(value = "未恢复告警数")
|
||||
private Integer alarmCount; // 未恢复告警数
|
||||
@ApiModelProperty(value = "SOC 分布")
|
||||
private Map<String, Integer> socDistribution; // SOC 分布
|
||||
@ApiModelProperty(value = "温度分布")
|
||||
private Map<String, Integer> tempDistribution; // 温度分布
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
package com.evobms.project.vehicledata.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 整车数据对象 vehicle_data
|
||||
*
|
||||
* @author 田志阳
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@ApiModel(description = "整车数据对象")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class VehicleData extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/** 设备ID */
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/** 数据时间戳 */
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/** 车辆状态 (1:启动 2:熄火 3:其他 254:异常 255:无效) */
|
||||
@ApiModelProperty(value = "车辆状态 (1:启动 2:熄火 3:其他 254:异常 255:无效)")
|
||||
@Excel(name = "车辆状态 ")
|
||||
private Integer vehicleStatus;
|
||||
|
||||
/** 充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效) */
|
||||
@ApiModelProperty(value = "充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效)")
|
||||
@Excel(name = "充电状态 ")
|
||||
private Integer chargingStatus;
|
||||
|
||||
/** 运行模式 (1:纯电 2:混动 3:燃油 254:异常 255:无效) */
|
||||
@ApiModelProperty(value = "运行模式 (1:纯电 2:混动 3:燃油 254:异常 255:无效)")
|
||||
@Excel(name = "运行模式 ")
|
||||
private Integer operationMode;
|
||||
|
||||
/** 车速(km/h) */
|
||||
@ApiModelProperty(value = "车速(km/h)")
|
||||
@Excel(name = "车速(km/h)")
|
||||
private BigDecimal vehicleSpeed;
|
||||
|
||||
/** 累计里程(km) */
|
||||
@ApiModelProperty(value = "累计里程(km)")
|
||||
@Excel(name = "累计里程(km)")
|
||||
private BigDecimal totalMileage;
|
||||
|
||||
/** 总电压(V) */
|
||||
@ApiModelProperty(value = "总电压(V)")
|
||||
@Excel(name = "总电压(V)")
|
||||
private BigDecimal totalVoltage;
|
||||
|
||||
/** 总电流(A) */
|
||||
@ApiModelProperty(value = "总电流(A)")
|
||||
@Excel(name = "总电流(A)")
|
||||
private BigDecimal totalCurrent;
|
||||
|
||||
/** SOC电量百分比(%) */
|
||||
@ApiModelProperty(value = "SOC电量百分比(%)")
|
||||
@Excel(name = "SOC电量百分比(%)")
|
||||
private Integer soc;
|
||||
|
||||
/** DC-DC状态 (1:工作 2:断开) */
|
||||
@ApiModelProperty(value = "DC-DC状态 (1:工作 2:断开)")
|
||||
@Excel(name = "DC-DC状态 (1:工作 2:断开)")
|
||||
private Integer dcdcStatus;
|
||||
|
||||
/** 档位 (0:空档 1-6:1-6档 13:倒档 14:自动D档 15:停车P档) */
|
||||
@ApiModelProperty(value = "档位 (0:空档 1-6:1-6档 13:倒档 14:自动D档 15:停车P档)")
|
||||
@Excel(name = "档位 ")
|
||||
private Integer gearPosition;
|
||||
|
||||
/** 绝缘电阻(kΩ) */
|
||||
@ApiModelProperty(value = "绝缘电阻(kΩ)")
|
||||
@Excel(name = "绝缘电阻(kΩ)")
|
||||
private Integer insulationResistance;
|
||||
|
||||
/** 预留字段 */
|
||||
@ApiModelProperty(value = "预留字段")
|
||||
@Excel(name = "预留字段")
|
||||
private String reservedData;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package com.evobms.project.vehicledata.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.evobms.framework.aspectj.lang.annotation.Excel;
|
||||
import com.evobms.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 车辆位置数据对象 vehicle_location
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-11-15
|
||||
*/
|
||||
@ApiModel(description = "车辆位置数据对象")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class VehicleLocation extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
@ApiModelProperty(value = "设备ID")
|
||||
@Excel(name = "设备ID")
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 数据时间戳
|
||||
*/
|
||||
@ApiModelProperty(value = "数据时间戳")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date timestamp;
|
||||
|
||||
/**
|
||||
* 定位状态 (0:无效 1:有效)
|
||||
*/
|
||||
@ApiModelProperty(value = "定位状态 (0:无效 1:有效)")
|
||||
@Excel(name = "定位状态 (0:无效 1:有效)")
|
||||
private Integer positioningStatus;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@ApiModelProperty(value = "经度")
|
||||
@Excel(name = "经度")
|
||||
private BigDecimal longitude;
|
||||
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
@ApiModelProperty(value = "纬度")
|
||||
@Excel(name = "纬度")
|
||||
private BigDecimal latitude;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.evobms.project.vehicledata.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ApiModel(value = "ChargeDischargeHistoryDTO", description = "充放电历史统计与明细")
|
||||
public class ChargeDischargeHistoryDTO {
|
||||
@ApiModelProperty(value = "月度充放电时长统计")
|
||||
private List<ChargeDischargeMonthDTO> months;
|
||||
@ApiModelProperty(value = "区段明细记录")
|
||||
private List<ChargeDischargeRecordDTO> records;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user