package com.inspect.nvr.service.impl; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.inspect.nvr.domain.Infrared.*; import com.inspect.nvr.domain.algorithm.in.AnalyseReqItem; import com.inspect.nvr.domain.algorithm.in.AnalyseRequest; import com.inspect.nvr.domain.algorithm.out.AnalyseResItem; import com.inspect.nvr.domain.algorithm.out.AnalyseResPoint; import com.inspect.nvr.domain.algorithm.out.AnalyseResult; import com.inspect.nvr.domain.camera.CameraPresetPoint; import com.inspect.nvr.hikVision.utils.AjaxResult; import com.inspect.nvr.hikVision.utils.StringUtils; import com.inspect.nvr.hikVision.utils.jna.HCNetSDK; import com.inspect.nvr.hikVision.utils.jna.HikVisionUtils; import com.inspect.nvr.service.HikCameraService; import com.inspect.nvr.service.HikFRemoteConfigCallBack_imp; import com.inspect.nvr.service.HikLoginService; import com.inspect.nvr.service.HikVisionService; import com.inspect.nvr.tempCount.TempCount; import com.inspect.nvr.utils.DateUtils; import com.inspect.nvr.utils.redis.RedisService; import com.inspect.nvr.utils.sftp.SftpClient; import com.sun.jna.Memory; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import okhttp3.*; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import org.apache.commons.net.ftp.FTPSClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.concurrent.*; /** * 海康威视测试服务类 */ @Service public class HikVisionServiceImpl implements HikVisionService { private static HikFExceptionCallBack_Imp fExceptionCallBack; private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private HCNetSDK hcNetSDK; private String picPath; // @Value("${file.hrUavUrl:test}") // private String hrUavUrl = "http://192.168.4.167:2000/"; private String hrUavUrl = "http://192.168.4.160:2000/"; // @Value("${file.hrFtpUrl:test}") private String hrFtpUrl = "ftp://ftpuser:atia2018@192.168.4.129:10012/"; // @Value("${file.ftpUrlAddress:test}") private String ftpUrlAddress = "192.168.1.116"; // @Value("${file.ftpUrlAccount:test}") private String ftpUrlAccount = "ftpuser"; // @Value("${file.ftpUrlPwd:test}") private String ftpUrlPwd = "atia2018"; // @Value("${file.ftpUrlPort:10000}") private Integer ftpUrlPort = 10990; // @Value("${file.produceEnvironment:true}") private Boolean produceEnvironment = true; @Autowired private RedisTemplate redisTemplate; @Resource private SftpClient sftpClient; @Resource private TempCount tempCount; @Resource private RedisService redisService; @Resource private HikCameraService hikCameraService; private Integer lUserID; @Autowired private HikLoginService hikLoginService; //二维数组转 CSV private static String convertMatrixToCsv(float[][] matrix) { StringBuilder csvBuilder = new StringBuilder(); for (float[] row : matrix) { for (int i = 0; i < row.length; i++) { csvBuilder.append(row[i]); if (i < row.length - 1) { csvBuilder.append(","); } } csvBuilder.append("\n"); } return csvBuilder.toString(); } public static String truncateFileNameToCsv(String originalPath) { // 获取文件名部分(最后一个 '/' 之后的内容) int lastSlashIndex = originalPath.lastIndexOf('/'); if (lastSlashIndex == -1) { // 如果没有路径分隔符,直接处理整个字符串 return processFileNameToCsv(originalPath); } // 分离路径和文件名 String path = originalPath.substring(0, lastSlashIndex + 1); String fileName = originalPath.substring(lastSlashIndex + 1); // 处理文件名部分并强制改为.csv String processedFileName = processFileNameToCsv(fileName); return path + processedFileName; } private static String processFileNameToCsv(String fileName) { // 去掉文件扩展名(如果有) int lastDotIndex = fileName.lastIndexOf('.'); if (lastDotIndex != -1) { fileName = fileName.substring(0, lastDotIndex); } // 去掉最后一个 '_' 及其后面的部分 int lastUnderscoreIndex = fileName.lastIndexOf('_'); if (lastUnderscoreIndex != -1) { fileName = fileName.substring(0, lastUnderscoreIndex); } // 强制添加.csv后缀 return fileName + ".csv"; } @Override public AjaxResult login(NvrInfo nvrInfo) { return login_V40(nvrInfo); } /** * 设备登录V40 与V30功能一致 */ public AjaxResult login_V40(NvrInfo nvrInfo) { HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = HikVisionUtils.login_V40(nvrInfo.getNvrIp(), nvrInfo.getServerPort().shortValue(), nvrInfo.getAccount(), nvrInfo.getPassword());//设备登录信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息 int lUserID = hcNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); if (lUserID == -1) { System.out.println("登录失败,错误码为" + hcNetSDK.NET_DVR_GetLastError()); return AjaxResult.error(hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(hcNetSDK.NET_DVR_GetLastError()))); } else { System.out.println(":设备登录成功!" + lUserID); // birdNvrMapper.updateNvrInfo(nvrInfo); // redisTemplate.opsForValue().set(nvrInfo.getNvrIp() + "_userId", lUserID); redisService.setCacheObject(nvrInfo.getNvrIp() + "_userId", lUserID, 200L, TimeUnit.SECONDS); //若果设备序列号为空时,即为第一次登陆,写入基础数据 if (nvrInfo.getNvrSerial() == null || nvrInfo.getNvrSerial().equals("")) { m_strDeviceInfo.read(); HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceinfo_v30 = m_strDeviceInfo.struDeviceV30; nvrInfo.setNvrSerial(StringUtils.bytetoString(deviceinfo_v30.sSerialNumber, "GB2312")); //模拟通道不为0,并且数字通道为0,即为模拟通道 if (deviceinfo_v30.byChanNum != 0 && deviceinfo_v30.byIPChanNum == 0) { nvrInfo.setChannelType(0); nvrInfo.setChannelNumber(deviceinfo_v30.byChanNum + deviceinfo_v30.byHighDChanNum * 256); nvrInfo.setStartChannel((int) deviceinfo_v30.byStartChan); } //模拟通道为0,并且数字通道不为0,即为数字通道 if (deviceinfo_v30.byChanNum == 0 && deviceinfo_v30.byIPChanNum != 0) { nvrInfo.setChannelType(1); nvrInfo.setChannelNumber(deviceinfo_v30.byIPChanNum + deviceinfo_v30.byHighDChanNum * 256); nvrInfo.setStartChannel((int) deviceinfo_v30.byStartDChan); } //模拟通道不为0,并且数字通道不为0,即为双通道。 if (deviceinfo_v30.byChanNum != 0 && deviceinfo_v30.byIPChanNum != 0) { nvrInfo.setChannelType(2); nvrInfo.setChannelNumber(deviceinfo_v30.byChanNum + deviceinfo_v30.byHighDChanNum * 256); nvrInfo.setStartChannel((int) deviceinfo_v30.byStartChan); } nvrInfo.setCalicheNumber((int) deviceinfo_v30.byDiskNum); nvrInfo.setCharEncodeType((int) m_strDeviceInfo.byCharEncodeType); nvrInfo.setSyncDate(new Date()); // nvrInfoMapper.updateNvrInfo(nvrInfo); } return AjaxResult.success(hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(hcNetSDK.NET_DVR_GetLastError()))); } } /** * 海康实时测温接口 * 优化并发场景 */ public TemperatureData StartRemote(Camera camera) { NvrInfo nvrInfo = new NvrInfo(); nvrInfo.setNvrIp(camera.getIp()); nvrInfo.setServerPort(camera.getPort()); nvrInfo.setAccount(camera.getUserName()); nvrInfo.setPassword(camera.getPassword()); TemperatureData data = hikCameraService.realTimeThermometry(nvrInfo, camera.getChannel()); return data; } /** * @deprecated 实时测温接口,获取最高温和最低温 */ @Deprecated public TemperatureData StartRemoteOld(Camera camera) { int result = 0; TemperatureData temperatureData = null; try { log.info("实时测温入口================================================="); if (camera.getLUserID() != 0) { NvrInfo nvrInfo = new NvrInfo(); nvrInfo.setNvrIp(camera.getIp()); nvrInfo.setServerPort(camera.getPort()); nvrInfo.setAccount(camera.getUserName()); nvrInfo.setPassword(camera.getPassword()); int userId = hikLoginService.login(nvrInfo); camera.setLUserID(userId); } log.info("开始实时测温================================================="); // 2. 设置测温参数 HCNetSDK.NET_DVR_REALTIME_THERMOMETRY_COND cond = new HCNetSDK.NET_DVR_REALTIME_THERMOMETRY_COND(); cond.dwSize = cond.size(); cond.dwChan = camera.getChannel();// 通道号 cond.byRuleID = 1; // 规则ID cond.byMode = 1; // 测温模式 cond.wInterval = 10; // 间隔 cond.byRes2 = new byte[32]; Arrays.fill(cond.byRes2, (byte) 0); cond.write(); // 手动同步结构体到内存 CompletableFuture temperatureFuture = new CompletableFuture<>(); // 启动看门狗(4秒超时,比get()的5秒早1秒,预留处理时间) ScheduledExecutorService watchdog = Executors.newSingleThreadScheduledExecutor(); watchdog.schedule(() -> { if (!temperatureFuture.isDone()) { log.warn("回调线程可能阻塞,看门狗强制标记超时"); temperatureFuture.completeExceptionally(new TimeoutException("回调线程阻塞超时")); } }, 5, TimeUnit.SECONDS); // 3. 启动远程测温 Pointer lpInBuffer = cond.getPointer(); int dwInBufferSize = cond.size(); result = hcNetSDK.NET_DVR_StartRemoteConfig( camera.getLUserID(), HCNetSDK.NET_DVR_GET_REALTIME_THERMOMETRY, lpInBuffer, dwInBufferSize, new HikFRemoteConfigCallBack_imp() { @Override public void invoke(int dwType, Pointer lpBuffer, int dwBufLen, Pointer pUserData) { System.out.println("回调收到数据,类型: " + dwType + ", 长度: " + dwBufLen); HCNetSDK.NET_DVR_THERMOMETRY_UPLOAD thermometryData = new HCNetSDK.NET_DVR_THERMOMETRY_UPLOAD(); int structSize = thermometryData.size(); if (dwBufLen < structSize) { System.out.println("缓冲区长度不足,期望: " + structSize + ", 实际: " + dwBufLen); return; } Pointer structurePointer = thermometryData.getPointer(); structurePointer.write(0, lpBuffer.getByteArray(0, structSize), 0, structSize); thermometryData.read(); // 解析数据到结构体字段 HCNetSDK.NET_DVR_LINEPOLYGON_THERM_CFG struLinePolygonThermCfg = thermometryData.struLinePolygonThermCfg; System.out.println("规则ID: " + thermometryData.byRuleID); System.out.println("最高温度: " + struLinePolygonThermCfg.fMaxTemperature); System.out.println("最低温度: " + struLinePolygonThermCfg.fMinTemperature); System.out.println("平均温度: " + struLinePolygonThermCfg.fAverageTemperature); System.out.println("温差: " + struLinePolygonThermCfg.fTemperatureDiff); System.out.println("通道号: " + thermometryData.dwChan); System.out.println("-----------------------------------------------------------"); // 封装所有温度数据 TemperatureData data = new TemperatureData( String.valueOf(struLinePolygonThermCfg.fMaxTemperature), String.valueOf(struLinePolygonThermCfg.fMinTemperature), struLinePolygonThermCfg.fAverageTemperature, struLinePolygonThermCfg.fTemperatureDiff, thermometryData.dwChan, thermometryData.byRuleID ); temperatureFuture.complete(data); // 返回完整数据 } }, null ); log.info("测温结束================================================="); if (result == -1) { int errorCode = hcNetSDK.NET_DVR_GetLastError(); String errorMsg = hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(errorCode)); log.error("启动远程测温失败,错误码为:{},错误信息为:{}", errorCode, errorMsg); } temperatureData = temperatureFuture.get(); } catch (Exception e) { log.error("测温异常报错: {}", e.getMessage()); } finally { log.info("关闭实时测温result值 {}", result); //关闭实时测温 boolean i = StopRemote(result); if (i) { log.info("关闭实时测温成功 {}", true); } } return temperatureData; } //关闭实时测温 @Override public boolean StopRemote(int result) { boolean b = hcNetSDK.NET_DVR_StopRemoteConfig(result); return b; } @Override public AjaxResult cameraAngleJump(Camera camera) { log.info(camera.getIp() + "摄像头跳转"); // hcNetSDK.NET_DVR_Init(); // 1. 登录设备 HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = HikVisionUtils.login_V40( camera.getIp(), (short) camera.getPort(), camera.getUserName(), camera.getPassword() ); HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); int lUserID = hcNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); //将登录认证传下去 camera.setLUserID(lUserID); //2. 直连摄像头跳转,打开实时预览 HCNetSDK.NET_DVR_CLIENTINFO netDvrClientinfo = new HCNetSDK.NET_DVR_CLIENTINFO(); netDvrClientinfo.lChannel = 1; netDvrClientinfo.lLinkMode = 1; int i = hcNetSDK.NET_DVR_RealPlay(lUserID, netDvrClientinfo); //实时预览返回,预置位跳转,跳转的预置位码 boolean gotoPreset = hcNetSDK.NET_DVR_PTZPreset(i, HCNetSDK.GOTO_PRESET, camera.getPointNum()); if (!gotoPreset) { log.error("获取设备预置位跳转设备参数失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); return AjaxResult.error(hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(hcNetSDK.NET_DVR_GetLastError()))); } else { log.info("海康-成功跳转到预置位!" + camera.getPointNum()); } return AjaxResult.success(); } //抓图 单独测试 未使用 @Override public Camera cameraPictrue(Camera camera) throws Exception { log.info(camera.getIp() + "摄像头抓图"); if (camera.getLUserID() != 0) { // 1. 登录设备 HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = HikVisionUtils.login_V40( camera.getIp(), (short) camera.getPort(), camera.getUserName(), camera.getPassword() ); HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); int lUserID = hcNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); //将登录认证传下去 camera.setLUserID(lUserID); } // 1. 设置抓图参数 HCNetSDK.NET_DVR_JPEGPARA dvrJpegpara = new HCNetSDK.NET_DVR_JPEGPARA(); dvrJpegpara.wPicSize = 0xff; // 0xff表示最高分辨率 dvrJpegpara.wPicQuality = 2; // 图像质量(1-6,1最高) // 2. 创建临时存储目录(系统临时目录更安全) // Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"), "hik_capture"); // if (!Files.exists(tempDir)) { // Files.createDirectories(tempDir); // } // // 3. 生成唯一文件名(IP+时间戳) // String fileName = String.format("%s_%s.jpg", camera.getIp(), DateUtils.dateTimeNow("yyyyMMddHHmmss")); // Path tempImagePath = tempDir.resolve(fileName); // 确保目录存在 File picDir = new File("D:\\pic"); if (!picDir.exists()) { picDir.mkdirs(); // 如果目录不存在,创建它 } // 生成文件名(例如:camera_ip + timestamp) String fileName = "D:\\pic\\" + camera.getIp() + "_" + System.currentTimeMillis() + ".jpg"; Path tempImagePath = Paths.get(fileName); // 4. 执行抓图(注意:海康SDK要求Windows风格的路径) boolean success = hcNetSDK.NET_DVR_CaptureJPEGPicture(camera.getLUserID(), 2, dvrJpegpara, tempImagePath.toString().getBytes("GBK")); // 海康设备通常需要GBK编码 if (!success) { int errorCode = hcNetSDK.NET_DVR_GetLastError(); String errorMsg = hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(errorCode)); // return AjaxResult.error("抓图失败:" + errorMsg + "(错误码:" + errorCode + ")"); log.error("抓图失败,错误码:{},错误信息:{}", errorCode, errorMsg); } // 5. 上传到FTP try (InputStream inputStream = Files.newInputStream(tempImagePath)) { picFtp(picPath + fileName, inputStream, ftpUrlAddress, ftpUrlPort, ftpUrlAccount, ftpUrlPwd ); } catch (Exception e) { // return AjaxResult.error("FTP上传失败:" + e.getMessage()); log.error("抓图并上传失败:{}", e.getMessage()); } finally { // 6. 确保删除临时文件 Files.deleteIfExists(tempImagePath); } camera.setUlr(picPath + fileName); return camera; } //红外摄像头任务流程 public InfraredInfo cameraCalculatePicture(Camera camera) { log.info("进入摄像头红外图片接口!"); picPath = "/2/"; InfraredInfo infraredInfo = new InfraredInfo(); int firstX = 1; int firstY = 1; int secondX = 639; int secondY = 511; int imgWidth = 640; int imgHeight = 512; InfraPictureInfo infraPictureInfo = new InfraPictureInfo(); List coordinates = new ArrayList<>(); coordinates.add(new Coordinate(firstX, firstY, secondX, secondY)); infraPictureInfo.setImgWidth(imgWidth); infraPictureInfo.setImgHeight(imgHeight); infraPictureInfo.setCoordinates(coordinates); //红外摄像头需要设置最大框测温规则1,固定到一个预置位上绑定 //1:跳转预置位 //家里相机没有预置位,现场相机存在预置位需要跳转到画测温框预置位,否则无法获取规则温度 // cameraAngleJump(camera); //2:抓取图片,保存到ftp try { Camera cameraPictrue = cameraPictrue(camera); camera.setLUserID(cameraPictrue.getLUserID()); } catch (Exception e) { throw new RuntimeException(e); } //3:调取摄像头实时测温功能,获取最高温和最低温 TemperatureData temperatureData = StartRemote(camera); // double maxTemperature = temperatureData.getMaxTemperature(); // double minTemperature = temperatureData.getMinTemperature(); temperatureData.getAvgTemperature(); temperatureData.getTemperatureDiff(); InputStream inputStream = downloadFtp(camera.getUlr()); //传入照片流,最大值最小温度值,反算温度矩阵 // float[][] floats = tempCount.countTemp(inputStream, maxTemperature, minTemperature); // infraredInfo.setTemperatureMatrix(floats); //4:画框标注,保存到ftp infraPictureInfo.setFilePath(camera.getUlr()); String s = cameraImageOverlays(infraPictureInfo, infraredInfo); infraredInfo.setOutPath(s); return infraredInfo; } //摄像头画框 public String cameraImageOverlays(InfraPictureInfo infraPictureInfo, InfraredInfo infraredInfo) { List coordinates = infraPictureInfo.getCoordinates(); Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss"); String markPicName = sf.format(date); // 图片路径(请替换为实际路径) String imagePath = infraPictureInfo.getFilePath(); // 获取文件名(不含扩展名) File file = new File(imagePath); String fileName = file.getName(); String pureName = fileName.substring(0, fileName.lastIndexOf('.')); String filename = picPath; String outputPath = picPath + pureName + "_" + markPicName + ".jpg"; String csvPath = picPath + pureName + "_" + markPicName + ".csv"; //判断路径是否存在 File filePath = new File(filename); if (!filePath.exists()) { //不存在,创建目录 filePath.mkdirs(); } try { InputStream inputStreamPath = downloadFtp(imagePath); if (inputStreamPath == null) { System.out.println("无法加载图片: " + imagePath); return null; } // 加载原始图片 BufferedImage originalImage = ImageIO.read(inputStreamPath); // 创建可编辑的图片副本 BufferedImage annotatedImage = new BufferedImage( originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_INT_RGB ); // 绘制原始图片 Graphics2D g2d = annotatedImage.createGraphics(); g2d.drawImage(originalImage, 0, 0, null); // 设置标注样式 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Font font = new Font("微软雅黑", Font.BOLD, 17); Font font = new Font("WenQuanYi Zen Hei", Font.BOLD, 20); final String imageType = infraPictureInfo.getImgType(); for (Coordinate c : coordinates) { //点标注 if (c.getFirstX() != null && c.getFirstY() != null && c.getSecondX() == null && c.getSecondY() == null) { g2d.setFont(font); // 标注点坐标 g2d.setColor(Color.WHITE); int x = c.getFirstX(); int y = c.getFirstY(); // 确保坐标在图片范围内 if (x >= 0 && x < originalImage.getWidth() && y >= 0 && y < originalImage.getHeight()) { // 绘制点(用实心圆表示) g2d.fillOval(x - 3, y - 3, 6, 6); infraPictureInfo.setFirstX(x); infraPictureInfo.setFirstY(y); // InfraredInfo drawStringPoint = PointTemperatureShow(c, infraredInfo.getMatrixWidth(), infraredInfo.getMatrixHeight(), infraredInfo.getTemperatureMatrix()); // // 添加坐标标签 // g2d.drawString("(" + String.format("%.2f", drawStringPoint.getPointTemperature()) + ")", x + 8, y - 8); } } //矩阵标注 if (c.getSecondX() != null && c.getSecondY() != null) { // 标注矩形(每两个点确定一个矩形) g2d.setColor(Color.WHITE); int x1 = c.getFirstX(); int y1 = c.getFirstY(); int x2 = c.getSecondX(); int y2 = c.getSecondY(); // 确保坐标在图片范围内 if (x1 >= 0 && x1 < originalImage.getWidth() && y1 >= 0 && y1 < originalImage.getHeight() && x2 >= 0 && x2 < originalImage.getWidth() && y2 >= 0 && y2 < originalImage.getHeight()) { // 确保x1,y1是左上角,x2,y2是右下角 int rectX = Math.min(x1, x2); int rectY = Math.min(y1, y2); int width = Math.abs(x2 - x1); int height = Math.abs(y2 - y1); // 设置更粗的画笔(加粗矩形边框) g2d.setStroke(new BasicStroke(3)); // 3像素宽 // 绘制矩形 g2d.drawRect(rectX, rectY, width, height); infraPictureInfo.setFirstX(x1); infraPictureInfo.setFirstY(y1); infraPictureInfo.setSecondX(x2); infraPictureInfo.setSecondY(y2); InfraredInfo drawStringMatrix = matrixTemperatureShow(c, infraredInfo.getMatrixWidth(), infraredInfo.getMatrixHeight(), infraredInfo.getTemperatureMatrix()); infraredInfo.setFrameMax(Math.round(drawStringMatrix.getFrameMax() * 100) / 100f); Integer maxTempX = drawStringMatrix.getMaxTempX(); Integer maxTempY = drawStringMatrix.getMaxTempY(); log.info("最高温度值坐标点:" + "maxTempX:" + maxTempX + " maxTempY:" + maxTempY); // 添加矩形标签 String line1 = "平均温度:" + String.format("%.2f", drawStringMatrix.getFrameAverage()); String line2 = "最高温度:" + String.format("%.2f", drawStringMatrix.getFrameMax()); String line3 = "最低温度:" + String.format("%.2f", drawStringMatrix.getFrameMin()); g2d.drawString(line1, rectX + 5, rectY + 15); g2d.drawString(line2, rectX + 5, rectY + 30); g2d.drawString(line3, rectX + 5, rectY + 45); // 在最高温度点画一个空心圆(红色边框) if (maxTempX != null && maxTempY != null) { log.info("画最高温度的点,坐标:x={}, y={}", maxTempX, maxTempY); // 边界检查 if (maxTempX >= 0 && maxTempX < originalImage.getWidth() && maxTempY >= 0 && maxTempY < originalImage.getHeight()) { // 设置醒目的颜色 g2d.setColor(Color.RED); g2d.setStroke(new BasicStroke(5)); // 画空心圆 int circleDiameter = 8; g2d.drawOval(maxTempX - circleDiameter / 2, maxTempY - circleDiameter / 2, circleDiameter, circleDiameter); // 画十字标记 g2d.drawLine(maxTempX - 3, maxTempY, maxTempX + 3, maxTempY); g2d.drawLine(maxTempX, maxTempY - 3, maxTempX, maxTempY + 3); log.info("成功绘制最高温度点标记"); } else { log.warn("最高温度点坐标超出图像范围:x={}, y={}", maxTempX, maxTempY); } } } else { log.error("画框坐标超出图片范围"); // 确保x1,y1是左上角,x2,y2是右下角 int rectX = Math.min(1, 639); int rectY = Math.min(1, 511); int width = Math.abs(639 - 1); int height = Math.abs(511 - 1); // 设置更粗的画笔(加粗矩形边框) g2d.setStroke(new BasicStroke(3)); // 3像素宽 // 绘制矩形 g2d.drawRect(rectX, rectY, width, height); infraPictureInfo.setFirstX(x1); infraPictureInfo.setFirstY(y1); infraPictureInfo.setSecondX(x2); infraPictureInfo.setSecondY(y2); InfraredInfo drawStringMatrix = matrixTemperatureShow(c, infraredInfo.getMatrixWidth(), infraredInfo.getMatrixHeight(), infraredInfo.getTemperatureMatrix()); infraredInfo.setFrameMax(Math.round(drawStringMatrix.getFrameMax() * 100) / 100f); // 添加矩形标签 String line1 = "平均温度:" + String.format("%.2f", drawStringMatrix.getFrameAverage()); String line2 = "最高温度:" + String.format("%.2f", drawStringMatrix.getFrameMax()); String line3 = "最低温度:" + String.format("%.2f", drawStringMatrix.getFrameMin()); g2d.drawString(line1, rectX + 5, rectY + 15); g2d.drawString(line2, rectX + 5, rectY + 30); g2d.drawString(line3, rectX + 5, rectY + 45); } } } g2d.dispose(); ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(annotatedImage, "jpg", os); InputStream inputStream = new ByteArrayInputStream(os.toByteArray()); float[][] temperatureMatrix = infraredInfo.getTemperatureMatrix(); String csvData = convertMatrixToCsv(temperatureMatrix); InputStream csvStream = new ByteArrayInputStream(csvData.getBytes(StandardCharsets.UTF_8)); //保存到FTP服务器 picFtp(outputPath, inputStream, ftpUrlAddress, ftpUrlPort, ftpUrlAccount, ftpUrlPwd); picFtp(csvPath, csvStream, ftpUrlAddress, ftpUrlPort, ftpUrlAccount, ftpUrlPwd); } catch (IOException e) { System.err.println("处理图片时出错: " + e.getMessage()); e.printStackTrace(); } return outputPath; } @Override public AjaxResult capturePicture(InfraPictureInfo infraPictureInfo) { return AjaxResult.success("设置成功"); } //从ftp获取csv流转换成二维数组 //框选温度值计算 public InfraredInfo matrixTemperatureShow(Coordinate coordinate, short width, short height, float[][] temperatureMatrix) { InfraredInfo infraredInfo = new InfraredInfo(); //存储框选矩阵温度值 List values = new ArrayList<>(); // 用于记录最高温度的坐标 int maxTempX = -1; int maxTempY = -1; float currentMax = Float.MIN_VALUE; if (ObjectUtil.isNotEmpty(coordinate.getFirstX()) && ObjectUtil.isNotEmpty(coordinate.getSecondX())) { //if (coordinate.getImgType() != 3) // {//无人机不需要对比底图 // //倍数计算 // double xMultiple = (coordinate.getImgWidth().doubleValue() / width) * 100 / 100.0; // double yMultiple = (coordinate.getImgHeight().doubleValue() / height) * 100 / 100.0; // // //比例缩放像素 获取底图温度值 // int x1 = (int) (coordinate.getFirstX() / xMultiple); // int y1 = (int) (coordinate.getFirstY() / yMultiple); // int x2 = (int) (coordinate.getSecondX() / xMultiple); // int y2 = (int) (coordinate.getSecondY() / yMultiple); // coordinate.setFirstX(x1); // coordinate.setFirstY(y1); // coordinate.setSecondX(x2); // coordinate.setSecondY(y2); // } if (coordinate.getSecondX() != 0 && coordinate.getSecondY() != 0) { for (int j = coordinate.getFirstY(); j <= coordinate.getSecondY(); j++) { // 列 if (j < 0 || j >= temperatureMatrix.length) continue; for (int i = coordinate.getFirstX(); i <= coordinate.getSecondX(); i++) { // 行(固定列,遍历行) if (i < 0 || i >= temperatureMatrix[j].length) continue; float temp = temperatureMatrix[j][i]; values.add(temp); if (temp > currentMax) { currentMax = temp; maxTempX = i; maxTempY = j; } } } } // 计算框选矩阵温度数值 float frameAverage = (float) values.stream().mapToDouble(f -> f).average().orElse(0); float frameMax = (float) values.stream().mapToDouble(f -> f).max().orElse(0); float frameMin = (float) values.stream().mapToDouble(f -> f).min().orElse(0); // 设置最高温度坐标(如果有找到的话) if (maxTempX != -1 && maxTempY != -1) { infraredInfo.setMaxTempX(maxTempX); infraredInfo.setMaxTempY(maxTempY); log.info("最大温度坐标:{}, {}", maxTempX, maxTempY); } infraredInfo.setFrameAverage(frameAverage); infraredInfo.setFrameMax(frameMax); infraredInfo.setFrameMin(frameMin); } return infraredInfo; } //调用华软接口获取csv文件 public float[][] UploadFtpImage(String url, String type, String image) { log.info("imageName" + image); log.info("hrUrl" + hrUavUrl); type = "ftp"; // OkHttpClient client = new OkHttpClient(); OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) // 连接超时5秒 .readTimeout(10, TimeUnit.SECONDS) // 读取超时10秒 .writeTimeout(5, TimeUnit.SECONDS) // 写入超时5秒 .retryOnConnectionFailure(false) // 禁用自动重试 .build(); log.info("UploadFtpImage, client: {}", client); float[][] floats = new float[0][]; try { // 构建 multipart 请求体 RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("type", type) .addFormDataPart("image", image) .build(); log.info("UploadFtpImage, url: {}", url); // 构建请求 Request request = new Request.Builder() .url(url) .post(requestBody) .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)") .addHeader("Accept", "*/*") .addHeader("Connection", "keep-alive") .build(); log.info("UploadFtpImage, request: {}", request); // 执行请求并处理响应 try (Response response = client.newCall(request).execute()) { log.info("UploadFtpImage, response: {}", response); if (!response.isSuccessful() && response.code() != 4006) { throw new IOException("请求失败,HTTP状态码: " + response.code()); } // if (!response.isSuccessful()) { // throw new IOException("请求失败,HTTP状态码: " + response.code()); // } String responseBody = response.body() != null ? response.body().string() : null; if (responseBody == null) { throw new IOException("响应体为空"); } // 解析 JSON 并提取 image_raw_flow ObjectMapper mapper = new ObjectMapper(); JsonNode jsonArray = mapper.readTree(responseBody); if (jsonArray.isEmpty()) { throw new RuntimeException("JSON数组为空"); } JsonNode firstItem = jsonArray.get(0); String imageRawFlow = firstItem.get("image_raw_flow").asText(); log.info("imageRawFlow" + imageRawFlow); floats = parseCsvFromFtp2(imageRawFlow); } } catch (Exception e) { e.printStackTrace(); System.err.println("FTP请求处理失败,尝试本地文件: " + e.getMessage()); // return null; } return floats; } private float[][] parseCsvFromFtp2(String csvUrl) throws IOException, URISyntaxException { log.info("连接ftp,获取csv文件"); InputStream inputStream = null; FTPSClient ftps = null; CSVParser csvParser = null; try { ftps = new FTPSClient(true); ftps.connect(ftpUrlAddress, ftpUrlPort); boolean loginRes = ftps.login(ftpUrlAccount, ftpUrlPwd); if (loginRes) { log.info("[FTP] LOGIN SUCCESS: {}", ftpUrlAddress); } ftps.setFileType(2); ftps.enterLocalPassiveMode(); ftps.setControlEncoding("UTF-8"); ftps.setFileTransferMode(10); ftps.execPROT("P"); // URI uri = new URI(csvUrl); String filePath = uri.getPath(); log.info("[FTP] DOWNLOAD: {}", filePath); inputStream = ftps.retrieveFileStream(filePath); if (inputStream == null) { log.error("[FTP] DOWNLOAD FAIL, EMPTY STREAM: {}", filePath); } Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); csvParser = CSVFormat.DEFAULT.parse(reader); List records = csvParser.getRecords(); // 7. 转换为 float[][] float[][] result = new float[records.size()][]; for (int i = 0; i < records.size(); i++) { CSVRecord record = records.get(i); result[i] = new float[record.size()]; for (int j = 0; j < record.size(); j++) { result[i][j] = Float.parseFloat(record.get(j)); } } return result; } finally { // 8. 确保资源关闭 IOUtils.closeQuietly(csvParser); IOUtils.closeQuietly(inputStream); if (ftps != null && ftps.isConnected()) { try { ftps.logout(); ftps.disconnect(); } catch (IOException e) { log.error("FTP 断开连接失败", e); } } } } //上传图片到ftp public void picFtp(String newPath, InputStream originalPath, String ftpUrlAddress, Integer ftpUrlPort, String ftpUrlAccount, String ftpUrlPwd) { FTPSClient ftps = null; try { ftps = new FTPSClient(true); ftps.connect(ftpUrlAddress, ftpUrlPort); boolean loginRes = ftps.login(ftpUrlAccount, ftpUrlPwd); System.out.println(loginRes); ftps.setFileType(2); ftps.enterLocalPassiveMode(); ftps.setControlEncoding("UTF-8"); ftps.setFileTransferMode(10); ftps.execPROT("P"); boolean success = ftps.storeFile(newPath, originalPath); if (!success) { System.err.println("上传失败!FTP 返回: " + ftps.getReplyString()); } } catch (Exception e) { log.error("error" + e); } finally { // 5. 关闭资源 try { if (originalPath != null) originalPath.close(); if (ftps != null && ftps.isConnected()) { ftps.logout(); ftps.disconnect(); } } catch (IOException e) { log.error("error" + e); } } } //ftp图片获取 public InputStream downloadFtp(String downloadPath) { InputStream inputStream = null; FTPSClient ftps; try { ftps = new FTPSClient(true); ftps.connect(ftpUrlAddress, ftpUrlPort); boolean loginRes = ftps.login(ftpUrlAccount, ftpUrlPwd); System.out.println(loginRes); ftps.setFileType(2); ftps.enterLocalPassiveMode(); ftps.setControlEncoding("UTF-8"); ftps.setFileTransferMode(10); ftps.execPROT("P"); inputStream = ftps.retrieveFileStream(downloadPath); if (inputStream == null) { System.out.println("[FTP] DOWNLOAD FAIL, EMPTY STREAM:" + downloadPath); } } catch (Exception e) { log.error("error" + e); } return inputStream; } @Override public ResponseEntity irPicAnalyse(final String analyseRequestJson) { log.info("[INFRARED] irPicAnalyse: analyseRequestJson={}", analyseRequestJson); AnalyseRequest analyseRequest; try { analyseRequest = new Gson().fromJson(analyseRequestJson, AnalyseRequest.class); } catch (Exception e) { log.error("[INFRARED] irPicAnalyse: analyseRequestJson parse exception: {}", e.getMessage()); return ResponseEntity.ok().body("{\"code\":\"201\"}"); } log.info("[INFRARED] irPicAnalyse: analyseRequest={}", new Gson().toJson(analyseRequest)); List analyseReqItemList = analyseRequest.getObjectList(); if (analyseReqItemList == null || analyseReqItemList.isEmpty()) { log.error("[INFRARED] irPicAnalyse: analyseReqItemList empty!"); return ResponseEntity.ok().body("{\"code\":\"202\"}"); } final AnalyseReqItem analyseReqItem = analyseReqItemList.get(0); final String[] typeList = analyseReqItem.getTypeList(); String algType = "unKnownType"; if (typeList != null && typeList.length != 0) { algType = typeList[0]; } final String feedBackHostIp = analyseRequest.getRequestHostIp(); final String feedBackPort = analyseRequest.getRequestHostPort(); final String feedbackUrl = feedBackHostIp + feedBackPort + "/picAnalyseRetNotify"; log.info("[INFRARED] irPicAnalyse: feedbackUrl={}", feedbackUrl); String[] imageUrlList = analyseReqItem.getImageUrlList(); String[] typeListImg = analyseReqItem.getTypeList(); InfraPictureInfo infraPictureInfo = new InfraPictureInfo(); // infraPictureInfo.setChannelId(); infraPictureInfo.setImgType(typeListImg[0]); infraPictureInfo.setFilePath(imageUrlList[0]); //红外方法 InfraredInfo infraredInfo = calculatePicture(infraPictureInfo, "1,1,639,511,640,512"); AnalyseResult analyseResult = new AnalyseResult(); analyseResult.setRequestId(analyseRequest.getRequestId()); AnalyseResPoint analyseResPoint = new AnalyseResPoint(); // analyseResPoint.setValue("0"); // analyseResPoint.setConf("0.85"); if (String.valueOf((double) infraredInfo.getFrameMax()) != null && infraredInfo.getOutPath() != null) { analyseResPoint.setValue("0");//成功 } else { analyseResPoint.setValue("1");//失败 } analyseResPoint.setConf(String.format("%.2f", (double) infraredInfo.getFrameMax())); analyseResPoint.setResImageUrl(infraredInfo.getOutPath()); analyseResPoint.setCode("2000"); // analyseResPoint.setResImageUrl(analyseRequest.getObjectList().get(0).getImageUrlList()[0]); List analyseResPoints = new ArrayList<>(); analyseResPoints.add(analyseResPoint); AnalyseResItem analyseResItem = new AnalyseResItem(); analyseResItem.setObjectId(analyseRequest.getObjectList().get(0).getObjectId()); analyseResItem.setAlgFactory(algType); analyseResItem.setResults(analyseResPoints); List analyseResItems = new ArrayList<>(); analyseResItems.add(analyseResItem); analyseResult.setResultList(analyseResItems); System.out.println("返回值打印: 是否成功(0成功;1失败)" + analyseResPoint.getValue() + ",最高温度值" + analyseResPoint.getConf() + ",返回图片路径:" + analyseResPoint.getResImageUrl()); try { String analyseResultOutJson = JSONObject.toJSONString(analyseResult); log.info("[INFRARED] irPicAnalyse: feedbackUrl={}, analyseResultOutJson={}", feedbackUrl, analyseResultOutJson); // String result = HttpClientUtils.sendPostAgain(feedbackUrl, analyseResultOutJson); // log.info("[INFRARED] irPicAnalyse: feedbackUrl={}, result: {}", feedbackUrl, result); } catch (Exception e) { log.info("[INFRARED] irPicAnalyse: feedbackUrl={}, EXCEPTION: {}", feedbackUrl, e.getMessage()); } return ResponseEntity.ok().body("{\"code\":\"200\"}"); } public InfraredInfo calculatePicture(InfraPictureInfo infraPictureInfo, String picData) { InfraredInfo infraredInfo = new InfraredInfo(); return infraredInfo; } @Override public InputStream downloadCsv(String filePath) { log.info("解析csv图片地址" + filePath); String updatePath = truncateFileNameToCsv(filePath); InputStream inputStream = downloadFtp(updatePath); if (inputStream == null) { log.info("图片地址" + updatePath + "无返回"); } // if (!produceEnvironment) { // //调用华软接口 // String protocol = hrFtpUrl.substring(0, 6); // "ftp://" // String withoutProtocol = hrFtpUrl.substring(6); // "zthr02:zthr02@123.184.14.138:50021/" // String[] userAndHost = withoutProtocol.split("@"); // if (userAndHost.length != 2) { // throw new IllegalArgumentException("URL 格式错误,缺少 @ 分隔符"); // } // String[] userPass = userAndHost[0].split(":"); // String username = userPass[0]; // String password = userPass[1]; // String hostPort = userAndHost[1].replace("/", ""); // 移除末尾的 "/" // String[] hostAndPort = hostPort.split(":"); // String host = hostAndPort[0]; // int port = Integer.parseInt(hostAndPort[1]); // String imageName = Paths.get(filePath).getFileName().toString(); // //将图片上传到华软 // boolean isLoginHr = pic2Ftp(imageName, inputStreamPath, host, port, username, password); // String ftpUrlName = "[\"" + hrFtpUrl + imageName + "\"]"; // if (isLoginHr) { // //可以登陆华软ftp // inputStream = UploadFtpImageStream(hrUavUrl, ftpUrlName); // if (inputStream != null) { // return inputStream; // } // } else { // log.error("调用华软接口失败,使用本地1.csv文件!"); // inputStream = getClass().getClassLoader().getResourceAsStream("1.csv"); // return inputStream; // } // } else { // //共用同一ftp // String imageName = Paths.get(filePath).getFileName().toString(); // String ftpUrlName = "[\"ftp://" + ftpUrlAccount + ":" + ftpUrlPwd + "@" + ftpUrlAddress + ":" + ftpUrlPort + "/" + imageName + "\"]"; // inputStream = UploadFtpImageStream(hrUavUrl, ftpUrlName); // if (inputStream != null) { // // return inputStream; // } // } return inputStream; } // NVR跳转到预置位 public AjaxResult NvrCameraAngleJump(Camera camera) { lUserID = (Integer) redisService.redisTemplate.opsForValue().get(camera.getIp() + "_userId"); if (ObjectUtil.isEmpty(lUserID)) { NvrInfo nvrInfo = new NvrInfo(); nvrInfo.setNvrIp(camera.getIp()); nvrInfo.setServerPort(camera.getPort()); nvrInfo.setAccount(camera.getUserName()); nvrInfo.setPassword(camera.getPassword()); login_V40(nvrInfo); lUserID = (Integer) redisService.redisTemplate.opsForValue().get(camera.getIp() + "_userId"); } //参数:登录令牌,通道号,预置位跳转,跳转的预置位码 boolean gotoPreset = hcNetSDK.NET_DVR_PTZPreset_Other(lUserID, camera.getChannel(), HCNetSDK.GOTO_PRESET, camera.getPointNum()); if (!gotoPreset) { System.out.println("获取设备预置位跳转设备参数失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); return AjaxResult.error(hcNetSDK.NET_DVR_GetErrorMsg(new IntByReference(hcNetSDK.NET_DVR_GetLastError()))); } else { System.out.println("海康-成功跳转到预置位!"); } return AjaxResult.success(); } //NVR抓图 public AjaxResult NvrCameraPictrue(Camera camera) throws IOException { lUserID = (Integer) redisService.redisTemplate.opsForValue().get(camera.getIp() + "_userId"); if (ObjectUtil.isEmpty(lUserID)) { NvrInfo nvrInfo = new NvrInfo(); nvrInfo.setNvrIp(camera.getIp()); nvrInfo.setServerPort(camera.getPort()); nvrInfo.setAccount(camera.getUserName()); nvrInfo.setPassword(camera.getPassword()); login_V40(nvrInfo); lUserID = (Integer) redisService.redisTemplate.opsForValue().get(camera.getIp() + "_userId"); } HCNetSDK.NET_DVR_JPEGPARA dvrJpegpara = new HCNetSDK.NET_DVR_JPEGPARA(); dvrJpegpara.wPicSize = 3; dvrJpegpara.wPicQuality = 0; dvrJpegpara.write(); // 2. 创建临时存储目录(系统临时目录更安全) Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"), "hik_capture"); if (!Files.exists(tempDir)) { Files.createDirectories(tempDir); } // 3. 生成唯一文件名(IP+时间戳) String fileName = String.format("%s_%s.jpg", camera.getIp(), DateUtils.dateTimeNow("yyyyMMddHHmmss")); Path tempImagePath = tempDir.resolve(fileName); boolean b = hcNetSDK.NET_DVR_CaptureJPEGPicture(lUserID, camera.getChannel(), dvrJpegpara, tempImagePath.toString().getBytes("GBK")); if (!b) { System.out.println("设置设备进行抓图失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); return AjaxResult.error("设置设备进行抓图失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); } try (InputStream inputStream = Files.newInputStream(tempImagePath)) { picFtp("/2/" + fileName, inputStream, ftpUrlAddress, ftpUrlPort, ftpUrlAccount, ftpUrlPwd ); } catch (Exception e) { log.error("抓图并上传失败:{}", e.getMessage()); } finally { // 6. 确保删除临时文件 Files.deleteIfExists(tempImagePath); } return AjaxResult.success(); } //预置位获取-海康 @Override public String cameraYzwHikVision(Camera camera) { CameraPresetPoint cameraPreset = new CameraPresetPoint(); int lUserID = (int) redisTemplate.opsForValue().get(camera.getNvrip() + "_userId"); HCNetSDK.NET_DVR_PRESET_NAME[] presetNames = new HCNetSDK.NET_DVR_PRESET_NAME[HCNetSDK.MAX_PRESET_V30]; for (int i = 0; i < presetNames.length; i++) { presetNames[i] = new HCNetSDK.NET_DVR_PRESET_NAME(); presetNames[i].dwSize = presetNames[i].size(); presetNames[i].write(); } Pointer lpOutBuffer = new Memory(presetNames.length * presetNames[0].size()); int dwOutBufferSize = presetNames.length * presetNames[0].size(); IntByReference lpBytesReturned = new IntByReference(0); //boolean NET_DVR_GetDVRConfig(int lUserID, int dwCommand, int lChannel, Pointer lpOutBuffer, int dwOutBufferSize, IntByReference lpBytesReturned); boolean presetList = hcNetSDK.NET_DVR_GetDVRConfig(lUserID, HCNetSDK.NET_DVR_GET_PRESET_NAME, camera.getChannel(), lpOutBuffer, dwOutBufferSize, lpBytesReturned); if (!presetList) { System.out.println("获取预置位数据失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); } else { ByteBuffer byteBuffer = lpOutBuffer.getByteBuffer(0, lpBytesReturned.getValue()); byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // 设置字节顺序 String presetName = ""; for (int i = 0; i < HCNetSDK.MAX_PRESET_V30; i++) { HCNetSDK.NET_DVR_PRESET_NAME presetNameStruct = new HCNetSDK.NET_DVR_PRESET_NAME(); presetNameStruct.dwSize = byteBuffer.getInt(); presetNameStruct.wPresetNum = byteBuffer.getShort(); byteBuffer.get(presetNameStruct.byRes1); // 读取保留字节 byteBuffer.get(presetNameStruct.byName); // 读取名称 presetNameStruct.wPanPos = byteBuffer.getShort();//水平参数 presetNameStruct.wTiltPos = byteBuffer.getShort();//垂直参数 presetNameStruct.wZoomPos = byteBuffer.getShort();//变倍参数 byteBuffer.get(presetNameStruct.byRes); // 读取保留字节 if (presetNameStruct.wPresetNum != 0) // 输出预置位数据 { try { if (Integer.valueOf(presetNameStruct.wPanPos) != 0 && Integer.valueOf(presetNameStruct.wTiltPos) != 0) { presetName = presetName + new String(presetNameStruct.byName, "GBK").trim() + ":" + presetNameStruct.wPresetNum + ","; } System.out.println("预置位 " + presetNameStruct.wPresetNum + " 名称:" + new String(presetNameStruct.byName, "GBK").trim()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } } return ""; } }