车辆位置,极值,位置等重要数据数据

This commit is contained in:
tzy 2026-02-23 08:44:44 +08:00
parent 3290319ba7
commit 6b6be61716
49 changed files with 1180 additions and 621 deletions

3
.vite/deps/package.json Normal file
View File

@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@ -150,7 +150,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);
}

View File

@ -23,7 +23,7 @@ import springfox.documentation.spring.web.plugins.Docket;
/**
* Swagger2的接口配置
*
*
* @author ruoyi
*/
@Configuration
@ -108,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))
// 版本

View File

@ -8,6 +8,7 @@ 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基类
@ -21,28 +22,35 @@ 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;

View File

@ -20,15 +20,18 @@ 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));

View File

@ -20,6 +20,8 @@ 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
@ -28,7 +30,8 @@ import com.evobms.framework.web.page.TableDataInfo;
* @date 2025-11-15
*/
@RestController
@RequestMapping("/temperature/temperature")
@RequestMapping("/Battery/SubsystemTemperature")
@Api(tags = "可充电储能子系统温度信息")
public class SubsystemTemperatureController extends BaseController
{
@Autowired
@ -37,8 +40,9 @@ public class SubsystemTemperatureController extends BaseController
/**
* 查询可充电储能子系统温度信息列表
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:list')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:list')")
@GetMapping("/list")
@ApiOperation("查询子系统温度信息列表")
public TableDataInfo list(SubsystemTemperature subsystemTemperature)
{
startPage();
@ -49,9 +53,10 @@ public class SubsystemTemperatureController extends BaseController
/**
* 导出可充电储能子系统温度信息列表
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:export')")
@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);
@ -62,8 +67,9 @@ public class SubsystemTemperatureController extends BaseController
/**
* 获取可充电储能子系统温度信息详细信息
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:query')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:query')")
@GetMapping(value = "/{id}")
@ApiOperation("获取子系统温度信息详细信息")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(subsystemTemperatureService.selectSubsystemTemperatureById(id));
@ -72,9 +78,10 @@ public class SubsystemTemperatureController extends BaseController
/**
* 新增可充电储能子系统温度信息
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:add')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:add')")
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增子系统温度信息")
public AjaxResult add(@RequestBody SubsystemTemperature subsystemTemperature)
{
return toAjax(subsystemTemperatureService.insertSubsystemTemperature(subsystemTemperature));
@ -83,9 +90,10 @@ public class SubsystemTemperatureController extends BaseController
/**
* 修改可充电储能子系统温度信息
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:edit')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:edit')")
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改子系统温度信息")
public AjaxResult edit(@RequestBody SubsystemTemperature subsystemTemperature)
{
return toAjax(subsystemTemperatureService.updateSubsystemTemperature(subsystemTemperature));
@ -94,9 +102,10 @@ public class SubsystemTemperatureController extends BaseController
/**
* 删除可充电储能子系统温度信息
*/
@PreAuthorize("@ss.hasPermi('temperature:temperature:remove')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemTemperature:remove')")
@Log(title = "可充电储能子系统温度信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@DeleteMapping("/{ids}")
@ApiOperation("删除子系统温度信息")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(subsystemTemperatureService.deleteSubsystemTemperatureByIds(ids));

View File

@ -20,6 +20,8 @@ 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
@ -28,7 +30,8 @@ import com.evobms.framework.web.page.TableDataInfo;
* @date 2025-11-15
*/
@RestController
@RequestMapping("/voltage/voltage")
@RequestMapping("/Battery/SubsystemVoltage")
@Api(tags = "可充电储能子系统电压信息")
public class SubsystemVoltageController extends BaseController
{
@Autowired
@ -37,8 +40,9 @@ public class SubsystemVoltageController extends BaseController
/**
* 查询可充电储能子系统电压信息列表
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:list')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:list')")
@GetMapping("/list")
@ApiOperation("查询子系统电压信息列表")
public TableDataInfo list(SubsystemVoltage subsystemVoltage)
{
startPage();
@ -49,9 +53,10 @@ public class SubsystemVoltageController extends BaseController
/**
* 导出可充电储能子系统电压信息列表
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:export')")
@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);
@ -62,8 +67,9 @@ public class SubsystemVoltageController extends BaseController
/**
* 获取可充电储能子系统电压信息详细信息
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:query')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:query')")
@GetMapping(value = "/{id}")
@ApiOperation("获取子系统电压信息详细信息")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(subsystemVoltageService.selectSubsystemVoltageById(id));
@ -72,9 +78,10 @@ public class SubsystemVoltageController extends BaseController
/**
* 新增可充电储能子系统电压信息
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:add')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:add')")
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增子系统电压信息")
public AjaxResult add(@RequestBody SubsystemVoltage subsystemVoltage)
{
return toAjax(subsystemVoltageService.insertSubsystemVoltage(subsystemVoltage));
@ -83,9 +90,10 @@ public class SubsystemVoltageController extends BaseController
/**
* 修改可充电储能子系统电压信息
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:edit')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:edit')")
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改子系统电压信息")
public AjaxResult edit(@RequestBody SubsystemVoltage subsystemVoltage)
{
return toAjax(subsystemVoltageService.updateSubsystemVoltage(subsystemVoltage));
@ -94,9 +102,10 @@ public class SubsystemVoltageController extends BaseController
/**
* 删除可充电储能子系统电压信息
*/
@PreAuthorize("@ss.hasPermi('voltage:voltage:remove')")
@PreAuthorize("@ss.hasPermi('Battery:SubsystemVoltage:remove')")
@Log(title = "可充电储能子系统电压信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@DeleteMapping("/{ids}")
@ApiOperation("删除子系统电压信息")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(subsystemVoltageService.deleteSubsystemVoltageByIds(ids));

View File

@ -2,7 +2,11 @@ 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;
@ -14,67 +18,85 @@ import com.evobms.framework.web.domain.BaseEntity;
* @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;
/** 数据时间戳 */
@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;

View File

@ -1,10 +1,13 @@
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
@ -13,44 +16,55 @@ import com.evobms.framework.web.domain.BaseEntity;
* @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;

View File

@ -2,6 +2,8 @@ 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;
@ -16,60 +18,74 @@ import com.evobms.framework.web.domain.BaseEntity;
* @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;

View File

@ -7,8 +7,10 @@ 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) {
String s = sn == null ? "" : sn;
@ -68,150 +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);
System.out.println("密钥------------------------>"+aesKey);
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) {
@ -280,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);
}
}

View File

