You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

1221 lines
56 KiB

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<TemperatureData> 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<Coordinate> 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<Coordinate> 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<Float> 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<CSVRecord> 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<String> 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<AnalyseReqItem> 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<AnalyseResPoint> analyseResPoints = new ArrayList<>();
analyseResPoints.add(analyseResPoint);
AnalyseResItem analyseResItem = new AnalyseResItem();
analyseResItem.setObjectId(analyseRequest.getObjectList().get(0).getObjectId());
analyseResItem.setAlgFactory(algType);
analyseResItem.setResults(analyseResPoints);
List<AnalyseResItem> 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 "";
}
}