From adbb9a16f49797c2f0b337ed15169b4df36269be Mon Sep 17 00:00:00 2001 From: xy <748613696@qq.com> Date: Wed, 14 Aug 2024 21:07:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../njcn/access/pojo/dto/UploadFileDto.java | 4 ++ .../service/impl/CsDevModelServiceImpl.java | 38 +++++++++----- .../com/njcn/access/utils/CRC32Utils.java | 52 +++++++++++++++++++ 3 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 iot-access/access-boot/src/main/java/com/njcn/access/utils/CRC32Utils.java diff --git a/iot-access/access-api/src/main/java/com/njcn/access/pojo/dto/UploadFileDto.java b/iot-access/access-api/src/main/java/com/njcn/access/pojo/dto/UploadFileDto.java index 80b3dd5..b2a4835 100644 --- a/iot-access/access-api/src/main/java/com/njcn/access/pojo/dto/UploadFileDto.java +++ b/iot-access/access-api/src/main/java/com/njcn/access/pojo/dto/UploadFileDto.java @@ -30,4 +30,8 @@ public class UploadFileDto { @ApiModelProperty("文件包数据") private String data; + @SerializedName("FileCheck") + @ApiModelProperty("文件校验码") + private String fileCheck; + } diff --git a/iot-access/access-boot/src/main/java/com/njcn/access/service/impl/CsDevModelServiceImpl.java b/iot-access/access-boot/src/main/java/com/njcn/access/service/impl/CsDevModelServiceImpl.java index b2752ae..010371b 100644 --- a/iot-access/access-boot/src/main/java/com/njcn/access/service/impl/CsDevModelServiceImpl.java +++ b/iot-access/access-boot/src/main/java/com/njcn/access/service/impl/CsDevModelServiceImpl.java @@ -17,6 +17,7 @@ import com.njcn.access.pojo.dto.devModel.*; import com.njcn.access.pojo.dto.file.FileRedisDto; import com.njcn.access.pojo.po.CsLineModel; import com.njcn.access.service.*; +import com.njcn.access.utils.CRC32Utils; import com.njcn.access.utils.JsonUtil; import com.njcn.common.pojo.dto.DeviceLogDTO; import com.njcn.common.pojo.exception.BusinessException; @@ -37,6 +38,7 @@ import com.njcn.system.pojo.vo.DictTreeVO; import com.njcn.web.utils.RequestUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.encoders.Hex; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -152,10 +154,19 @@ public class CsDevModelServiceImpl implements ICsDevModelService { } } + + public static void main(String[] args) { + + } @Override public void uploadDevFile(MultipartFile file,String id,String path) { DeviceLogDTO logDto = null; try { + byte[] bytes = file.getBytes(); + int length = bytes.length; + //生成文件校验码 + int crc = CRC32Utils.calculateCRC32(bytes,length,0xffffffff); + String hexString = String.format("%08X", crc); //判断nDid是否存在 CsEquipmentDeliveryVO csEquipmentDeliveryVO = csEquipmentDeliveryService.queryEquipmentBynDid(id); logDto = new DeviceLogDTO(); @@ -172,61 +183,59 @@ public class CsDevModelServiceImpl implements ICsDevModelService { //获取版本 String version = csTopicService.getVersion(id); int cap = 50 * 1024; - byte[] bytes = file.getBytes(); - int length = bytes.length; //需要分片处理 一帧按50k大小传递 if (length > cap){ //需要循环的次数 int times = bytes.length / cap + 1; for (int i = 1; i <= times; i++) { - FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep"); byte[] lsBytes; if (length > 50*1024) { lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, i * cap); - ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap); + ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap,hexString); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); logDto.setOperate(id + "设备上送文件,这是第" + i + "帧"); logDto.setResult(1); length = length - cap; //判断是否重发 - sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i); + sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i,hexString); + FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep"); //重发之后判断继续循环还是跳出循环 if (!Objects.equals(fileRedisDto.getCode(),200)) { break; } } else { lsBytes = Arrays.copyOfRange(bytes, (i - 1) * cap, bytes.length); - ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap); + ReqAndResDto.Req req = getPojo(i,path,file,bytes.length,lsBytes,(i-1)*cap,hexString); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); logDto.setOperate(id + "设备上送文件,这是最后一帧,为第" + i + "帧"); logDto.setResult(1); //判断是否重发 - sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i); + sendNextStep(logDto,path,file,bytes.length,lsBytes,(i-1)*cap,version,id,i,hexString); } csLogsFeignClient.addUserLog(logDto); } } else { - ReqAndResDto.Req req = getPojo(1,path,file,length,bytes,0); + ReqAndResDto.Req req = getPojo(1,path,file,length,bytes,0,hexString); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); logDto.setOperate(id + "系统上送文件,当前文件只有1帧"); logDto.setResult(1); csLogsFeignClient.addUserLog(logDto); //判断是否重发 - sendNextStep(logDto,path,file,length,bytes,0,version,id,1); + sendNextStep(logDto,path,file,length,bytes,0,version,id,1,hexString); } } catch (Exception e) { assert logDto != null; logDto.setResult(0); logDto.setFailReason(AccessResponseEnum.UPLOAD_ERROR.getMessage()); csLogsFeignClient.addUserLog(logDto); - throw new RuntimeException(e); + throw new BusinessException(AccessResponseEnum.UPLOAD_ERROR); } } /** * 上送文件至装置 */ - public ReqAndResDto.Req getPojo(Integer mid, String path, MultipartFile file, Integer allLength, byte[] bytes, Integer offset) { + public ReqAndResDto.Req getPojo(Integer mid, String path, MultipartFile file, Integer allLength, byte[] bytes, Integer offset, String fileCheck) { //组装报文 ReqAndResDto.Req reqAndResParam = new ReqAndResDto.Req(); reqAndResParam.setMid(mid); @@ -240,6 +249,7 @@ public class CsDevModelServiceImpl implements ICsDevModelService { uploadFileDto.setOffset(offset); uploadFileDto.setLen(bytes.length); uploadFileDto.setData(Base64.getEncoder().encodeToString(bytes)); + uploadFileDto.setFileCheck(fileCheck); reqAndResParam.setMsg(uploadFileDto); return reqAndResParam; } @@ -247,17 +257,17 @@ public class CsDevModelServiceImpl implements ICsDevModelService { /** * 根据装置响应来判断发送的内容 */ - public void sendNextStep(DeviceLogDTO logDto, String path, MultipartFile file, int length, byte[] bytes, Integer offset, String version, String id, int mid) { + public void sendNextStep(DeviceLogDTO logDto, String path, MultipartFile file, int length, byte[] bytes, Integer offset, String version, String id, int mid, String fileCheck) { try { for (int i = 0; i < 3; i++) { - Thread.sleep(100); + Thread.sleep(300); FileRedisDto fileRedisDto = (FileRedisDto) redisUtil.getObjectByKey("uploadFileStep"); FileRedisDto fileRedis = new FileRedisDto(); if (Objects.nonNull(fileRedisDto.getCode()) && fileRedisDto.getCode().equals(200)) { fileRedis.setCode(200); break; } else { - ReqAndResDto.Req req = getPojo(mid,path,file,length,bytes,offset); + ReqAndResDto.Req req = getPojo(mid,path,file,length,bytes,offset,fileCheck); publisher.send("/Pfm/DevFileCmd/" + version + "/" + id, new Gson().toJson(req), 1, false); logDto.setOperate(id + "系统上送文件,装置响应失败,重新发送,这是第" + (i+1) + "次"); logDto.setResult(1); diff --git a/iot-access/access-boot/src/main/java/com/njcn/access/utils/CRC32Utils.java b/iot-access/access-boot/src/main/java/com/njcn/access/utils/CRC32Utils.java new file mode 100644 index 0000000..d369109 --- /dev/null +++ b/iot-access/access-boot/src/main/java/com/njcn/access/utils/CRC32Utils.java @@ -0,0 +1,52 @@ +package com.njcn.access.utils; + +/** + * @author xy + */ +public class CRC32Utils { + + // CRC-32/MPEG-2 多项式, x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 + private static final int POLYNOMIAL = 0x04C11DB7; + + public static int calculateCRC32(byte[] buf, int len, int seed) { + if (buf == null || len <= 0) { + return seed; + } + + int crc = seed; + int count = 0; + // 对长度进行填充以适应32位整数 + int rem = len % Integer.BYTES; + if (rem > 0) { + int n = Integer.BYTES - rem; + byte[] newBuf = new byte[len + n]; + System.arraycopy(buf, 0, newBuf, 0, len); + // 填充字节用0xFF + for (int i = len; i < len + n; i++) { + newBuf[i] = (byte) 0xFF; + } + buf = newBuf; + len += n; + } + + int uiCount = len / Integer.BYTES; + for (int k = 0; k < uiCount; k++) { + int uiTemp = 0; + for (int i = 0; i < Integer.BYTES; i++) { + uiTemp |= (buf[k * Integer.BYTES + i] & 0xFF) << (8 * (3 - i)); + } + for (int j = 0; j < 32; j++) { + // 检查最高位是否为1 + if ((crc ^ uiTemp) < 0) { + crc = 0x04C11DB7 ^ (crc << 1); + count ++; + } else { + crc <<= 1; + } + uiTemp <<= 1; + } + } + return crc; + } + +}