package com.yeechart.dotMatrix.signage; import com.yeechart.dotMatrix.canvas.DotMatrixConversionUtil; import com.yeechart.dotMatrix.crc.CustomCRC32Util; import com.yeechart.dotMatrix.minilzo.MiniLZO; import com.yeechart.dotMatrix.minilzo.MiniLZOUtil; import com.yeechart.dotMatrix.minilzo.bean.MInt; import com.yeechart.dotMatrix.oss.LatticeOSSUpload; import com.yeechart.dotMatrix.oss.OSSUpload; import com.yeechart.dotMatrix.signage.bean.mizilzo.BitmapDataVo; import com.yeechart.dotMatrix.signage.bean.mizilzo.MiniLZOVo; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import com.yeechart.dotMatrix.util.OtherUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Collectors; /** * 对 点阵图 文件操作 */ @Component public class SignageFileUtil { /** * 终端类总路径名称 */ public static final String ROOT_FILE_NAME = "Device/"; /** * 默认的文件名称 */ public static final String ROOT_FILE_TYPE_NAME = ".txt"; public static String fileName = "device/020201/lattice/";//路径; protected static Logger logger = LoggerFactory.getLogger(SignageFileUtil.class); //private ThreadPoolExecutor threadPoolTaskExecutor = ThreadPoolTaskExecutor.getInstance().getThreadPoolExecutor(); @javax.annotation.Resource private ThreadPoolTaskExecutor threadPoolTaskExecutor; @Autowired private LatticeOSSUpload latticeOSSUpload; @Autowired private OSSUpload ossUpload; /** * 获取最新的点阵图文件对象 * * @param dId 设备ID * @param typeCode 功能code * @param isDefault 是否是默认图 * @return */ public BitmapDataVo getLastBitmapDataVo(String dId, String typeCode, boolean isDefault) { if (isDefault) { typeCode = "D" + typeCode; } String url = "http://" + ossUpload.getEndpoint() + "/" + fileName + dId + "/" + typeCode; BitmapDataVo bitmapDataVo = new BitmapDataVo(); bitmapDataVo.setTypeCode(typeCode); bitmapDataVo.setPath(url); return getFileBitmapArrays(bitmapDataVo); } /** * 删除点阵图 * @param dId 设备ID */ public void deleteSignageDotMatrix(String dId){ String url = "http://" + ossUpload.getEndpoint() + "/" + fileName + dId ; latticeOSSUpload.deleteFolderAndSubFolders(url); } /** * 从 指定路径中,获取对应的文件夹数据,并解压数据合并为原始数据 * * @return */ public BitmapDataVo getFileBitmapArrays(BitmapDataVo bitmapDataVo) { try { Map fileMap = new HashMap<>(); CompletableFuture> completableFuture = latticeOSSUpload.listFilesByPath(bitmapDataVo.getPath()); fileMap = completableFuture.get(); if (fileMap.isEmpty()) { return null; } //排序 List> entries = new ArrayList<>(fileMap.entrySet()); Map sizeMap = new HashMap<>(); // 定义比较器,根据文件名最后两位数字进行排序 entries.sort((entry1, entry2) -> { String name1 = entry1.getKey(); String name2 = entry2.getKey(); int lastDotIndex = name1.lastIndexOf('.'); name1 = name1.substring(0, lastDotIndex); lastDotIndex = name2.lastIndexOf('.'); name2 = name2.substring(0, lastDotIndex); int a1 = Integer.parseInt(name1.substring(name1.length() - 2)); int a2 = Integer.parseInt(name2.substring(name2.length() - 2)); return Integer.compare(a1, a2); }); // 根据排序后的列表构造一个新的LinkedHashMap,以保持排序顺序 Map sortedMap = new LinkedHashMap<>(); for (Map.Entry entry : entries) { String name = entry.getKey(); sortedMap.put(name, entry.getValue()); //获取文件路径中的图的原始数据大小 if (!sizeMap.containsKey(name)) { String sum = name.substring(0, name.lastIndexOf('/')); sizeMap.put(name, Integer.parseInt(sum)); } } //整图的原始数据的大小 sizeMap 的value 总和 String fileName = null; Integer ogSize = null; byte[] data = new byte[sizeMap.values().stream().mapToInt(Integer::intValue).sum()]; int length = 0; Map miniLZOVoList = new HashMap<>(); for (Map.Entry entry : sortedMap.entrySet()) { fileName = entry.getKey(); ogSize = Integer.parseInt(fileName.substring(0, fileName.lastIndexOf('/'))); byte[] dataBytes = entry.getValue(); //解压缩 byte[] dataBytes2 = new byte[ogSize]; MInt outL2 = new MInt(); MiniLZO.lzo1x_decompress(dataBytes, ogSize, dataBytes2, outL2); // logger.info("解压缩后的长度 outLen len:" +outL2.v); System.arraycopy(dataBytes2, 0, data, length, outL2.v); MiniLZOVo miniLZOVo = new MiniLZOVo(); miniLZOVo.setOgSize(ogSize); miniLZOVo.setData(dataBytes); miniLZOVo.setCrc32(CustomCRC32Util.calculateCRC32(dataBytes2)); miniLZOVoList.put(fileName, miniLZOVo); length = length + ogSize; } // byte[] dataBytes33 = new byte[4]; // System.arraycopy(data,data.length-4,dataBytes33,0,4); byte[] dataBytes3 = new byte[data.length - 4]; System.arraycopy(data, 0, dataBytes3, 0, data.length - 4); //将 16点阵数据 转换为 二进制点阵数据 byte[] twoBytes = DotMatrixConversionUtil.sixteenTo2Lattice(data); bitmapDataVo.setMiniLZOVoList(miniLZOVoList); bitmapDataVo.setTwoData(twoBytes); return bitmapDataVo; } catch (Exception e) { e.printStackTrace(); logger.error("获取 点阵图文件 :" + e + " 路径为 " + bitmapDataVo.getPath()); } return null; } /************************************** 处理的点阵数据对象 **************************************/ /** * 将完整的点阵图数据 转换为 点整图对象 * * @param twoBytes * @param deId * @param path * @param typeCode * @param isDefault * @return */ public BitmapDataVo dealWithBitmapDataVo(byte[] twoBytes, String deId, String path, String typeCode, boolean isDefault) { BitmapDataVo bitmapDataVo = new BitmapDataVo(); bitmapDataVo.setTwoData(twoBytes); bitmapDataVo.setTime(System.currentTimeMillis()); //区分默认点阵图 if (isDefault) { typeCode = "D" + typeCode; } bitmapDataVo.setTypeCode(typeCode); bitmapDataVo.setPath(path + typeCode); //保存文件 Map sizeMap = dealWithMiniLZOVo(typeCode, twoBytes); bitmapDataVo.setMiniLZOVoList(sizeMap); return bitmapDataVo; } /** * 将完整的点阵图数据 进行 分割并压缩 * * @param typeCode * @param twoBytes * @return */ public Map dealWithMiniLZOVo(String typeCode, byte[] twoBytes) { Map sizeMap = new HashMap<>(); // 将二进制点阵图转换为16进制点阵图 byte[] dataBytes2 = DotMatrixConversionUtil.twoTo16Lattice(twoBytes); //2024/04/09 新增 在整体点阵数据后面追加整体CRC32的值 //进行CRC32算法 long crc32 = CustomCRC32Util.calculateCRC32(dataBytes2); byte[] crc32Bytes = OtherUtil.longToByteArray(crc32, 4);//固定4位 byte[] dataBytes = new byte[dataBytes2.length + crc32Bytes.length]; System.arraycopy(dataBytes2, 0, dataBytes, 0, dataBytes2.length); System.arraycopy(crc32Bytes, 0, dataBytes, dataBytes2.length, crc32Bytes.length); //将16进制点阵图进行压缩 List miniLZOVoList = MiniLZOUtil.getInstance().subMiniLZO(dataBytes); //生成对应的文件名称 for (int i = 0; i < miniLZOVoList.size(); i++) { String fileName = typeCode + (i < 10 ? "0" + i : i) + ROOT_FILE_TYPE_NAME; MiniLZOVo miniLZOVo = miniLZOVoList.get(i); sizeMap.put(miniLZOVo.getOgSize() + "/" + fileName, miniLZOVo); } return sizeMap; } }