@ -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,6 +42,7 @@ 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) {
@ -58,6 +62,7 @@ public class MqttPublishController {
* 发布原始十六进制字节消息到指定主题
*/
@PostMapping("/publishHex")
@ApiOperation("发布HEX消息")
public AjaxResult publishHex(@RequestParam String topic, @RequestParam String hex) {
try {
if (mqttService == null) {
@ -78,6 +83,7 @@ public class MqttPublishController {
* 获取当前请求的鉴权令牌从请求头读取并去除前缀
*/
@GetMapping("/authToken")
@ApiOperation("获取鉴权令牌")
public AjaxResult getAuthToken(HttpServletRequest request) {
try {
String raw = request.getHeader(tokenHeader);
@ -129,6 +135,7 @@ public class MqttPublishController {
*/
@PostMapping("/publishDeviceData")
// @Log(title = "设备数据发布", businessType = BusinessType.INSERT)
@ApiOperation("发布设备测试数据")
public AjaxResult publishDeviceData(@RequestParam String deviceCode) {
try {
if (mqttService == null) {
@ -160,6 +167,7 @@ public class MqttPublishController {
* 快速测试 - 发布消息到test设备
*/
@GetMapping("/quickTest")
@ApiOperation("快速测试发布")
public AjaxResult quickTest() {
try {
if (mqttService == null) {
@ -192,6 +200,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) {

View File

@ -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,6 +34,7 @@ public class MqttTestController {
* @return 测试结果
*/
@PostMapping("/handleDeviceData")
@ApiOperation("测试处理设备数据")
public Map<String, Object> testHandleDeviceData(
@RequestParam String topic,
@RequestParam byte[] payload) {
@ -70,6 +74,7 @@ public class MqttTestController {
* @return 测试用的JSON数据
*/
@GetMapping("/generateTestData")
@ApiOperation("生成测试数据")
public Map<String, Object> generateTestData() {
Map<String, Object> testData = new HashMap<>();
testData.put("voltage", 12.5);

View File

@ -0,0 +1,75 @@
package com.evobms.project.bms.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 com.evobms.framework.aspectj.lang.annotation.Excel;
import com.evobms.framework.web.domain.BaseEntity;
@Data
@ApiModel(description = "BMS充电过程详细数据")
public class BmsChargeDetail extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
private Long id;
@ApiModelProperty("设备ID")
@Excel(name = "设备ID")
private String deviceId;
@ApiModelProperty("数据时间戳")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date timestamp;
@ApiModelProperty("慢充电流(A)")
@Excel(name = "慢充电流(A)")
private java.math.BigDecimal acChargeCurrent;
@ApiModelProperty("慢充电压(V)")
@Excel(name = "慢充电压(V)")
private java.math.BigDecimal acChargeVoltage;
@ApiModelProperty("快充电流(A)")
@Excel(name = "快充电流(A)")
private java.math.BigDecimal dcChargeCurrent;
@ApiModelProperty("快充电压(V)")
@Excel(name = "快充电压(V)")
private java.math.BigDecimal dcChargeVoltage;
@ApiModelProperty("充电时长(min)")
@Excel(name = "充电时长(min)")
private Integer chargeTime;
@ApiModelProperty("慢充停止码")
@Excel(name = "慢充停止码")
private Integer acStopCode;
@ApiModelProperty("快充停止码")
@Excel(name = "快充停止码")
private Integer dcStopCode;
@ApiModelProperty("慢充CP值")
@Excel(name = "慢充CP值")
private Integer acCpValue;
@ApiModelProperty("慢充枪阻值")
@Excel(name = "慢充枪阻值")
private Integer acGunResistance;
@ApiModelProperty("充电阶段")
@Excel(name = "充电阶段")
private Integer chargingStage;
@ApiModelProperty("慢充阶段")
@Excel(name = "慢充阶段")
private Integer acStage;
@ApiModelProperty("快充阶段")
@Excel(name = "快充阶段")
private Integer dcStage;
}

View File

@ -0,0 +1,67 @@
package com.evobms.project.bms.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 com.evobms.framework.aspectj.lang.annotation.Excel;
import com.evobms.framework.web.domain.BaseEntity;
@Data
@ApiModel(description = "BMS功率能力(SOP)数据")
public class BmsSopData extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
private Long id;
@ApiModelProperty("设备ID")
@Excel(name = "设备ID")
private String deviceId;
@ApiModelProperty("数据时间戳")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date timestamp;
@ApiModelProperty("10秒放电SOP(A)")
@Excel(name = "10秒放电SOP(A)")
private Integer dischargeSop10s;
@ApiModelProperty("30秒放电SOP(A)")
@Excel(name = "30秒放电SOP(A)")
private Integer dischargeSop30s;
@ApiModelProperty("60秒放电SOP(A)")
@Excel(name = "60秒放电SOP(A)")
private Integer dischargeSop60s;
@ApiModelProperty("持续放电SOP(A)")
@Excel(name = "持续放电SOP(A)")
private Integer dischargeSopContinuous;
@ApiModelProperty("10秒回馈SOP(A)")
@Excel(name = "10秒回馈SOP(A)")
private Integer regenSop10s;
@ApiModelProperty("30秒回馈SOP(A)")
@Excel(name = "30秒回馈SOP(A)")
private Integer regenSop30s;
@ApiModelProperty("60秒回馈SOP(A)")
@Excel(name = "60秒回馈SOP(A)")
private Integer regenSop60s;
@ApiModelProperty("持续回馈SOP(A)")
@Excel(name = "持续回馈SOP(A)")
private Integer regenSopContinuous;
@ApiModelProperty("充电SOP(A)")
@Excel(name = "充电SOP(A)")
private Integer chargeSop;
@ApiModelProperty("慢充SOP(A)")
@Excel(name = "慢充SOP(A)")
private Integer acChargeSop;
}

View File

@ -0,0 +1,59 @@
package com.evobms.project.bms.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 com.evobms.framework.aspectj.lang.annotation.Excel;
import com.evobms.framework.web.domain.BaseEntity;
@Data
@ApiModel(description = "BMS系统状态数据")
public class BmsSystemStatus extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
private Long id;
@ApiModelProperty("设备ID")
@Excel(name = "设备ID")
private String deviceId;
@ApiModelProperty("数据时间戳")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "数据时间戳", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date timestamp;
@ApiModelProperty("继电器状态")
@Excel(name = "继电器状态")
private Integer relayStatus;
@ApiModelProperty("ON/A+/CC状态")
@Excel(name = "ON/A+/CC状态")
private Integer onaaccStatus;
@ApiModelProperty("系统复位次数")
@Excel(name = "系统复位次数")
private Integer resetCount;
@ApiModelProperty("电池循环次数")
@Excel(name = "电池循环次数")
private Integer cycleCount;
@ApiModelProperty("2.5V采样电压(V)")
@Excel(name = "2.5V采样电压(V)")
private java.math.BigDecimal sample25v;
@ApiModelProperty("5V采样电压(V)")
@Excel(name = "5V采样电压(V)")
private java.math.BigDecimal sample5v;
@ApiModelProperty("单体数量")
@Excel(name = "单体数量")
private Integer cellCount;
@ApiModelProperty("温度探头数量")
@Excel(name = "温度探头数量")
private Integer tempSensorCount;
}

View File

@ -0,0 +1,9 @@
package com.evobms.project.bms.mapper;
import com.evobms.project.bms.domain.BmsChargeDetail;
import java.util.List;
public interface BmsChargeDetailMapper {
int insertBmsChargeDetail(BmsChargeDetail data);
List<BmsChargeDetail> selectBmsChargeDetailList(BmsChargeDetail filter);
}

View File

@ -0,0 +1,9 @@
package com.evobms.project.bms.mapper;
import com.evobms.project.bms.domain.BmsSopData;
import java.util.List;
public interface BmsSopDataMapper {
int insertBmsSopData(BmsSopData data);
List<BmsSopData> selectBmsSopDataList(BmsSopData filter);
}

View File

@ -0,0 +1,9 @@
package com.evobms.project.bms.mapper;
import com.evobms.project.bms.domain.BmsSystemStatus;
import java.util.List;
public interface BmsSystemStatusMapper {
int insertBmsSystemStatus(BmsSystemStatus data);
List<BmsSystemStatus> selectBmsSystemStatusList(BmsSystemStatus filter);
}

View File

@ -0,0 +1,7 @@
package com.evobms.project.bms.service;
import com.evobms.project.bms.domain.BmsChargeDetail;
public interface IBmsChargeDetailService {
int insertBmsChargeDetail(BmsChargeDetail data);
}

View File

@ -0,0 +1,7 @@
package com.evobms.project.bms.service;
import com.evobms.project.bms.domain.BmsSopData;
public interface IBmsSopDataService {
int insertBmsSopData(BmsSopData data);
}

View File

@ -0,0 +1,7 @@
package com.evobms.project.bms.service;
import com.evobms.project.bms.domain.BmsSystemStatus;
public interface IBmsSystemStatusService {
int insertBmsSystemStatus(BmsSystemStatus data);
}

View File

@ -261,30 +261,32 @@ public class MqttService {
*/
private void parseByProtocolIndex(byte[] message, String deviceSn) {
try {
// 1. 时间信息 - 索引24-29 (6字节)
// 1.时间戳- 索引24-29 (6字节)
Date frameTime = parseTimeAtIndex(message, 0, deviceSn);
if (frameTime == null) {
frameTime = new Date();
}
// 2. 整车数据 - 索引30-49 (20字节)
// 2. 整车数据 - 绝对索引30-49(20字节) | 相对偏移: 6-25
parseVehicleDataAtIndex(message, 6, deviceSn, frameTime);
// 3. 位置信息 - 索引51-60 (10字节)
// 3. 位置信息 - 绝对索引51-60(10字节) | 相对偏移: 27-36
parseLocationDataAtIndex(message, 27, deviceSn, frameTime);
// 4. 极值数据 - 索引61-75 (14字节)
// 4. 极值数据 - 绝对索引61-75(15字节) | 相对偏移: 37-51
parseExtremeDataAtIndex(message, 37, deviceSn, frameTime);
// 5. 单体电压数据 - 索引76-447 (372字节)
// 5. 单体电压数据 - 绝对索引76-447(372字节) | 相对偏移: 52-423
parseCellVoltageAtIndex(message, 52, deviceSn, frameTime);
// 6. 单体温度数据 - 索引448-542 (95字节)
// 6. 单体温度数据 - 绝对索引448-542(95字节) | 相对偏移: 424-518
parseCellTemperatureAtIndex(message, 424, deviceSn, frameTime);
// 7. 累计充放电量 - 索引543-553 (11字节)
// 7. 累计充放电量 - 绝对索引543-553(11字节) | 相对偏移: 519-529
parseChargeDischargeAtIndex(message, 519, deviceSn, frameTime);
parseExtendedDataAtIndex(message, 506, deviceSn, frameTime);
log.info("设备 {} 所有数据段解析完成", deviceSn);
} catch (Exception e) {
@ -293,7 +295,7 @@ public class MqttService {
}
/**
* 解析时间信息 - 索引24-29 (6字节)
* 解析时间信息 - 绝对索引24-29(6字节) | 相对偏移: 0-5
* 格式: (偏移2000) + + + + +
*/
private Date parseTimeAtIndex(byte[] message, int startIndex, String deviceSn) {
@ -330,7 +332,7 @@ public class MqttService {
}
/**
* 解析整车数据 - 索引30-49 (20字节)
* 解析整车数据 - 绝对索引30-49(20字节) | 相对偏移: 6-25
*/
private void parseVehicleDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -381,7 +383,7 @@ public class MqttService {
/**
* 解析位置信息 - 索引51-60 (10字节)
* 解析位置信息 - 绝对索引51-60(10字节) | 相对偏移: 27-36
*/
private void parseLocationDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -431,7 +433,7 @@ public class MqttService {
}
/**
* 解析极值数据 - 索引61-75 (14字节)
* 解析极值数据 - 绝对索引61-75(15字节) | 相对偏移: 37-51
*/
private void parseExtremeDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -492,7 +494,7 @@ public class MqttService {
/**
* 解析单体电压数据 - 索引76-447 (372字节)
* 解析单体电压数据 - 绝对索引76-447(372字节) | 相对偏移: 52-423
*/
private void parseCellVoltageAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -575,7 +577,7 @@ public class MqttService {
/**
* 解析单体温度数据 - 索引448-542 (95字节)
* 解析单体温度数据 - 绝对索引448-542(95字节) | 相对偏移: 424-518
*/
private void parseCellTemperatureAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -638,7 +640,7 @@ public class MqttService {
}
/**
* 解析累计充放电量 - 索引543-553 (11字节)
* 解析累计充放电量 - 绝对索引543-553(11字节) | 相对偏移: 519-529
*/
private void parseChargeDischargeAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
@ -646,7 +648,6 @@ public class MqttService {
log.warn("设备 {}: 充放电数据索引越界", deviceSn);
return;
}
// 索引543: 数据标识 (应该是0x80)
byte dataFlag = message[startIndex];
if (dataFlag != (byte) 0x80) {
@ -658,16 +659,10 @@ public class MqttService {
// 跳过索引544-545的保留字节
// 索引546-549: 累计放电电量 (0.1kWh)
long dischargeEnergy = ((message[startIndex + 3] & 0xFFL) << 24) |
((message[startIndex + 4] & 0xFFL) << 16) |
((message[startIndex + 5] & 0xFFL) << 8) |
(message[startIndex + 6] & 0xFFL);
long dischargeEnergy = ((message[startIndex + 3] & 0xFFL) << 24) | ((message[startIndex + 4] & 0xFFL) << 16) | ((message[startIndex + 5] & 0xFFL) << 8) | (message[startIndex + 6] & 0xFFL);
// 索引550-553: 累计充电电量 (0.1kWh)
long chargeEnergy = ((message[startIndex + 7] & 0xFFL) << 24) |
((message[startIndex + 8] & 0xFFL) << 16) |
((message[startIndex + 9] & 0xFFL) << 8) |
(message[startIndex + 10] & 0xFFL);
long chargeEnergy = ((message[startIndex + 7] & 0xFFL) << 24) |((message[startIndex + 8] & 0xFFL) << 16) | ((message[startIndex + 9] & 0xFFL) << 8) | (message[startIndex + 10] & 0xFFL);
double dischargeKwh = dischargeEnergy * 0.1;
double chargeKwh = chargeEnergy * 0.1;
@ -944,6 +939,132 @@ public class MqttService {
sendDeviceCommand(deviceCode, "STATUS_QUERY");
}
/**
* 扩展区块解析BatteryData[530..716]
* 索引换算: 绝对索引abs message索引 = startIndex + (abs - 530)
* 单位与偏移:
* - 电压/电流 ×0.1除特殊 2.5V/5V 采样为 ×0.001
* - 温度值需减去 40协议偏移
* - 车速 ×0.1 km/h
* - 里程为 u32 原始值单位由上位业务确定
*/
private void parseExtendedDataAtIndex(byte[] message, int startIndex, String deviceSn, Date frameTime) {
try {
int base = startIndex;
int need = (716 - 530 + 1);
if (message.length < base + need) {
log.warn("设备 {}: 扩展数据索引越界", deviceSn);
return;
}
// 系统计数/绝缘/车速/总压
long resetCount = ((message[base + 0] & 0xFFL) << 24) | ((message[base + 1] & 0xFFL) << 16) | ((message[base + 2] & 0xFFL) << 8) | (message[base + 3] & 0xFFL); // 复位次数(u32)
int insulationVal = ((message[base + 4] & 0xFF) << 8) | (message[base + 5] & 0xFF); // 绝缘值(单位KΩ)
int carSpdRaw = ((message[base + 6] & 0xFF) << 8) | (message[base + 7] & 0xFF); // 车速原始(×0.1km/h)
double carSpd = carSpdRaw * 0.1;
int gpvRaw = ((message[base + 8] & 0xFF) << 8) | (message[base + 9] & 0xFF); // GPV(×0.1V)
double gpv = gpvRaw * 0.1;
// RTP1..7(×0.1V)
double rtp1 = (((message[base + 10] & 0xFF) << 8) | (message[base + 11] & 0xFF)) * 0.1;
double rtp2 = (((message[base + 12] & 0xFF) << 8) | (message[base + 13] & 0xFF)) * 0.1;
double rtp3 = (((message[base + 14] & 0xFF) << 8) | (message[base + 15] & 0xFF)) * 0.1;
double rtp4 = (((message[base + 16] & 0xFF) << 8) | (message[base + 17] & 0xFF)) * 0.1;
double rtp5 = (((message[base + 18] & 0xFF) << 8) | (message[base + 19] & 0xFF)) * 0.1;
double rtp6 = (((message[base + 20] & 0xFF) << 8) | (message[base + 21] & 0xFF)) * 0.1;
double rtp7 = (((message[base + 22] & 0xFF) << 8) | (message[base + 23] & 0xFF)) * 0.1;
// RTN探针序号
int rtn1 = message[base + 24] & 0xFF; // RTN1
int rtn2 = message[base + 25] & 0xFF; // RTN2
int rtn3 = message[base + 26] & 0xFF; // RTN3
int rtn4 = message[base + 27] & 0xFF; // RTN4
double realSocMax = (((message[base + 28] & 0xFF) << 8) | (message[base + 29] & 0xFF)) * 0.1; // RealSOC最大(×0.1%)
double realSocMin = (((message[base + 30] & 0xFF) << 8) | (message[base + 31] & 0xFF)) * 0.1; // RealSOC最小(×0.1%)
// 充电座温度(需减40)
int chgBs1Tmp = (message[base + 32] & 0xFF) - 40;
int chgBs2Tmp = (message[base + 33] & 0xFF) - 40;
int chgBs3Tmp = (message[base + 34] & 0xFF) - 40;
int chgBs4Tmp = (message[base + 35] & 0xFF) - 40;
int chgBs5Tmp = (message[base + 36] & 0xFF) - 40;
int chgBs6Tmp = (message[base + 37] & 0xFF) - 40;
int chgBs7Tmp = (message[base + 38] & 0xFF) - 40;
int chgBs8Tmp = (message[base + 39] & 0xFF) - 40;
// 慢充/快充电流电压(×0.1)
double tChgCur = (((message[base + 40] & 0xFF) << 8) | (message[base + 41] & 0xFF)) * 0.1; // 慢充电流(A)
double tChgVol = (((message[base + 42] & 0xFF) << 8) | (message[base + 43] & 0xFF)) * 0.1; // 慢充电压(V)
double fChgCur = (((message[base + 44] & 0xFF) << 8) | (message[base + 45] & 0xFF)) * 0.1; // 快充电流(A)
double fChgVol = (((message[base + 46] & 0xFF) << 8) | (message[base + 47] & 0xFF)) * 0.1; // 快充电压(V)
// 放电/回馈SOP能力(A)
int disSop10 = ((message[base + 48] & 0xFF) << 8) | (message[base + 49] & 0xFF);
int disSop30 = ((message[base + 50] & 0xFF) << 8) | (message[base + 51] & 0xFF);
int disSop60 = ((message[base + 52] & 0xFF) << 8) | (message[base + 53] & 0xFF);
int disSopCont = ((message[base + 54] & 0xFF) << 8) | (message[base + 55] & 0xFF);
int regSop10 = ((message[base + 56] & 0xFF) << 8) | (message[base + 57] & 0xFF);
int regSop30 = ((message[base + 58] & 0xFF) << 8) | (message[base + 59] & 0xFF);
int regSop60 = ((message[base + 60] & 0xFF) << 8) | (message[base + 61] & 0xFF);
int regSopCont = ((message[base + 62] & 0xFF) << 8) | (message[base + 63] & 0xFF);
int disSopTol = ((message[base + 64] & 0xFF) << 8) | (message[base + 65] & 0xFF);
int regSopTol = ((message[base + 66] & 0xFF) << 8) | (message[base + 67] & 0xFF);
// 版本与编码
int hwVer = ((message[base + 68] & 0xFF) << 8) | (message[base + 69] & 0xFF); // 硬件版本
int swVer = ((message[base + 70] & 0xFF) << 8) | (message[base + 71] & 0xFF); // 软件版本
String bmsCode = readAsciiRange(message, 602, 28, base); // BMS编码(28字节ASCII)
String vin = readAsciiRange(message, 629, 21, base); // VIN码(21字节ASCII)
// 系统状态
int sysVolRaw = ((message[base + (649 - 530)] & 0xFF) << 8) | (message[base + (650 - 530)] & 0xFF); // 系统电压(×0.1V)
int sysCurRaw = ((message[base + (651 - 530)] & 0xFF) << 8) | (message[base + (652 - 530)] & 0xFF); // 系统电流(×0.1A)
double sysVol = sysVolRaw * 0.1;
double sysCur = sysCurRaw * 0.1;
int cellCount = ((message[base + (653 - 530)] & 0xFF) << 8) | (message[base + (654 - 530)] & 0xFF);
int tempSensorCount = ((message[base + (655 - 530)] & 0xFF) << 8) | (message[base + (656 - 530)] & 0xFF);
int relayStatus = ((message[base + (657 - 530)] & 0xFF) << 8) | (message[base + (658 - 530)] & 0xFF);
int onaaccStatus = ((message[base + (659 - 530)] & 0xFF) << 8) | (message[base + (660 - 530)] & 0xFF);
int acStopCode = message[base + (661 - 530)] & 0xFF;
int dcStopCode = message[base + (662 - 530)] & 0xFF;
int cycleCount = ((message[base + (663 - 530)] & 0xFF) << 8) | (message[base + (664 - 530)] & 0xFF);
long devId = ((message[base + (665 - 530)] & 0xFFL) << 24) | ((message[base + (666 - 530)] & 0xFFL) << 16) | ((message[base + (667 - 530)] & 0xFFL) << 8) | (message[base + (668 - 530)] & 0xFFL);
String clientCode = readAsciiRange(message, 669, 28, base); // 客户编码(28字节ASCII)
double samp25v = (((message[base + (696 - 530)] & 0xFF) << 8) | (message[base + (697 - 530)] & 0xFF)) * 0.001; // 2.5V采样(×0.001V)
double samp5v = (((message[base + (698 - 530)] & 0xFF) << 8) | (message[base + (699 - 530)] & 0xFF)) * 0.001; // 5V采样(×0.001V)
int chargeSop = ((message[base + (700 - 530)] & 0xFF) << 8) | (message[base + (701 - 530)] & 0xFF); // 充电SOP(A)
int acChargeSop = ((message[base + (702 - 530)] & 0xFF) << 8) | (message[base + (703 - 530)] & 0xFF); // 慢充SOP(A)
// 运行阶段/充电阶段/时间与里程
int runSts = message[base + (704 - 530)] & 0xFF; // 行车阶段
int runPwrSts = message[base + (705 - 530)] & 0xFF; // 行车上电阶段
int tChgCp = message[base + (706 - 530)] & 0xFF; // 慢充CP值
int tChgR = message[base + (707 - 530)] & 0xFF; // 慢充枪阻值
int tChgSts = message[base + (708 - 530)] & 0xFF; // 慢充阶段
int fChgSts2 = message[base + (709 - 530)] & 0xFF; // 快充阶段
int chgSts = message[base + (710 - 530)] & 0xFF; // 充电阶段
int chgTime = ((message[base + (711 - 530)] & 0xFF) << 8) | (message[base + (712 - 530)] & 0xFF); // 充电时长(min)
long mileage = ((message[base + (713 - 530)] & 0xFFL) << 24) | ((message[base + (714 - 530)] & 0xFFL) << 16) | ((message[base + (715 - 530)] & 0xFFL) << 8) | (message[base + (716 - 530)] & 0xFFL); // 里程(u32)
log.info("设备 {} 扩展数据: resetCount={}, insulationValKOhm={}, carSpeedKmH={}, GPV0_1V={}, RTPs(V)=[{},{},{},{},{},{},{}], RTNs=[{},{},{},{}], realSOCMax0_1={}, realSOCMin0_1={}, chargeSeatTempsC=[{},{},{},{},{},{},{},{}]", deviceSn, resetCount, insulationVal, carSpd, gpv, rtp1, rtp2, rtp3, rtp4, rtp5, rtp6, rtp7, rtn1, rtn2, rtn3, rtn4, realSocMax, realSocMin, chgBs1Tmp, chgBs2Tmp, chgBs3Tmp, chgBs4Tmp, chgBs5Tmp, chgBs6Tmp, chgBs7Tmp, chgBs8Tmp);
log.info("设备 {} 充电详情: tChgCurA={}, tChgVolV={}, fChgCurA={}, fChgVolV={}, disSOP(A)=[{},{},{},{}], regSOP(A)=[{},{},{},{}], disSopTolA={}, regSopTolA={}", deviceSn, tChgCur, tChgVol, fChgCur, fChgVol, disSop10, disSop30, disSop60, disSopCont, regSop10, regSop30, regSop60, regSopCont, disSopTol, regSopTol);
log.info("设备 {} 版本与编码: hwVer={}, swVer={}, BMSCode='{}', VIN='{}', clientCode='{}', devId={}", deviceSn, hwVer, swVer, bmsCode, vin, clientCode, devId);
log.info("设备 {} 系统状态: sysVolV={}, sysCurA={}, cellCount={}, tempSensorCount={}, relayStatus={}, onaaccStatus={}, acStopCode={}, dcStopCode={}, cycleCount={}, samp25V={}, samp5V={}, chargeSopA={}, acChargeSopA={}", deviceSn, sysVol, sysCur, cellCount, tempSensorCount, relayStatus, onaaccStatus, acStopCode, dcStopCode, cycleCount, samp25v, samp5v, chargeSop, acChargeSop);
log.info("设备 {} 运行阶段: runSts={}, runPwrSts={}, tChgCp={}, tChgR={}, tChgSts={}, fChgSts={}, chgSts={}, chgTimeMin={}, mileage={}", deviceSn, runSts, runPwrSts, tChgCp, tChgR, tChgSts, fChgSts2, chgSts, chgTime, mileage);
} catch (Exception e) {
log.error("设备 {} 解析扩展数据时发生错误: {}", deviceSn, e.getMessage());
}
}
/**
* 读取 ASCII 字符串
* @param startAbs BatteryData 绝对索引(例如 602 对应 BMS编码起始)
* @param len 字节长度
* @param base 530 的映射起点message 中的 startIndex
*/
private String readAsciiRange(byte[] message, int startAbs, int len, int base) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
int idx = base + (startAbs - 530) + i;
if (idx >= 0 && idx < message.length) {
int b = message[idx] & 0xFF;
if (b != 0) {
sb.append((char) b);
}
}
}
return sb.toString().trim();
}
/**
* 根据设备唯一编号(deviceCode)查询系统设备表的SN码

View File

@ -0,0 +1,18 @@
package com.evobms.project.bms.service.impl;
import com.evobms.project.bms.domain.BmsChargeDetail;
import com.evobms.project.bms.mapper.BmsChargeDetailMapper;
import com.evobms.project.bms.service.IBmsChargeDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BmsChargeDetailServiceImpl implements IBmsChargeDetailService {
@Autowired
private BmsChargeDetailMapper mapper;
@Override
public int insertBmsChargeDetail(BmsChargeDetail data) {
return mapper.insertBmsChargeDetail(data);
}
}

View File

@ -0,0 +1,18 @@
package com.evobms.project.bms.service.impl;
import com.evobms.project.bms.domain.BmsSopData;
import com.evobms.project.bms.mapper.BmsSopDataMapper;
import com.evobms.project.bms.service.IBmsSopDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BmsSopDataServiceImpl implements IBmsSopDataService {
@Autowired
private BmsSopDataMapper mapper;
@Override
public int insertBmsSopData(BmsSopData data) {
return mapper.insertBmsSopData(data);
}
}

View File

@ -0,0 +1,18 @@
package com.evobms.project.bms.service.impl;
import com.evobms.project.bms.domain.BmsSystemStatus;
import com.evobms.project.bms.mapper.BmsSystemStatusMapper;
import com.evobms.project.bms.service.IBmsSystemStatusService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BmsSystemStatusServiceImpl implements IBmsSystemStatusService {
@Autowired
private BmsSystemStatusMapper mapper;
@Override
public int insertBmsSystemStatus(BmsSystemStatus data) {
return mapper.insertBmsSystemStatus(data);
}
}

View File

@ -13,6 +13,7 @@ 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;
@ -52,7 +53,9 @@ import java.util.Map;
*/
@RestController
@Tag(name = "设备鉴权", description = "设备鉴权令牌接口")
@Api(tags = "IoT设备鉴权")
@RequestMapping("/iot")
@Slf4j
public class IotAuthController {
private static final Logger log = LoggerFactory.getLogger(IotAuthController.class);
@ -96,11 +99,13 @@ public class IotAuthController {
*/
@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);
@ -388,6 +393,7 @@ public class IotAuthController {
*/
@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) {

View File

@ -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<>();

View File

@ -20,6 +20,8 @@ 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,6 +31,7 @@ import com.evobms.framework.web.page.TableDataInfo;
*/
@RestController
@RequestMapping("/ota/tasks")
@Api(tags = "OTA任务管理")
public class OtaTasksController extends BaseController
{
@Autowired
@ -39,6 +42,7 @@ public class OtaTasksController extends BaseController
*/
//@PreAuthorize("@ss.hasPermi('OTA:tasks:list')")
@GetMapping("/list")
@ApiOperation("查询OTA任务列表")
public TableDataInfo list(OtaTasks otaTasks)
{
startPage();
@ -52,6 +56,7 @@ public class OtaTasksController extends BaseController
//@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 +69,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 +81,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 +93,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,6 +104,7 @@ 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));

View File

@ -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;
/** 任务IDUUID */
@ApiModelProperty(value = "任务IDUUID")
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();
}
}

View File

@ -20,6 +20,8 @@ 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
@ -29,6 +31,7 @@ import com.evobms.framework.web.page.TableDataInfo;
*/
@RestController
@RequestMapping("/summary/summary")
@Api(tags = "充放电统计")
public class ChargeDischargeSummaryController extends BaseController
{
@Autowired
@ -39,6 +42,7 @@ public class ChargeDischargeSummaryController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('summary:summary:list')")
@GetMapping("/list")
@ApiOperation("查询累计充放电量列表")
public TableDataInfo list(ChargeDischargeSummary chargeDischargeSummary)
{
startPage();
@ -52,6 +56,7 @@ public class ChargeDischargeSummaryController extends BaseController
@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);
@ -64,6 +69,7 @@ public class ChargeDischargeSummaryController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('summary:summary:query')")
@GetMapping(value = "/{id}")
@ApiOperation("获取累计充放电量详细信息")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(chargeDischargeSummaryService.selectChargeDischargeSummaryById(id));
@ -75,6 +81,7 @@ public class ChargeDischargeSummaryController extends BaseController
@PreAuthorize("@ss.hasPermi('summary:summary:add')")
@Log(title = "累计充放电量", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增累计充放电量")
public AjaxResult add(@RequestBody ChargeDischargeSummary chargeDischargeSummary)
{
return toAjax(chargeDischargeSummaryService.insertChargeDischargeSummary(chargeDischargeSummary));
@ -86,6 +93,7 @@ public class ChargeDischargeSummaryController extends BaseController
@PreAuthorize("@ss.hasPermi('summary:summary:edit')")
@Log(title = "累计充放电量", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改累计充放电量")
public AjaxResult edit(@RequestBody ChargeDischargeSummary chargeDischargeSummary)
{
return toAjax(chargeDischargeSummaryService.updateChargeDischargeSummary(chargeDischargeSummary));
@ -96,7 +104,8 @@ public class ChargeDischargeSummaryController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('summary:summary:remove')")
@Log(title = "累计充放电量", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@DeleteMapping("/{ids}")
@ApiOperation("删除累计充放电量")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(chargeDischargeSummaryService.deleteChargeDischargeSummaryByIds(ids));

View File

@ -3,6 +3,10 @@ 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;
@ -14,6 +18,9 @@ import com.evobms.framework.web.domain.BaseEntity;
* @author 田志阳
* @date 2026-01-09
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "ChargeDischargeSummary", description = "累计充放电量对象")
public class ChargeDischargeSummary extends BaseEntity
{
private static final long serialVersionUID = 1L;
@ -23,83 +30,23 @@ public class ChargeDischargeSummary extends BaseEntity
/** 设备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) */
@Excel(name = "累计充电kWh)")
@ApiModelProperty(value = "累计充电kWh")
@Excel(name = "累计充电(kWh)")
private BigDecimal chargeKwh;
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 setDischargeKwh(BigDecimal dischargeKwh)
{
this.dischargeKwh = dischargeKwh;
}
public BigDecimal getDischargeKwh()
{
return dischargeKwh;
}
public void setChargeKwh(BigDecimal chargeKwh)
{
this.chargeKwh = chargeKwh;
}
public BigDecimal getChargeKwh()
{
return chargeKwh;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("timestamp", getTimestamp())
.append("dischargeKwh", getDischargeKwh())
.append("chargeKwh", getChargeKwh())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.append("createBy", getCreateBy())
.append("updateBy", getUpdateBy())
.toString();
}
}

View File

@ -20,15 +20,18 @@ 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;
/**
* BBOX管理Controller
*
* @author 田志阳
* @date 2025-10-10
* @date 2025-11-15
*/
@RestController
@RequestMapping("/devices/devices")
@Api(tags = "BBOX设备管理")
public class BmsDevicesController extends BaseController
{
@Autowired
@ -37,7 +40,9 @@ public class BmsDevicesController extends BaseController
/**
* 查询BBOX管理列表
*/
@PreAuthorize("@ss.hasPermi('system:devices:list')")
@GetMapping("/list")
@ApiOperation("查询BBOX设备列表")
public TableDataInfo list(BmsDevices bmsDevices)
{
startPage();
@ -48,8 +53,10 @@ public class BmsDevicesController extends BaseController
/**
* 导出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,7 +67,9 @@ 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));
@ -69,8 +78,10 @@ public class BmsDevicesController extends BaseController
/**
* 新增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 +90,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,8 +102,10 @@ 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));

View File

@ -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,41 +19,51 @@ 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;
/** 最后在线时间 */
@ApiModelProperty("最后在线时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "最后在线时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date lastOnline;

View File

@ -29,6 +29,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
/**
* 图标组件Controller
*
@ -57,7 +58,9 @@ public class BatteryChartController {
// 图表数据按最近 hours 小时返回整车电压/电流/SOC 的时间序列
@GetMapping("/battery-data/{deviceId}/chart")
@ApiOperation(value = "整车电压电流SOC时间序列", notes = "按最近hours小时返回时间序列")
public List<ChartDataPoint> getChartData(@PathVariable("deviceId") String deviceId, @RequestParam(value = "hours", required = false, defaultValue = "24") int 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);
@ -72,21 +75,25 @@ public class BatteryChartController {
// 整车最新返回 deviceId 最新的一条整车数据
@GetMapping("/vehicle-data/{deviceId}/latest")
@ApiOperation(value = "整车最新数据", notes = "返回指定设备最新整车数据")
public VehicleData latestVehicleData(@PathVariable("deviceId") String deviceId) {
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(@PathVariable("deviceId") String deviceId) {
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(@PathVariable("deviceId") String deviceId, @RequestParam("start") long startMillis, @RequestParam("end") long endMillis, @RequestParam(value = "limit", required = false) Integer limit) {
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);
@ -95,21 +102,26 @@ public class BatteryChartController {
// 子系统最新帧电压返回指定子系统号最新的一帧电压数据
@GetMapping("/subsystem-voltage/{deviceId}/{subsystemNo}/latest")
@ApiOperation(value = "子系统最新电压帧", notes = "返回指定子系统最新电压数据")
public SubsystemVoltage latestVoltage(@PathVariable("deviceId") String deviceId, @PathVariable("subsystemNo") Integer subsystemNo) {
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(@PathVariable("deviceId") String deviceId, @PathVariable("subsystemNo") Integer subsystemNo) {
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(@PathVariable("deviceId") String deviceId,
@RequestParam(value = "before", required = false) String 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);
}
@ -126,7 +138,7 @@ public class BatteryChartController {
return extremeValuesService.selectLatestByDeviceIdBefore(deviceId, beforeTime);
}
@GetMapping("/api/dashboard/home")
@ApiOperation(value = "首页所有分布数据", notes = "返回指定设备极值数据支持before筛选")
@ApiOperation(value = "首页所有分布数据", notes = "获取首页大屏的分布统计数据")
public R<HomeDashboardDTO> home(){
HomeDashboardDTO dto = vehicleDataService.getHomeDashboard();
return R.ok(dto);

View File

@ -20,6 +20,8 @@ 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
@ -29,6 +31,7 @@ import com.evobms.framework.web.page.TableDataInfo;
*/
@RestController
@RequestMapping("/VehicleData/VehicleData")
@Api(tags = "整车数据管理")
public class VehicleDataController extends BaseController
{
@Autowired
@ -39,6 +42,7 @@ public class VehicleDataController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:list')")
@GetMapping("/list")
@ApiOperation("查询整车数据列表")
public TableDataInfo list(VehicleData vehicleData)
{
startPage();
@ -52,6 +56,7 @@ public class VehicleDataController extends BaseController
@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);
@ -64,6 +69,7 @@ public class VehicleDataController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:query')")
@GetMapping(value = "/{id}")
@ApiOperation("获取整车数据详细信息")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(vehicleDataService.selectVehicleDataById(id));
@ -75,6 +81,7 @@ public class VehicleDataController extends BaseController
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:add')")
@Log(title = "整车数据", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增整车数据")
public AjaxResult add(@RequestBody VehicleData vehicleData)
{
return toAjax(vehicleDataService.insertVehicleData(vehicleData));
@ -86,6 +93,7 @@ public class VehicleDataController extends BaseController
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:edit')")
@Log(title = "整车数据", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改整车数据")
public AjaxResult edit(@RequestBody VehicleData vehicleData)
{
return toAjax(vehicleDataService.updateVehicleData(vehicleData));
@ -96,7 +104,8 @@ public class VehicleDataController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('VehicleData:VehicleData:remove')")
@Log(title = "整车数据", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@DeleteMapping("/{ids}")
@ApiOperation("删除整车数据")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(vehicleDataService.deleteVehicleDataByIds(ids));

View File

@ -20,6 +20,8 @@ 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
@ -29,6 +31,7 @@ import com.evobms.framework.web.page.TableDataInfo;
*/
@RestController
@RequestMapping("/location/location")
@Api(tags = "车辆位置管理")
public class VehicleLocationController extends BaseController
{
@Autowired
@ -39,6 +42,7 @@ public class VehicleLocationController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('location:location:list')")
@GetMapping("/list")
@ApiOperation("查询车辆位置列表")
public TableDataInfo list(VehicleLocation vehicleLocation)
{
startPage();
@ -52,6 +56,7 @@ public class VehicleLocationController extends BaseController
@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);
@ -64,6 +69,7 @@ public class VehicleLocationController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('location:location:query')")
@GetMapping(value = "/{id}")
@ApiOperation("获取车辆位置详细信息")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(vehicleLocationService.selectVehicleLocationById(id));
@ -75,6 +81,7 @@ public class VehicleLocationController extends BaseController
@PreAuthorize("@ss.hasPermi('location:location:add')")
@Log(title = "车辆位置数据", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增车辆位置")
public AjaxResult add(@RequestBody VehicleLocation vehicleLocation)
{
return toAjax(vehicleLocationService.insertVehicleLocation(vehicleLocation));
@ -86,6 +93,7 @@ public class VehicleLocationController extends BaseController
@PreAuthorize("@ss.hasPermi('location:location:edit')")
@Log(title = "车辆位置数据", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改车辆位置")
public AjaxResult edit(@RequestBody VehicleLocation vehicleLocation)
{
return toAjax(vehicleLocationService.updateVehicleLocation(vehicleLocation));
@ -96,7 +104,8 @@ public class VehicleLocationController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('location:location:remove')")
@Log(title = "车辆位置数据", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@DeleteMapping("/{ids}")
@ApiOperation("删除车辆位置")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(vehicleLocationService.deleteVehicleLocationByIds(ids));

View File

@ -1,18 +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; // 温度分布
}

View File

@ -2,7 +2,11 @@ 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;
@ -14,240 +18,87 @@ import com.evobms.framework.web.domain.BaseEntity;
* @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 = "车辆状态 (1:启动 2:熄火 3:其他 254:异常 255:无效)")
private Integer vehicleStatus;
/** 充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效) */
@ApiModelProperty(value = "充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效)")
@Excel(name = "充电状态 (1:停车充电 2:行驶充电 3:未充电 4:充电完成 254:异常 255:无效)")
private Integer chargingStatus;
/** 运行模式 (1:纯电 2:混动 3:燃油 254:异常 255:无效) */
@ApiModelProperty(value = "运行模式 (1:纯电 2:混动 3:燃油 254:异常 255:无效)")
@Excel(name = "运行模式 (1:纯电 2:混动 3:燃油 254:异常 255:无效)")
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 = "档位 (0:空档 1-6:1-6档 13:倒档 14:自动D档 15:停车P档)")
private Integer gearPosition;
/** 绝缘电阻(kΩ) */
@ApiModelProperty(value = "绝缘电阻(kΩ)")
@Excel(name = "绝缘电阻(kΩ)")
private Integer insulationResistance;
/** 预留字段 */
@ApiModelProperty(value = "预留字段")
@Excel(name = "预留字段")
private String reservedData;
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 setVehicleStatus(Integer vehicleStatus)
{
this.vehicleStatus = vehicleStatus;
}
public Integer getVehicleStatus()
{
return vehicleStatus;
}
public void setChargingStatus(Integer chargingStatus)
{
this.chargingStatus = chargingStatus;
}
public Integer getChargingStatus()
{
return chargingStatus;
}
public void setOperationMode(Integer operationMode)
{
this.operationMode = operationMode;
}
public Integer getOperationMode()
{
return operationMode;
}
public void setVehicleSpeed(BigDecimal vehicleSpeed)
{
this.vehicleSpeed = vehicleSpeed;
}
public BigDecimal getVehicleSpeed()
{
return vehicleSpeed;
}
public void setTotalMileage(BigDecimal totalMileage)
{
this.totalMileage = totalMileage;
}
public BigDecimal getTotalMileage()
{
return totalMileage;
}
public void setTotalVoltage(BigDecimal totalVoltage)
{
this.totalVoltage = totalVoltage;
}
public BigDecimal getTotalVoltage()
{
return totalVoltage;
}
public void setTotalCurrent(BigDecimal totalCurrent)
{
this.totalCurrent = totalCurrent;
}
public BigDecimal getTotalCurrent()
{
return totalCurrent;
}
public void setSoc(Integer soc)
{
this.soc = soc;
}
public Integer getSoc()
{
return soc;
}
public void setDcdcStatus(Integer dcdcStatus)
{
this.dcdcStatus = dcdcStatus;
}
public Integer getDcdcStatus()
{
return dcdcStatus;
}
public void setGearPosition(Integer gearPosition)
{
this.gearPosition = gearPosition;
}
public Integer getGearPosition()
{
return gearPosition;
}
public void setInsulationResistance(Integer insulationResistance)
{
this.insulationResistance = insulationResistance;
}
public Integer getInsulationResistance()
{
return insulationResistance;
}
public void setReservedData(String reservedData)
{
this.reservedData = reservedData;
}
public String getReservedData()
{
return reservedData;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("timestamp", getTimestamp())
.append("vehicleStatus", getVehicleStatus())
.append("chargingStatus", getChargingStatus())
.append("operationMode", getOperationMode())
.append("vehicleSpeed", getVehicleSpeed())
.append("totalMileage", getTotalMileage())
.append("totalVoltage", getTotalVoltage())
.append("totalCurrent", getTotalCurrent())
.append("soc", getSoc())
.append("dcdcStatus", getDcdcStatus())
.append("gearPosition", getGearPosition())
.append("insulationResistance", getInsulationResistance())
.append("reservedData", getReservedData())
.toString();
}
}

View File

@ -3,7 +3,11 @@ 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;
@ -15,23 +19,29 @@ import com.evobms.framework.web.domain.BaseEntity;
* @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;
@ -39,79 +49,21 @@ public class VehicleLocation extends BaseEntity {
/**
* 定位状态 (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;
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 setPositioningStatus(Integer positioningStatus) {
this.positioningStatus = positioningStatus;
}
public Integer getPositioningStatus() {
return positioningStatus;
}
public void setLongitude(BigDecimal longitude) {
this.longitude = longitude;
}
public BigDecimal getLongitude() {
return longitude;
}
public void setLatitude(BigDecimal latitude) {
this.latitude = latitude;
}
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();
}
}

View File

@ -6,7 +6,7 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/evo_bms1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://192.168.5.121:3306/evo_bms1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: root
# 从库数据源

View File

@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器HTTP端口支持环境变量覆盖SERVER_PORT默认8080
port: ${SERVER_PORT:8080}
port: ${SERVER_PORT:8011}
servlet:
# 应用的访问路径
context-path: /

View File

@ -1,24 +1,10 @@
Application Version: ${ruoyi.version}
Application Version: ${ruoyi-vue-plus.version}
Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////
_______ _______ _________ _______ _______
( ____ \|\ /|( ___ )\__ __/( ____ \( ____ \|\ /|
| ( \/| ) ( || ( ) | ) ( | ( \/| ( \/| ) ( |
| (__ | | | || | | | | | | (__ | | | (___) |
| __) ( ( ) )| | | | | | | __) | | | ___ |
| ( \ \_/ / | | | | | | | ( | | | ( ) |
| (____/\ \ / | (___) | | | | (____/\| (____/\| ) ( |
(_______/ \_/ (_______) )_( (_______/(_______/|/ \|

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.evobms.project.bms.mapper.BmsChargeDetailMapper">
<resultMap type="com.evobms.project.bms.domain.BmsChargeDetail" id="BmsChargeDetailResult">
<result property="id" column="id"/>
<result property="deviceId" column="device_id"/>
<result property="timestamp" column="timestamp"/>
<result property="acChargeCurrent" column="ac_charge_current"/>
<result property="acChargeVoltage" column="ac_charge_voltage"/>
<result property="dcChargeCurrent" column="dc_charge_current"/>
<result property="dcChargeVoltage" column="dc_charge_voltage"/>
<result property="chargeTime" column="charge_time"/>
<result property="acStopCode" column="ac_stop_code"/>
<result property="dcStopCode" column="dc_stop_code"/>
<result property="acCpValue" column="ac_cp_value"/>
<result property="acGunResistance" column="ac_gun_resistance"/>
<result property="chargingStage" column="charging_stage"/>
<result property="acStage" column="ac_stage"/>
<result property="dcStage" column="dc_stage"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<insert id="insertBmsChargeDetail" parameterType="com.evobms.project.bms.domain.BmsChargeDetail" useGeneratedKeys="true" keyProperty="id">
insert into bms_charge_detail
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">device_id,</if>
<if test="timestamp != null">timestamp,</if>
<if test="acChargeCurrent != null">ac_charge_current,</if>
<if test="acChargeVoltage != null">ac_charge_voltage,</if>
<if test="dcChargeCurrent != null">dc_charge_current,</if>
<if test="dcChargeVoltage != null">dc_charge_voltage,</if>
<if test="chargeTime != null">charge_time,</if>
<if test="acStopCode != null">ac_stop_code,</if>
<if test="dcStopCode != null">dc_stop_code,</if>
<if test="acCpValue != null">ac_cp_value,</if>
<if test="acGunResistance != null">ac_gun_resistance,</if>
<if test="chargingStage != null">charging_stage,</if>
<if test="acStage != null">ac_stage,</if>
<if test="dcStage != null">dc_stage,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
<if test="timestamp != null">#{timestamp},</if>
<if test="acChargeCurrent != null">#{acChargeCurrent},</if>
<if test="acChargeVoltage != null">#{acChargeVoltage},</if>
<if test="dcChargeCurrent != null">#{dcChargeCurrent},</if>
<if test="dcChargeVoltage != null">#{dcChargeVoltage},</if>
<if test="chargeTime != null">#{chargeTime},</if>
<if test="acStopCode != null">#{acStopCode},</if>
<if test="dcStopCode != null">#{dcStopCode},</if>
<if test="acCpValue != null">#{acCpValue},</if>
<if test="acGunResistance != null">#{acGunResistance},</if>
<if test="chargingStage != null">#{chargingStage},</if>
<if test="acStage != null">#{acStage},</if>
<if test="dcStage != null">#{dcStage},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
</trim>
</insert>
</mapper>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.evobms.project.bms.mapper.BmsSopDataMapper">
<resultMap type="com.evobms.project.bms.domain.BmsSopData" id="BmsSopDataResult">
<result property="id" column="id"/>
<result property="deviceId" column="device_id"/>
<result property="timestamp" column="timestamp"/>
<result property="dischargeSop10s" column="discharge_sop_10s"/>
<result property="dischargeSop30s" column="discharge_sop_30s"/>
<result property="dischargeSop60s" column="discharge_sop_60s"/>
<result property="dischargeSopContinuous" column="discharge_sop_continuous"/>
<result property="regenSop10s" column="regen_sop_10s"/>
<result property="regenSop30s" column="regen_sop_30s"/>
<result property="regenSop60s" column="regen_sop_60s"/>
<result property="regenSopContinuous" column="regen_sop_continuous"/>
<result property="chargeSop" column="charge_sop"/>
<result property="acChargeSop" column="ac_charge_sop"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<insert id="insertBmsSopData" parameterType="com.evobms.project.bms.domain.BmsSopData" useGeneratedKeys="true" keyProperty="id">
insert into bms_sop_data
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">device_id,</if>
<if test="timestamp != null">timestamp,</if>
<if test="dischargeSop10s != null">discharge_sop_10s,</if>
<if test="dischargeSop30s != null">discharge_sop_30s,</if>
<if test="dischargeSop60s != null">discharge_sop_60s,</if>
<if test="dischargeSopContinuous != null">discharge_sop_continuous,</if>
<if test="regenSop10s != null">regen_sop_10s,</if>
<if test="regenSop30s != null">regen_sop_30s,</if>
<if test="regenSop60s != null">regen_sop_60s,</if>
<if test="regenSopContinuous != null">regen_sop_continuous,</if>
<if test="chargeSop != null">charge_sop,</if>
<if test="acChargeSop != null">ac_charge_sop,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
<if test="timestamp != null">#{timestamp},</if>
<if test="dischargeSop10s != null">#{dischargeSop10s},</if>
<if test="dischargeSop30s != null">#{dischargeSop30s},</if>
<if test="dischargeSop60s != null">#{dischargeSop60s},</if>
<if test="dischargeSopContinuous != null">#{dischargeSopContinuous},</if>
<if test="regenSop10s != null">#{regenSop10s},</if>
<if test="regenSop30s != null">#{regenSop30s},</if>
<if test="regenSop60s != null">#{regenSop60s},</if>
<if test="regenSopContinuous != null">#{regenSopContinuous},</if>
<if test="chargeSop != null">#{chargeSop},</if>
<if test="acChargeSop != null">#{acChargeSop},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
</trim>
</insert>
</mapper>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.evobms.project.bms.mapper.BmsSystemStatusMapper">
<resultMap type="com.evobms.project.bms.domain.BmsSystemStatus" id="BmsSystemStatusResult">
<result property="id" column="id"/>
<result property="deviceId" column="device_id"/>
<result property="timestamp" column="timestamp"/>
<result property="relayStatus" column="relay_status"/>
<result property="onaaccStatus" column="onaacc_status"/>
<result property="resetCount" column="reset_count"/>
<result property="cycleCount" column="cycle_count"/>
<result property="sample25v" column="sample_25v"/>
<result property="sample5v" column="sample_5v"/>
<result property="cellCount" column="cell_count"/>
<result property="tempSensorCount" column="temp_sensor_count"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="createBy" column="create_by"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<insert id="insertBmsSystemStatus" parameterType="com.evobms.project.bms.domain.BmsSystemStatus" useGeneratedKeys="true" keyProperty="id">
insert into bms_system_status
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">device_id,</if>
<if test="timestamp != null">timestamp,</if>
<if test="relayStatus != null">relay_status,</if>
<if test="onaaccStatus != null">onaacc_status,</if>
<if test="resetCount != null">reset_count,</if>
<if test="cycleCount != null">cycle_count,</if>
<if test="sample25v != null">sample_25v,</if>
<if test="sample5v != null">sample_5v,</if>
<if test="cellCount != null">cell_count,</if>
<if test="tempSensorCount != null">temp_sensor_count,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
<if test="timestamp != null">#{timestamp},</if>
<if test="relayStatus != null">#{relayStatus},</if>
<if test="onaaccStatus != null">#{onaaccStatus},</if>
<if test="resetCount != null">#{resetCount},</if>
<if test="cycleCount != null">#{cycleCount},</if>
<if test="sample25v != null">#{sample25v},</if>
<if test="sample5v != null">#{sample5v},</if>
<if test="cellCount != null">#{cellCount},</if>
<if test="tempSensorCount != null">#{tempSensorCount},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
</trim>
</insert>
</mapper>

File diff suppressed because one or more lines are too long

Binary file not shown.