diff --git a/pom.xml b/pom.xml
index 97f03fe..9d54e53 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,12 @@
org.springframework.boot
spring-boot-starter
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+ 3.0.3
+
@@ -270,6 +276,11 @@
lombok
provided
+
+ io.springfox
+ springfox-boot-starter
+ 3.0.0
+
diff --git a/src/main/java/com/evobms/framework/config/SecurityConfig.java b/src/main/java/com/evobms/framework/config/SecurityConfig.java
index 1380bf7..d930240 100644
--- a/src/main/java/com/evobms/framework/config/SecurityConfig.java
+++ b/src/main/java/com/evobms/framework/config/SecurityConfig.java
@@ -114,7 +114,8 @@ 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()
diff --git a/src/main/java/com/evobms/framework/config/SwaggerConfig.java b/src/main/java/com/evobms/framework/config/SwaggerConfig.java
index 8abcf83..0f31dbc 100644
--- a/src/main/java/com/evobms/framework/config/SwaggerConfig.java
+++ b/src/main/java/com/evobms/framework/config/SwaggerConfig.java
@@ -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 */
diff --git a/src/main/java/com/evobms/project/Battery/domain/SubsystemTemperature.java b/src/main/java/com/evobms/project/Battery/domain/SubsystemTemperature.java
index c46c9b1..c9aa8b5 100644
--- a/src/main/java/com/evobms/project/Battery/domain/SubsystemTemperature.java
+++ b/src/main/java/com/evobms/project/Battery/domain/SubsystemTemperature.java
@@ -2,6 +2,7 @@ package com.evobms.project.Battery.domain;
import java.util.Date;
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;
@@ -9,10 +10,11 @@ import com.evobms.framework.web.domain.BaseEntity;
/**
* 可充电储能子系统温度信息对象 subsystem_temperature
- *
+ *
* @author 田志阳
* @date 2025-11-15
*/
+@Data
public class SubsystemTemperature extends BaseEntity
{
private static final long serialVersionUID = 1L;
@@ -48,115 +50,11 @@ public class SubsystemTemperature extends BaseEntity
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
- private Date createdAt;
+ private Date createTime;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
- private Date updatedAt;
+ private Date updateTime;
- public void setId(Long id)
- {
- this.id = id;
- }
-
- public Long getId()
- {
- return id;
- }
-
- public void setDeviceId(String deviceId)
- {
- this.deviceId = deviceId;
- }
-
- public String getDeviceId()
- {
- return deviceId;
- }
-
- public void setTimestamp(Date timestamp)
- {
- this.timestamp = timestamp;
- }
-
- public Date getTimestamp()
- {
- return timestamp;
- }
-
- public void setSubsystemCount(Integer subsystemCount)
- {
- this.subsystemCount = subsystemCount;
- }
-
- public Integer getSubsystemCount()
- {
- return subsystemCount;
- }
-
- public void setSubsystemNo(Integer subsystemNo)
- {
- this.subsystemNo = subsystemNo;
- }
-
- public Integer getSubsystemNo()
- {
- return subsystemNo;
- }
-
- public void setTempProbeCount(Integer tempProbeCount)
- {
- this.tempProbeCount = tempProbeCount;
- }
-
- public Integer getTempProbeCount()
- {
- return tempProbeCount;
- }
-
- public void setTemperatureValues(String temperatureValues)
- {
- this.temperatureValues = temperatureValues;
- }
-
- public String getTemperatureValues()
- {
- return temperatureValues;
- }
-
- public void setCreatedAt(Date createdAt)
- {
- this.createdAt = createdAt;
- }
-
- public Date getCreatedAt()
- {
- return createdAt;
- }
-
- public void setUpdatedAt(Date updatedAt)
- {
- this.updatedAt = updatedAt;
- }
-
- public Date getUpdatedAt()
- {
- return updatedAt;
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
- .append("id", getId())
- .append("deviceId", getDeviceId())
- .append("timestamp", getTimestamp())
- .append("subsystemCount", getSubsystemCount())
- .append("subsystemNo", getSubsystemNo())
- .append("tempProbeCount", getTempProbeCount())
- .append("temperatureValues", getTemperatureValues())
- .append("createdAt", getCreatedAt())
- .append("updatedAt", getUpdatedAt())
- .toString();
- }
}
diff --git a/src/main/java/com/evobms/project/VehicleData/controller/BatteryChartController.java b/src/main/java/com/evobms/project/VehicleData/controller/BatteryChartController.java
index 11be9b9..a050d55 100644
--- a/src/main/java/com/evobms/project/VehicleData/controller/BatteryChartController.java
+++ b/src/main/java/com/evobms/project/VehicleData/controller/BatteryChartController.java
@@ -21,6 +21,8 @@ import com.evobms.project.Battery.service.IExtremeValuesService;
import com.evobms.project.Battery.domain.ExtremeValues;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
/**
* 图标组件Controller
*
@@ -28,6 +30,7 @@ import java.text.SimpleDateFormat;
* @date 2025-11-15
*/
@RestController
+@Api(tags = "图表组件")
public class BatteryChartController {
@Autowired
@@ -47,6 +50,7 @@ public class BatteryChartController {
// 图表数据:按最近 hours 小时返回整车电压/电流/SOC 的时间序列
@GetMapping("/battery-data/{deviceId}/chart")
+ @ApiOperation(value = "整车电压电流SOC时间序列", notes = "按最近hours小时返回时间序列")
public List getChartData(@PathVariable("deviceId") String deviceId, @RequestParam(value = "hours", required = false, defaultValue = "24") int hours) {
long millis = System.currentTimeMillis() - (long) hours * 3600_000L;
Date startTime = new Date(millis);
@@ -61,18 +65,21 @@ public class BatteryChartController {
// 整车最新:返回 deviceId 最新的一条整车数据
@GetMapping("/vehicle-data/{deviceId}/latest")
+ @ApiOperation(value = "整车最新数据", notes = "返回指定设备最新整车数据")
public VehicleData latestVehicleData(@PathVariable("deviceId") String deviceId) {
return vehicleDataService.selectLatestByDeviceId(deviceId);
}
// 位置最新:返回 deviceId 最新的一条位置数据
@GetMapping("/vehicle-location/{deviceId}/latest")
+ @ApiOperation(value = "车辆最新位置", notes = "返回指定设备最新位置数据")
public VehicleLocation latestVehicleLocation(@PathVariable("deviceId") String deviceId) {
return vehicleLocationService.selectLatestByDeviceId(deviceId);
}
// 位置轨迹:按时间范围返回位置列表,start/end 为毫秒时间戳,可选 limit 限制条数
@GetMapping("/vehicle-location/{deviceId}")
+ @ApiOperation(value = "车辆位置轨迹", notes = "按时间范围返回位置列表")
public List locationRange(@PathVariable("deviceId") String deviceId,
@RequestParam("start") long startMillis,
@RequestParam("end") long endMillis,
@@ -84,25 +91,28 @@ public class BatteryChartController {
// 子系统最新帧(电压):返回指定子系统号最新的一帧电压数据
@GetMapping("/subsystem-voltage/{deviceId}/{subsystemNo}/latest")
+ @ApiOperation(value = "子系统最新电压帧", notes = "返回指定子系统最新电压数据")
public SubsystemVoltage latestVoltage(@PathVariable("deviceId") String deviceId, @PathVariable("subsystemNo") Integer subsystemNo) {
return subsystemVoltageService.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
}
// 子系统最新帧(温度):返回指定子系统号最新的一帧温度数据
@GetMapping("/subsystem-temperature/{deviceId}/{subsystemNo}/latest")
+ @ApiOperation(value = "子系统最新温度帧", notes = "返回指定子系统最新温度数据")
public SubsystemTemperature latestTemperature(@PathVariable("deviceId") String deviceId, @PathVariable("subsystemNo") Integer subsystemNo) {
return subsystemTemperatureService.selectLatestByDeviceAndSubsystem(deviceId, subsystemNo);
}
@GetMapping("/extreme-values/{deviceId}/latest")
+ @ApiOperation(value = "极值最新数据", notes = "返回指定设备极值数据,支持before筛选")
public ExtremeValues latestExtremeValues(@PathVariable("deviceId") String deviceId,
@RequestParam(value = "before", required = false) String before) {
if (before == null || before.isEmpty()) {
return extremeValuesService.selectLatestByDeviceId(deviceId);
}
- java.util.Date beforeTime = null;
+ Date beforeTime = null;
if (before.matches("\\d+")) {
- beforeTime = new java.util.Date(Long.parseLong(before));
+ beforeTime = new Date(Long.parseLong(before));
} else {
try {
beforeTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(before);
diff --git a/src/main/java/com/evobms/project/VehicleData/domain/VehicleData.java b/src/main/java/com/evobms/project/VehicleData/domain/VehicleData.java
index 9c8c7e9..24926ec 100644
--- a/src/main/java/com/evobms/project/VehicleData/domain/VehicleData.java
+++ b/src/main/java/com/evobms/project/VehicleData/domain/VehicleData.java
@@ -26,8 +26,8 @@ public class VehicleData extends BaseEntity
private String deviceId;
/** 数据时间戳 */
- @JsonFormat(pattern = "yyyy-MM-dd")
- @Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
+ @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:无效) */
diff --git a/src/main/java/com/evobms/project/VehicleData/domain/VehicleLocation.java b/src/main/java/com/evobms/project/VehicleData/domain/VehicleLocation.java
index 15b9433..71160f7 100644
--- a/src/main/java/com/evobms/project/VehicleData/domain/VehicleLocation.java
+++ b/src/main/java/com/evobms/project/VehicleData/domain/VehicleLocation.java
@@ -2,6 +2,7 @@ package com.evobms.project.VehicleData.domain;
import java.math.BigDecimal;
import java.util.Date;
+
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -14,105 +15,103 @@ import com.evobms.framework.web.domain.BaseEntity;
* @author ruoyi
* @date 2025-11-15
*/
-public class VehicleLocation extends BaseEntity
-{
+public class VehicleLocation extends BaseEntity {
private static final long serialVersionUID = 1L;
- /** 主键ID */
+ /**
+ * 主键ID
+ */
private Long id;
- /** 设备ID */
+ /**
+ * 设备ID
+ */
@Excel(name = "设备ID")
private String deviceId;
- /** 数据时间戳 */
+ /**
+ * 数据时间戳
+ */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd")
private Date timestamp;
- /** 定位状态 (0:无效 1:有效) */
+ /**
+ * 定位状态 (0:无效 1:有效)
+ */
@Excel(name = "定位状态 (0:无效 1:有效)")
private Integer positioningStatus;
- /** 经度 */
+ /**
+ * 经度
+ */
@Excel(name = "经度")
private BigDecimal longitude;
- /** 纬度 */
+ /**
+ * 纬度
+ */
@Excel(name = "纬度")
private BigDecimal latitude;
- 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 setPositioningStatus(Integer positioningStatus)
- {
+ public void setPositioningStatus(Integer positioningStatus) {
this.positioningStatus = positioningStatus;
}
- public Integer getPositioningStatus()
- {
+ public Integer getPositioningStatus() {
return positioningStatus;
}
- public void setLongitude(BigDecimal longitude)
- {
+ public void setLongitude(BigDecimal longitude) {
this.longitude = longitude;
}
- public BigDecimal getLongitude()
- {
+ public BigDecimal getLongitude() {
return longitude;
}
- public void setLatitude(BigDecimal latitude)
- {
+ public void setLatitude(BigDecimal latitude) {
this.latitude = latitude;
}
- public BigDecimal getLatitude()
- {
+ public BigDecimal getLatitude() {
return latitude;
}
-
@Override
public String toString() {
- return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
- .append("id", getId())
- .append("deviceId", getDeviceId())
- .append("timestamp", getTimestamp())
- .append("positioningStatus", getPositioningStatus())
- .append("longitude", getLongitude())
- .append("latitude", getLatitude())
- .toString();
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", getId())
+ .append("deviceId", getDeviceId())
+ .append("timestamp", getTimestamp())
+ .append("positioningStatus", getPositioningStatus())
+ .append("longitude", getLongitude())
+ .append("latitude", getLatitude())
+ .toString();
}
}
diff --git a/src/main/java/com/evobms/project/bms/controller/GBT32960FullDecoder.java b/src/main/java/com/evobms/project/bms/controller/GBT32960FullDecoder.java
index ed73cde..7786a48 100644
--- a/src/main/java/com/evobms/project/bms/controller/GBT32960FullDecoder.java
+++ b/src/main/java/com/evobms/project/bms/controller/GBT32960FullDecoder.java
@@ -5,17 +5,28 @@ 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解密
@@ -173,6 +184,7 @@ public class GBT32960FullDecoder {
//使用的AES密钥
byte[] aesKey = generateKeyFromSn(deviceSn);
+ System.out.println("密钥------------------------>"+aesKey);
byte[] decryptedData = decryptData(encryptedData, aesKey);
bytesData = bytesToHex(decryptedData);
log.info("解密成功!");
diff --git a/src/main/java/com/evobms/project/bms/service/MqttService.java b/src/main/java/com/evobms/project/bms/service/MqttService.java
index d37bf4c..992f22a 100644
--- a/src/main/java/com/evobms/project/bms/service/MqttService.java
+++ b/src/main/java/com/evobms/project/bms/service/MqttService.java
@@ -30,6 +30,7 @@ import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
+import java.util.stream.Collectors;
import com.evobms.project.system.service.IBmsDevicesService;
import com.evobms.project.system.domain.BmsDevices;
@@ -73,7 +74,6 @@ public class MqttService {
private IChargeDischargeSummaryService chargeDischargeSummaryService;
-
@Value("${mqtt.publishTopic}")
private String publishTopic;
@@ -86,7 +86,7 @@ public class MqttService {
/**
* 发送MQTT消息
*
- * @param topic 主题
+ * @param topic 主题
* @param payload 消息内容
*/
public void sendMessage(String topic, String payload) {
@@ -100,7 +100,7 @@ public class MqttService {
/**
* 发送MQTT字节消息
*
- * @param topic 主题
+ * @param topic 主题
* @param payload 原始字节
*/
public void sendMessageBytes(String topic, byte[] payload) {
@@ -168,7 +168,7 @@ public class MqttService {
* 发送设备控制命令
*
* @param deviceCode 设备编号
- * @param command 控制命令
+ * @param command 控制命令
*/
public void sendDeviceCommand(String deviceCode, String command) {
Map commandData = new HashMap<>();
@@ -185,7 +185,7 @@ public class MqttService {
/**
* 处理接收到的设备数据
*
- * @param topic 主题
+ * @param topic 主题
* @param message 消息内容
*/
public void handleDeviceData(String topic, byte[] message) {
@@ -220,10 +220,11 @@ public class MqttService {
log.error("处理设备数据时发生错误: {}", e.getMessage(), e);
}
}
+
/**
* 逐字段解析数据字符串 - 直接解析十六进制数据
*
- * @param data 十六进制数据字符串
+ * @param data 十六进制数据字符串
* @param deviceSn 设备SN码
*/
private void parseDataFields(String data, String deviceSn) {
@@ -252,31 +253,35 @@ public class MqttService {
log.error("设备 {} 解析数据字段时发生错误: {}", deviceSn, e.getMessage(), e);
}
}
+
/**
* 按照协议定义的索引位置解析各个数据段
*/
private void parseByProtocolIndex(byte[] message, String deviceSn) {
try {
// 1. 时间信息 - 索引24-29 (6字节)
- parseTimeAtIndex(message, 0, deviceSn);
+ Date frameTime = parseTimeAtIndex(message, 0, deviceSn);
+ if (frameTime == null) {
+ frameTime = new Date();
+ }
// 2. 整车数据 - 索引30-49 (20字节)
- parseVehicleDataAtIndex(message, 6, deviceSn);
+ parseVehicleDataAtIndex(message, 6, deviceSn, frameTime);
// 3. 位置信息 - 索引51-60 (10字节)
- parseLocationDataAtIndex(message, 27, deviceSn);
+ parseLocationDataAtIndex(message, 27, deviceSn, frameTime);
// 4. 极值数据 - 索引61-75 (14字节)
- parseExtremeDataAtIndex(message, 37, deviceSn);
+ parseExtremeDataAtIndex(message, 37, deviceSn, frameTime);
// 5. 单体电压数据 - 索引76-447 (372字节)
- parseCellVoltageAtIndex(message, 52, deviceSn);
+ parseCellVoltageAtIndex(message, 52, deviceSn, frameTime);
// 6. 单体温度数据 - 索引448-542 (95字节)
- parseCellTemperatureAtIndex(message, 424, deviceSn);
+ parseCellTemperatureAtIndex(message, 424, deviceSn, frameTime);
// 7. 累计充放电量 - 索引543-553 (11字节)
- parseChargeDischargeAtIndex(message, 519, deviceSn);
+ parseChargeDischargeAtIndex(message, 519, deviceSn, frameTime);
log.info("设备 {} 所有数据段解析完成", deviceSn);
@@ -284,15 +289,16 @@ public class MqttService {
log.error("设备 {} 按索引解析时发生错误: {}", deviceSn, e.getMessage(), e);
}
}
+
/**
* 解析时间信息 - 索引24-29 (6字节)
* 格式: 年(偏移2000) + 月 + 日 + 时 + 分 + 秒
*/
- private void parseTimeAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private Date parseTimeAtIndex(byte[] message, int startIndex, String deviceSn) {
try {
if (message.length < startIndex + 6) {
log.warn("设备 {}: 时间数据索引越界", deviceSn);
- return;
+ return null;
}
int year = (message[startIndex] & 0xFF) + 2000; // 索引24: 年
@@ -307,19 +313,26 @@ public class MqttService {
year, month, day, hour, minute, second);
log.info("设备 {} - 时间: {}", deviceSn, time);
saveTimeData(deviceSn, time);
+ Calendar cal = Calendar.getInstance(TimeZone.getDefault());
+ cal.set(year, month - 1, day, hour, minute, second);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTime();
} else {
log.info("设备 {} - 时间: 无效数据({}-{}-{} {}:{}:{})",
deviceSn, year, month, day, hour, minute, second);
+ return null;
}
} catch (Exception e) {
log.error("设备 {} 解析时间数据时发生错误: {}", deviceSn, e.getMessage());
+ return null;
}
}
+
/**
* 解析整车数据 - 索引30-49 (20字节)
*/
- private void parseVehicleDataAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseVehicleDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 20) {
log.warn("设备 {}: 整车数据索引越界", deviceSn);
@@ -359,7 +372,7 @@ public class MqttService {
log.info("设备 {} - 正极绝缘电阻: {} Ω", deviceSn, insulationResistance);
// 保存整车数据
- saveVehicleData(deviceSn, voltageValue, currentValue, soc, chargeStatus,insulationResistance);
+ saveVehicleData(deviceSn, voltageValue, currentValue, soc, chargeStatus, insulationResistance, frameTime);
} catch (Exception e) {
log.error("设备 {} 解析整车数据时发生错误: {}", deviceSn, e.getMessage());
@@ -370,7 +383,7 @@ public class MqttService {
/**
* 解析位置信息 - 索引51-60 (10字节)
*/
- private void parseLocationDataAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseLocationDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 10) {
log.warn("设备 {}: 位置数据索引越界", deviceSn);
@@ -388,7 +401,8 @@ public class MqttService {
// 索引52: 位置状态
byte locationStatus = message[startIndex + 1];
-
+ // 转成十六进制字符串,例如 "00", "01"
+ String locationStatusHex = String.format("%02X", locationStatus);
// 索引53-56: 经度 (0.000001°)
long longitude = ((message[startIndex + 2] & 0xFFL) << 24) |
((message[startIndex + 3] & 0xFFL) << 16) |
@@ -404,8 +418,9 @@ public class MqttService {
if (longitude != 0 || latitude != 0) {
double lon = longitude / 1000000.0;
double lat = latitude / 1000000.0;
- log.info("设备 {} - 位置: 经度={}°, 纬度={}° (状态:0x{})", deviceSn, lon, lat, String.format("%02X", locationStatus));
- processLocationData(deviceSn, lon, lat,String.format("%02X", locationStatus));
+
+ log.info("设备 {} - 位置: 经度={}°, 纬度={}° (状态:0x{})", deviceSn, lon, lat, locationStatusHex);
+ processLocationData(deviceSn, lon, lat, locationStatusHex, frameTime);
} else {
log.info("设备 {} - 位置: 无效数据", deviceSn);
}
@@ -418,7 +433,7 @@ public class MqttService {
/**
* 解析极值数据 - 索引61-75 (14字节)
*/
- private void parseExtremeDataAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseExtremeDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 14) {
log.warn("设备 {}: 极值数据索引越界", deviceSn);
@@ -468,7 +483,7 @@ public class MqttService {
int minTempValue = minTemperature - 40;
log.info("设备 {} - 最低温度: 子系统{}-探针{}, {}°C", deviceSn, minTempSystem, minTempProbe, minTempValue);
// 保存极值数据
- saveExtremeData(deviceSn, (maxVoltageSystem & 0xFF), (maxVoltageProbe & 0xFF), maxVoltageValue, (minVoltageSystem & 0xFF), (minVoltageProbe & 0xFF), minVoltageValue, (maxTempSystem & 0xFF), (maxTempProbe & 0xFF), maxTempValue, (minTempSystem & 0xFF), (minTempProbe & 0xFF), minTempValue);
+ saveExtremeData(deviceSn, (maxVoltageSystem & 0xFF), (maxVoltageProbe & 0xFF), maxVoltageValue, (minVoltageSystem & 0xFF), (minVoltageProbe & 0xFF), minVoltageValue, (maxTempSystem & 0xFF), (maxTempProbe & 0xFF), maxTempValue, (minTempSystem & 0xFF), (minTempProbe & 0xFF), minTempValue, frameTime);
} catch (Exception e) {
log.error("设备 {} 解析极值数据时发生错误: {}", deviceSn, e.getMessage());
@@ -479,7 +494,7 @@ public class MqttService {
/**
* 解析单体电压数据 - 索引76-447 (372字节)
*/
- private void parseCellVoltageAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseCellVoltageAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 372) {
log.warn("设备 {}: 单体电压数据索引越界", deviceSn);
@@ -535,7 +550,7 @@ public class MqttService {
}
SubsystemVoltage sv = new SubsystemVoltage();
sv.setDeviceId(deviceSn);
- sv.setTimestamp(new Date());
+ sv.setTimestamp(frameTime);
sv.setSubsystemCount((int) subsystemCount);
sv.setSubsystemNo((int) subsystemNum);
sv.setSubsystemVoltage(BigDecimal.valueOf(storageVoltageValue));
@@ -546,7 +561,7 @@ public class MqttService {
sv.setCreateTime(new Date());
sv.setCreateBy(deviceSn);
String voltagesStr = voltages.stream().map(Object::toString).collect(java.util.stream.Collectors.joining(","));
- sv.setBatteryVoltages(voltagesStr);
+ sv.setBatteryVoltages(JSON.toJSONString(voltagesStr));
subsystemVoltageService.insertSubsystemVoltage(sv);
parseCellVoltagesDetail(message, voltageDataStart, deviceSn, startCellIndex, frameCellCount);
} else {
@@ -562,7 +577,7 @@ public class MqttService {
/**
* 解析单体温度数据 - 索引448-542 (95字节)
*/
- private void parseCellTemperatureAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseCellTemperatureAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 89) {
log.warn("设备 {}: 单体温度数据索引越界", deviceSn);
@@ -603,14 +618,14 @@ public class MqttService {
}
SubsystemTemperature st = new SubsystemTemperature();
st.setDeviceId(deviceSn);
- st.setTimestamp(new Date());
+ st.setTimestamp(frameTime);
st.setSubsystemCount((int) subsystemCount);
st.setSubsystemNo((int) subsystemNum);
st.setTempProbeCount(totalTempCount);
st.setCreateTime(new Date());
st.setCreateBy(deviceSn);
- String tempsStr = temperatures.stream().map(Object::toString).collect(java.util.stream.Collectors.joining(","));
- st.setTemperatureValues(tempsStr);
+ String tempsStr = temperatures.stream().map(Object::toString).collect(Collectors.joining(","));
+ st.setTemperatureValues(JSON.toJSONString(tempsStr));
subsystemTemperatureService.insertSubsystemTemperature(st);
parseCellTemperaturesDetail(message, tempDataStart, deviceSn, totalTempCount);
} else {
@@ -625,7 +640,7 @@ public class MqttService {
/**
* 解析累计充放电量 - 索引543-553 (11字节)
*/
- private void parseChargeDischargeAtIndex(byte[] message, int startIndex, String deviceSn) {
+ private void parseChargeDischargeAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
if (message.length < startIndex + 11) {
log.warn("设备 {}: 充放电数据索引越界", deviceSn);
@@ -659,7 +674,7 @@ public class MqttService {
log.info("设备 {} - 累计充放电量: 放电{}kWh, 充电{}kWh", deviceSn, dischargeKwh, chargeKwh);
- saveChargeDischargeSummary(deviceSn, dischargeKwh, chargeKwh);
+ saveChargeDischargeSummary(deviceSn, dischargeKwh, chargeKwh, frameTime);
} catch (Exception e) {
log.error("设备 {} 解析充放电数据时发生错误: {}", deviceSn, e.getMessage());
@@ -667,8 +682,6 @@ public class MqttService {
}
-
-
/**
* 解析详细的单体温度数据
*/
@@ -734,6 +747,7 @@ public class MqttService {
log.info("设备 {} - 电压统计: 最小值{}V, 最大值{}V, 平均值{}V", deviceSn, minVoltage, maxVoltage, avgVoltage);
}
+
/**
* 检查单体电压数据有效性
*/
@@ -746,18 +760,25 @@ public class MqttService {
}
return false;
}
+
/**
* 充电状态描述
*/
private int getChargeStatusDescription(byte status) {
/** 充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效) */
switch (status & 0xFF) {
- case 0x01: return 1;
- case 0x02: return 2;
- case 0x03: return 3;
- case 0x04: return 4;
- case 0xFE: return 254;
- case 0xFF: return 255;
+ case 0x01:
+ return 1;
+ case 0x02:
+ return 2;
+ case 0x03:
+ return 3;
+ case 0x04:
+ return 4;
+ case 0xFE:
+ return 254;
+ case 0xFF:
+ return 255;
}
return 0;
@@ -774,6 +795,7 @@ public class MqttService {
minute >= 0 && minute <= 59 &&
second >= 0 && second <= 59;
}
+
/**
* 十六进制字符串转字节数组
*/
@@ -793,8 +815,7 @@ public class MqttService {
*/
private void saveCellVoltageData(String deviceSn, byte subsystemNum, int startIndex, int count, List voltages, double min, double max, double avg) {
// TODO: 实现单体电压数据保存逻辑
- log.debug("保存设备 {} 子系统 {} 电压数据: 起始{}, 数量{}, 范围{}-{}V",
- deviceSn, subsystemNum, startIndex, count, min, max);
+ log.debug("保存设备 {} 子系统 {} 电压数据: 起始{}, 数量{}, 范围{}-{}V", deviceSn, subsystemNum, startIndex, count, min, max);
}
/**
@@ -802,8 +823,7 @@ public class MqttService {
*/
private void saveCellTemperatureData(String deviceSn, byte subsystemNum, int count, List temperatures, int min, int max, double avg) {
// TODO: 实现单体温度数据保存逻辑
- log.debug("保存设备 {} 子系统 {} 温度数据: 数量{}, 范围{}-{}°C",
- deviceSn, subsystemNum, count, min, max);
+ log.debug("保存设备 {} 子系统 {} 温度数据: 数量{}, 范围{}-{}°C", deviceSn, subsystemNum, count, min, max);
}
/**
@@ -813,13 +833,15 @@ public class MqttService {
// TODO: 实现时间数据保存逻辑
log.debug("保存设备 {} 时间数据: {}", deviceSn, time);
}
+
/**
* 保存整车数据
*/
- private void saveVehicleData(String deviceSn, double voltage, double current, int soc, byte chargeStatus,int insulationResistance) {
+ private void saveVehicleData(String deviceSn, double voltage, double current, int soc, byte chargeStatus,int insulationResistance, Date frameTime) {
// 保存整车数据到数据库
VehicleData ve = new VehicleData();
ve.setDeviceId(deviceSn);
+ ve.setTimestamp(frameTime);
ve.setTotalVoltage(BigDecimal.valueOf(voltage));
ve.setTotalCurrent(BigDecimal.valueOf(current));
ve.setSoc(soc);
@@ -831,11 +853,13 @@ public class MqttService {
}
- private void processLocationData(String deviceSn, double longitude, double latitude,String locationStatus) {
+ private void processLocationData(String deviceSn, double longitude, double latitude,String locationStatus, Date frameTime) {
VehicleLocation ve = new VehicleLocation();
ve.setDeviceId(deviceSn);
- ve.setTimestamp(new Date());
- ve.setPositioningStatus(Integer.valueOf(String.format("%02X", locationStatus)));
+ ve.setTimestamp(frameTime);
+ // 十六进制字符串(如 "00")转成整数(如 0)
+ int status = Integer.parseInt(locationStatus, 16);
+ ve.setPositioningStatus(status);
ve.setLongitude(BigDecimal.valueOf(longitude));
ve.setLatitude(BigDecimal.valueOf(latitude));
ve.setCreateTime(new Date());
@@ -844,10 +868,10 @@ public class MqttService {
}
private void saveExtremeData(String deviceSn, int maxVoltageSubsystemNo, int maxVoltageBatteryNo, double maxVoltageValue, int minVoltageSubsystemNo, int minVoltageBatteryNo, double minVoltageValue, int maxTempSubsystemNo,
- int maxTempProbeNo, int maxTempValue, int minTempSubsystemNo, int minTempProbeNo, int minTempValue) {
+ int maxTempProbeNo, int maxTempValue, int minTempSubsystemNo, int minTempProbeNo, int minTempValue, Date frameTime) {
ExtremeValues ex = new ExtremeValues();
ex.setDeviceId(deviceSn);
- ex.setTimestamp(new Date());
+ ex.setTimestamp(frameTime);
ex.setMaxVoltageSubsystemNo(maxVoltageSubsystemNo);
ex.setMaxVoltageBatteryNo(maxVoltageBatteryNo);
ex.setMaxVoltageValue(BigDecimal.valueOf(maxVoltageValue));
@@ -863,16 +887,17 @@ public class MqttService {
extremeValuesService.insertExtremeValues(ex);
}
- private void saveChargeDischargeSummary(String deviceSn, double dischargeKwh, double chargeKwh) {
+ private void saveChargeDischargeSummary(String deviceSn, double dischargeKwh, double chargeKwh, Date frameTime) {
ChargeDischargeSummary s = new ChargeDischargeSummary();
s.setDeviceId(deviceSn);
- s.setTimestamp(new Date());
+ s.setTimestamp(frameTime);
s.setDischargeKwh(BigDecimal.valueOf(dischargeKwh));
s.setChargeKwh(BigDecimal.valueOf(chargeKwh));
s.setCreateTime(new Date());
s.setCreateBy(deviceSn);
chargeDischargeSummaryService.insertChargeDischargeSummary(s);
}
+
/**
* 处理单体温度数据
*/
@@ -888,70 +913,56 @@ public class MqttService {
}
-
-
-
-
-
-
-
-
-
-
-
-
/**
* 更新设备数据
*
* @param device 设备对象
- * @param data 数据
+ * @param data 数据
*/
- private void updateDeviceData(BmsDevice device, Map data) {
- if (data.containsKey("voltage")) {
- device.setCurrentVoltage(Double.valueOf(data.get("voltage").toString()));
- }
- if (data.containsKey("current")) {
- device.setCurrentCurrent(Double.valueOf(data.get("current").toString()));
- }
- if (data.containsKey("capacity")) {
- device.setRemainingCapacity(Double.valueOf(data.get("capacity").toString()));
- }
- if (data.containsKey("temperature")) {
- device.setTemperature(Double.valueOf(data.get("temperature").toString()));
- }
+ private void updateDeviceData(BmsDevice device, Map data) {
+ if (data.containsKey("voltage")) {
+ device.setCurrentVoltage(Double.valueOf(data.get("voltage").toString()));
+ }
+ if (data.containsKey("current")) {
+ device.setCurrentCurrent(Double.valueOf(data.get("current").toString()));
+ }
+ if (data.containsKey("capacity")) {
+ device.setRemainingCapacity(Double.valueOf(data.get("capacity").toString()));
+ }
+ if (data.containsKey("temperature")) {
+ device.setTemperature(Double.valueOf(data.get("temperature").toString()));
+ }
- device.setLastCommTime(new Date());
- }
+ device.setLastCommTime(new Date());
+ }
- /**
+ /**
* 发送设备状态查询命令
*
* @param deviceCode 设备编号
*/
- public void queryDeviceStatus(String deviceCode) {
- sendDeviceCommand(deviceCode, "STATUS_QUERY");
- }
+ public void queryDeviceStatus(String deviceCode) {
+ sendDeviceCommand(deviceCode, "STATUS_QUERY");
+ }
-
-
- /**
+ /**
* 根据设备唯一编号(deviceCode)查询系统设备表的SN码
*/
- private String lookupDeviceSnByCode(String deviceCode) {
- try {
- BmsDevices query = new BmsDevices();
- query.setDeviceId(deviceCode);
- List list = bmsDevicesService.selectBmsDevicesList(query);
- if (list != null && !list.isEmpty()) {
- String sn = list.get(0).getDeviceSn();
- if (sn != null && !sn.isEmpty()) {
- return sn;
- }
- }
- } catch (Exception e) {
- log.warn("查询设备SN失败: {}", e.getMessage());
- }
- return null;
- }
+ private String lookupDeviceSnByCode(String deviceCode) {
+ try {
+ BmsDevices query = new BmsDevices();
+ query.setDeviceId(deviceCode);
+ List list = bmsDevicesService.selectBmsDevicesList(query);
+ if (list != null && !list.isEmpty()) {
+ String sn = list.get(0).getDeviceSn();
+ if (sn != null && !sn.isEmpty()) {
+ return sn;
+ }
+ }
+ } catch (Exception e) {
+ log.warn("查询设备SN失败: {}", e.getMessage());
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/evobms/project/iot/controller/IotAuthController.java b/src/main/java/com/evobms/project/iot/controller/IotAuthController.java
index 0a8ee29..6bc286b 100644
--- a/src/main/java/com/evobms/project/iot/controller/IotAuthController.java
+++ b/src/main/java/com/evobms/project/iot/controller/IotAuthController.java
@@ -9,6 +9,10 @@ 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 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
@@ -25,6 +29,7 @@ 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.InputStream;
@@ -46,6 +51,7 @@ import java.util.Map;
* 路径:POST /iot/auth/token
*/
@RestController
+@Tag(name = "设备鉴权", description = "设备鉴权令牌接口")
@RequestMapping("/iot")
public class IotAuthController {
private static final Logger log = LoggerFactory.getLogger(IotAuthController.class);
@@ -89,6 +95,7 @@ public class IotAuthController {
* 返回:{ code, success, token }
*/
@PostMapping("/auth/token")
+ @Operation(summary = "设备请求令牌", description = "通过SN码,设备号,版本信息生成TOKEN")
public Map requestToken(@RequestBody Map body) {
String sn = safeTrim(body.get("sn"));
String model = safeTrim(body.get("device"));
@@ -133,7 +140,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 +169,8 @@ public class IotAuthController {
* 请求参数:version(可选)
* 返回:{ code, success, data(Base64) }
*/
+ @Operation(summary = " MQTT 登录", description = "获取设备端 MQTT 登录信息")
+ @ApiOperation(value = "MQTT 登录", notes = "获取设备端 MQTT 登录信息")
@GetMapping("/auth/mqtt")
public Map getMqttCredentials(@RequestParam(value = "version", required = false) String version,
HttpServletRequest request) {
@@ -186,10 +195,11 @@ public class IotAuthController {
if (uri.getPort() != -1) {
port = uri.getPort();
}
- } catch (Exception ignore) {}
+ } catch (Exception ignore) {
+ }
String use = fixLengthRight(mqttUsername, 8);
- String pass = fixLengthRight(mqttPassword,16);
+ String pass = fixLengthRight(mqttPassword, 16);
Map data = new HashMap<>();
data.put("clientid", sn);
@@ -199,10 +209,17 @@ 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 {
+ 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 +238,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 deviceLogin(@RequestBody(required = false) String body, @RequestParam(value = "version", required = false) String versionParam, HttpServletRequest request) {
Map resp = new HashMap<>();
@@ -285,7 +303,8 @@ public class IotAuthController {
// 目标升级版本:直接取设备记录中的固件版本(跳过 OTA 任务查询)
String targetVersion = null;
- try { targetVersion = device.getFirmwareVersion();
+ try {
+ targetVersion = device.getFirmwareVersion();
} catch (Exception ignore) {
}
@@ -362,13 +381,14 @@ 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 固件分片下载接口")
public Object downloadOtaChunk(@PathVariable("num") String num,
@RequestParam(value = "version", required = false) String version,
HttpServletRequest request) {
@@ -453,7 +473,8 @@ 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)之后开始切片;并在分片前置校验头(摘要基于该分片数据)
int firstDataLen = Math.min(otaChunkSize, firmwareBytes);
@@ -486,8 +507,9 @@ 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);
@@ -497,14 +519,14 @@ public class IotAuthController {
.contentLength(chunk.length)
.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 分片总数
@@ -554,7 +576,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);
@@ -580,7 +603,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 +631,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');
diff --git a/src/main/java/com/evobms/project/system/domain/BmsDevices.java b/src/main/java/com/evobms/project/system/domain/BmsDevices.java
index 2804035..c4254fe 100644
--- a/src/main/java/com/evobms/project/system/domain/BmsDevices.java
+++ b/src/main/java/com/evobms/project/system/domain/BmsDevices.java
@@ -47,7 +47,7 @@ public class BmsDevices extends BaseEntity
@Excel(name = "设备IP地址")
private String ipAddress;
- /** 固件版本号 */
+ /** 服务器固件版本号 */
@Excel(name = "固件版本号")
private String firmwareVersion;
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 9bcccf9..f99a863 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -6,7 +6,7 @@ ruoyi:
version: 3.9.0
# 版权年份
copyrightYear: 2025
- # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
+ # 文件路径
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
@@ -15,8 +15,8 @@ ruoyi:
# 开发环境配置
server:
- # 服务器的HTTP端口,默认为8080
- port: 8080
+ # 服务器HTTP端口,支持环境变量覆盖:SERVER_PORT,默认8080
+ port: ${SERVER_PORT:8081}
servlet:
# 应用的访问路径
context-path: /
@@ -208,11 +208,11 @@ mqtt:
# 默认QoS等级
defaultQos: 1
# 订阅主题
- subscribeTopic: /bbox/EVO0002/#
+ subscribeTopic: "/bbox/+/#"
# 发布主题
publishTopic: evobms/command
# 调试:开启HTTP请求打印
-debug:
- httpdump:
+ debug:
+ httpdump:
enabled: true
diff --git a/src/main/resources/mybatis/temperature/SubsystemTemperatureMapper.xml b/src/main/resources/mybatis/temperature/SubsystemTemperatureMapper.xml
index 1bf2066..81d225a 100644
--- a/src/main/resources/mybatis/temperature/SubsystemTemperatureMapper.xml
+++ b/src/main/resources/mybatis/temperature/SubsystemTemperatureMapper.xml
@@ -13,13 +13,13 @@
-
+
- select id, device_id, timestamp, subsystem_count, subsystem_no, temp_probe_count, temperature_values, create_time, updated_time, create_by, update_by from subsystem_temperature
+ select id, device_id, timestamp, subsystem_count, subsystem_no, temp_probe_count, temperature_values, create_time, update_time, create_by, update_by from subsystem_temperature
@@ -50,7 +50,7 @@
temp_probe_count,
temperature_values,
create_time,
- updated_time,
+ update_time,
create_by,
update_by,
@@ -62,7 +62,7 @@
#{tempProbeCount},
#{temperatureValues},
#{createTime},
- #{updatedTime},
+ #{updateTime},
#{createBy},
#{updateBy},
@@ -78,7 +78,7 @@
temp_probe_count = #{tempProbeCount},
temperature_values = #{temperatureValues},
create_time = #{createTime},
- updated_time = #{updatedTime},
+ update_time = #{updateTime},
create_by = #{createBy},
update_by = #{updateBy},