Compare commits

...

2 Commits

Author SHA256 Message Date
25e6c79b4c Merge remote-tracking branch 'origin/main' 2025-11-19 10:55:49 +08:00
b7349fd7b0 远程升级 2025-11-19 10:55:39 +08:00
9 changed files with 173 additions and 30 deletions

View File

@ -3,11 +3,11 @@ package com.cdzy.operations.controller;
import com.cdzy.common.enums.Message;
import com.cdzy.common.model.request.PageParam;
import com.cdzy.common.model.response.JsonResult;
import com.cdzy.operations.enums.CommandType;
import com.cdzy.operations.model.dto.EbikeEcuInOverview;
import com.cdzy.operations.model.entity.EbikeEcuInfo;
import com.cdzy.operations.model.vo.EbikeEcuInfoBatchVo;
import com.cdzy.operations.model.vo.EbikeEcuInfoVo;
import com.cdzy.operations.model.vo.EbikeEcuUpgradeVo;
import com.cdzy.operations.service.EbikeEcuInfoService;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
@ -170,9 +170,9 @@ public class EbikeEcuInfoController {
*
* @return 执行结构
*/
@GetMapping("upgrade")
public JsonResult<?> upgrade(String ecuSn,String bikeCode,@NotNull(message = "远程文件地址不能为空") String url) {
boolean result = ebikeEcuInfoService.executeCommand(ecuSn,bikeCode, CommandType.UPGRADE,url);
@PostMapping("upgrade")
public JsonResult<?> upgrade(@Validated @RequestBody EbikeEcuUpgradeVo upgradeVo) {
boolean result = ebikeEcuInfoService.upgrade(upgradeVo);
return JsonResult.success(result);
}

View File

@ -50,4 +50,9 @@ public interface CommandType {
* 升级
*/
String UPGRADE = "UPGRADE";
/**
* 更新语音播报
*/
String UPGRADE_AUDIO = "UPGRADE_AUDIO";
}

View File

@ -0,0 +1,51 @@
package com.cdzy.operations.model.vo;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author attiya
* @since 2025-11-19
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EbikeEcuUpgradeVo {
/**
* 中控编号
*/
String ecuSn;
/**
* 车辆编号
*/
String bikeCode;
/**
* 中控品牌
*/
private Integer ecuBrand;
/**
* 文件地址
*/
@NotNull(message = "远程文件地址不能为空")
String url;
/**
* 升级类型
*/
@NotNull(message = "升级类型不能为空")
Integer type;
/**
* 全部升级true时所有中控都会升级
*/
@NotNull(message = "是否全部升级不能为空")
Boolean fullUpgrade;
}

View File

@ -79,5 +79,14 @@ public interface CommandService{
* @param ebikeEcuInfo 中控信息
* @return 执行结果
*/
boolean upgrade(EbikeEcuInfo ebikeEcuInfo,String url);
boolean upgrade(EbikeEcuInfo ebikeEcuInfo,String url,Boolean fullUpgrade);
/**
* 升级/更换音频
* @param ebikeEcuInfo 中控信息
* @param url 文件路径
* @param idx 所升级音频编号
* @return 执行结果
*/
boolean upgradeAudio(EbikeEcuInfo ebikeEcuInfo, String url, Integer idx,Boolean fullUpgrade);
}

View File

@ -3,6 +3,7 @@ package com.cdzy.operations.service;
import com.cdzy.operations.model.dto.EbikeEcuInOverview;
import com.cdzy.operations.model.vo.EbikeEcuInfoBatchVo;
import com.cdzy.operations.model.vo.EbikeEcuInfoVo;
import com.cdzy.operations.model.vo.EbikeEcuUpgradeVo;
import com.mybatisflex.core.service.IService;
import com.cdzy.operations.model.entity.EbikeEcuInfo;
import org.springframework.web.multipart.MultipartFile;
@ -126,15 +127,22 @@ public interface EbikeEcuInfoService extends IService<EbikeEcuInfo> {
EbikeEcuInfo getEcu(String bikeCode);
/**
* 远程升级
* 远程升级中控
* @param ebikeEcuInfo 中控信息
* @return 结果
*/
boolean upgrade(EbikeEcuInfo ebikeEcuInfo,String url);
boolean upgradeFile(EbikeEcuInfo ebikeEcuInfo,String url,Boolean fullUpgrade);
/**
* 上传远程升级
* @param file 文件对象
*/
String upload(MultipartFile file) throws Exception;
/**
* 远程升级
* @param upgradeVoe 升级信息
* @return 操作结果
*/
boolean upgrade(EbikeEcuUpgradeVo upgradeVoe);
}

View File

@ -40,7 +40,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.FIND_BIKE,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.FIND_BIKE,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -57,7 +57,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.GPS,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.GPS,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -74,7 +74,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.OPEN_BATTERY_LOCK,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.OPEN_BATTERY_LOCK,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -91,7 +91,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.CLOSE_BATTERY_LOCK,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.CLOSE_BATTERY_LOCK,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -108,7 +108,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.LOCK,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.LOCK,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -125,7 +125,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.UNLOCK,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.UNLOCK,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -147,7 +147,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.OPEN_HELMET,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.OPEN_HELMET,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -164,7 +164,7 @@ public class CommandServiceImpl implements CommandService {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.POWER_OFF,null);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.POWER_OFF,null,null,false);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -175,13 +175,34 @@ public class CommandServiceImpl implements CommandService {
}
@Override
public boolean upgrade(EbikeEcuInfo ebikeEcuInfo,String url) {
public boolean upgrade(EbikeEcuInfo ebikeEcuInfo,String url,Boolean fullUpgrade) {
String taskId = createTaskId();
String ecuSn = null;
if (!fullUpgrade) {
ecuSn = ebikeEcuInfo.getEcuSn();
}
switch (ebikeEcuInfo.getEcuBrand()) {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong( ecuSn, taskId, CommandType.UPGRADE,url,null,fullUpgrade);
} catch (Exception e) {
throw new RuntimeException(e);
}
return submitTaskAndWait(topic, taskId, command);
default:
throw new EbikeException("该品牌中控暂未接入");
}
}
@Override
public boolean upgradeAudio(EbikeEcuInfo ebikeEcuInfo, String url, Integer idx,Boolean fullUpgrade) {
String taskId = createTaskId();
switch (ebikeEcuInfo.getEcuBrand()) {
case EcuBrand.GUANG_HE_TONG:
String command;
try {
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.UPGRADE,url);
command = CommandUtil.guang_he_tong(ebikeEcuInfo.getEcuSn(), taskId, CommandType.UPGRADE_AUDIO,url,idx,fullUpgrade);
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@ -9,6 +9,7 @@ import com.cdzy.operations.model.dto.EbikeEcuInOverview;
import com.cdzy.operations.model.entity.EbikeBikeInfo;
import com.cdzy.operations.model.vo.EbikeEcuInfoBatchVo;
import com.cdzy.operations.model.vo.EbikeEcuInfoVo;
import com.cdzy.operations.model.vo.EbikeEcuUpgradeVo;
import com.cdzy.operations.service.CommandService;
import com.cdzy.operations.utils.EmqxApiClient;
import com.cdzy.operations.utils.MinioUtil;
@ -174,17 +175,49 @@ public class EbikeEcuInfoServiceImpl extends ServiceImpl<EbikeEcuInfoMapper, Ebi
}
@Override
public boolean upgrade(EbikeEcuInfo ebikeEcuInfo, String url) {
return commandService.upgrade(ebikeEcuInfo, url);
public boolean upgradeFile(EbikeEcuInfo ebikeEcuInfo, String url, Boolean fullUpgrade) {
return commandService.upgrade(ebikeEcuInfo, url, fullUpgrade);
}
@Override
public String upload(MultipartFile file) throws Exception {
String objectName = upgradeUrl + UUID.randomUUID().toString().replace("-", "") + FileNameUtil.extName(file.getOriginalFilename());
minioUtil.uploadFile(file.getInputStream() , objectName);
String objectName = upgradeUrl + UUID.randomUUID().toString().replace("-", "") + "." + FileNameUtil.extName(file.getOriginalFilename());
minioUtil.uploadFile(file.getInputStream(), objectName);
return minioUtil.getShowUrl(objectName);
}
@Override
public boolean upgrade(EbikeEcuUpgradeVo upgradeVo) {
String ecuSn = upgradeVo.getEcuSn();
String bikeCode = upgradeVo.getBikeCode();
String url = upgradeVo.getUrl();
Integer type = upgradeVo.getType();
EbikeEcuInfo ebikeEcuInfo = new EbikeEcuInfo();
if (!upgradeVo.getFullUpgrade()) {
check(ecuSn, bikeCode);
if (StringUtil.hasText(ecuSn)) {
ebikeEcuInfo = checkEcuSn(ecuSn);
} else {
ebikeEcuInfo = getEcu(bikeCode);
}
} else {
Integer ecuBrand = upgradeVo.getEcuBrand();
if (ecuBrand == null) {
throw new EbikeException("全部升级时中控品牌不能为空");
}
ebikeEcuInfo.setEcuBrand(ecuBrand);
}
if (type == 12) {
return upgradeFile(ebikeEcuInfo, url, upgradeVo.getFullUpgrade());
} else {
return upgradeAudio(ebikeEcuInfo, url, type, upgradeVo.getFullUpgrade());
}
}
public boolean upgradeAudio(EbikeEcuInfo ebikeEcuInfo, String url, Integer idx, Boolean fullUpgrade) {
return commandService.upgradeAudio(ebikeEcuInfo, url, idx, fullUpgrade);
}
@Override
public boolean checkSnOrBikeCode(String ecuSn, String bikeCode) {
try {
@ -218,7 +251,7 @@ public class EbikeEcuInfoServiceImpl extends ServiceImpl<EbikeEcuInfoMapper, Ebi
case CommandType.UNLOCK -> unLock(ebikeEcuInfo);
case CommandType.OPEN_HELMET -> openHelmet(ebikeEcuInfo);
case CommandType.POWER_OFF -> powerOff(ebikeEcuInfo);
case CommandType.UPGRADE -> upgrade(ebikeEcuInfo, url);
case CommandType.UPGRADE -> upgradeFile(ebikeEcuInfo, url, false);
default -> throw new EbikeException("该命令不存在/未接入");
};
}

View File

@ -17,14 +17,18 @@ import java.io.IOException;
public class CommandUtil {
private static final ObjectMapper mapper = new ObjectMapper();
private static final String prefix = "ecu/cmd/cdzybms/";
private static final String guang_he_tong_prefix = "ecu/cmd/cdzybms/";
private static final String guang_he_tong_broadcast = "ecu/cmd/cdzybms/broadcast";
public static String guang_he_tong(String ecuSn, String taskId, String code,String url) throws IOException {
String topic = prefix + ecuSn;
public static String guang_he_tong(String ecuSn, String taskId, String code, String url, Integer idx, Boolean fullUpgrade) throws IOException {
String topic = guang_he_tong_prefix + ecuSn;
ObjectNode jsonNode = mapper.createObjectNode();
if (fullUpgrade) {
topic = guang_he_tong_broadcast;
}
jsonNode.put("topic", topic);
switch (code) {
case CommandType.FIND_BIKE:
String command_14 = "{\"c\":14,\"tid\":\"" + taskId + "\",\"param\":{\"volume\":50,\"idx\":5}}";
@ -53,27 +57,32 @@ public class CommandUtil {
break;
case CommandType.LOCK:
String command_4 = "{\"c\":4,\"tid\":\""+taskId+"\",\"param\":{\"defend\":1,\"idx\":14,\"isTBeacon\":0}}";
String command_4 = "{\"c\":4,\"tid\":\"" + taskId + "\",\"param\":{\"defend\":1,\"idx\":14,\"isTBeacon\":0}}";
ObjectNode objectNode_4 = mapper.readValue(command_4, ObjectNode.class);
jsonNode.put("command", objectNode_4.toString());
break;
case CommandType.OPEN_HELMET:
String command_89 = "{\"tid\":\""+taskId+"\",\"c\":89,\"param\":{\"opt\":0}}";
String command_89 = "{\"tid\":\"" + taskId + "\",\"c\":89,\"param\":{\"opt\":0}}";
ObjectNode objectNode_89 = mapper.readValue(command_89, ObjectNode.class);
jsonNode.put("command", objectNode_89.toString());
break;
case CommandType.POWER_OFF:
String command_100 = "{\"c\":100,\"tid\":\""+taskId+"\",\"param\":{\"Dsg\":0}}";
String command_100 = "{\"c\":100,\"tid\":\"" + taskId + "\",\"param\":{\"Dsg\":0}}";
ObjectNode objectNode_100 = mapper.readValue(command_100, ObjectNode.class);
jsonNode.put("command", objectNode_100.toString());
break;
case CommandType.UPGRADE:
File tempFile = RemoteFileUtils.getRemoteFile(url);
long size = FileUtil.size(tempFile);
String command_35 = "{\"tid\":\""+taskId+"\",\"c\":35,\"param\":{\"len\":"+size+",\"url\":\""+url+"\"}}";
String command_35 = "{\"tid\":\"" + taskId + "\",\"c\":35,\"param\":{\"len\":" + size + ",\"url\":\"" + url + "\"}}";
ObjectNode objectNode_35 = mapper.readValue(command_35, ObjectNode.class);
jsonNode.put("command", objectNode_35.toString());
break;
case CommandType.UPGRADE_AUDIO:
String command_30 = "{\"tid\":\"" + taskId + "\",\"c\":30,\"param\":{\"idx\":" + idx + ",\"url\":\"" + url + "\",\"default\":0}}";
ObjectNode objectNode_30 = mapper.readValue(command_30, ObjectNode.class);
jsonNode.put("command", objectNode_30.toString());
break;
default:
throw new EbikeException("该命令暂未接入");
}

View File

@ -45,9 +45,16 @@ public class ReoprtHandler {
case 66:
bmsMsgHandler(param, deviceId);
break;
case 42:
upgradeMsgHandler(param, deviceId);
break;
}
}
private void upgradeMsgHandler(JsonNode param, String deviceId) {
//TODO生成远程升级记录
}
public void gpsMsgHandler(JsonNode param, String deviceId) {
int number = param.get("sw").asInt();
String binary = BinaryUtil.to32BitBinary(number);