智能识别摄像头相关代码提交

This commit is contained in:
liux 2025-09-25 13:59:43 +08:00
parent 57c0bf4dda
commit 202ecaa85a
13 changed files with 762 additions and 35 deletions

View File

@ -28,6 +28,12 @@
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>

View File

@ -1,5 +1,9 @@
package com.bonus.canteen.core.kitchen.domain.constants;
import com.bonus.canteen.core.account.constants.AccTradeStateEnum;
import com.bonus.canteen.core.account.constants.AccTradeTypeEnum;
import com.bonus.canteen.core.cook.enums.BasicMealtimeTypeEnum;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -10,15 +14,19 @@ import java.util.stream.Stream;
*/
public enum ViolationEnum {
UNWEAR_MASK(1, "未戴口罩"),
NOT_WEAR_COOK_CLOTHES(4, "未穿厨师服"),
NOT_WEAR_COOK_HAT(5, "未戴厨师帽"),
NOT_WEAR_GLOVES(6, "未戴手套"),
UNWEAR_MASK(1, "未戴口罩检测"),
MOUSE(2, "垃圾桶未盖检测"),
TRASH_CAN_NOT_COVER(3, "老鼠检测"),
NOT_WEAR_COOK_CLOTHES(4, "未穿厨师服检测"),
NOT_WEAR_COOK_HAT(5, "未戴厨师帽检测"),
NOT_WEAR_GLOVES(6, "未戴手套检测"),
SMOKE(7, "抽烟"),
CALL_PHONE(8, "打电话"),
DEVICE_RETURN(10, "设备归位");
private Integer key;
private String desc;
@ -36,6 +44,21 @@ public enum ViolationEnum {
));
}
public static Integer getKeyByDesc(String desc) {
ViolationEnum[] enums = values();
ViolationEnum[] var2 = enums;
int var3 = enums.length;
for(int var4 = 0; var4 < var3; ++var4) {
ViolationEnum anEnum = var2[var4];
if (anEnum.getDesc().equals(desc)) {
return anEnum.getKey();
}
}
return 100;
}
public Integer getKey() {
return this.key;
}

View File

@ -0,0 +1,15 @@
package com.bonus.canteen.core.kitchen.dto;
import lombok.Data;
/**
* @author xliu
* @date 2025/9/24 14:14
*/
@Data
public class VideoPhotoDTO {
private String channel;
private String recordTime;
private String jsonText;
}

View File

@ -0,0 +1,27 @@
package com.bonus.canteen.core.kitchen.feign;
import com.bonus.common.core.web.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
/**
* @author xliu
* @date 2025/9/24 14:19
*/
@FeignClient(value="bonus-file")
@Service
@Component
public interface FileServiceClient {
@PostMapping(value = "upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation("上传本地文件到服务器")
AjaxResult uploadVideoFile(MultipartFile file);
}

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bonus.canteen.core.kitchen.domain.KitchenDeviceInfo;
import com.bonus.canteen.core.kitchen.dto.KitchenDeviceListDTO;
import com.bonus.canteen.core.kitchen.vo.KitchenDeviceListVO;
import org.apache.ibatis.annotations.Param;
/**
* 厨房设备基础信息Mapper接口
@ -24,6 +25,8 @@ public interface KitchenDeviceInfoMapper extends BaseMapper<KitchenDeviceInfo> {
public KitchenDeviceInfo selectKitchenDeviceInfoByDeviceIdk(Long deviceId);
public KitchenDeviceInfo selectKitchenDeviceInfoByChannelAndDeviceType(@Param("channel") String channel,@Param("deviceType") String deviceType);
/**
* 查询厨房设备基础信息列表
*

View File

@ -2,17 +2,19 @@ package com.bonus.canteen.core.kitchen.service;
import java.util.List;
import com.bonus.canteen.core.kitchen.domain.KitchenStaffIllegalWarning;
import com.bonus.canteen.core.kitchen.dto.VideoPhotoDTO;
import org.springframework.web.multipart.MultipartFile;
/**
* 厨房员工违规报警Service接口
*
*
* @author xsheng
* @date 2025-06-16
*/
public interface IKitchenStaffIllegalWarningService {
/**
* 查询厨房员工违规报警
*
*
* @param illegalWarningId 厨房员工违规报警主键
* @return 厨房员工违规报警
*/
@ -20,7 +22,7 @@ public interface IKitchenStaffIllegalWarningService {
/**
* 查询厨房员工违规报警列表
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 厨房员工违规报警集合
*/
@ -28,7 +30,7 @@ public interface IKitchenStaffIllegalWarningService {
/**
* 新增厨房员工违规报警
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 结果
*/
@ -36,7 +38,7 @@ public interface IKitchenStaffIllegalWarningService {
/**
* 修改厨房员工违规报警
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 结果
*/
@ -44,7 +46,7 @@ public interface IKitchenStaffIllegalWarningService {
/**
* 批量删除厨房员工违规报警
*
*
* @param illegalWarningIds 需要删除的厨房员工违规报警主键集合
* @return 结果
*/
@ -52,9 +54,11 @@ public interface IKitchenStaffIllegalWarningService {
/**
* 删除厨房员工违规报警信息
*
*
* @param illegalWarningId 厨房员工违规报警主键
* @return 结果
*/
public int deleteKitchenStaffIllegalWarningByIllegalWarningId(Long illegalWarningId);
void uploadVideoPhoto(byte[] bytes, VideoPhotoDTO videoPhotoDTO);
}

View File

@ -1,29 +1,62 @@
package com.bonus.canteen.core.kitchen.service.impl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import com.bonus.canteen.core.kitchen.domain.KitchenDeviceInfo;
import com.bonus.canteen.core.kitchen.domain.constants.ViolationEnum;
import com.bonus.canteen.core.kitchen.dto.VideoPhotoDTO;
import com.bonus.canteen.core.kitchen.feign.FileServiceClient;
import com.bonus.canteen.core.kitchen.mapper.KitchenDeviceInfoMapper;
import com.bonus.canteen.core.kitchen.utils.TimestampUtils;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.houqin.constant.DeviceTypeEnum;
import com.bonus.common.houqin.utils.SM4EncryptUtils;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.system.api.domain.SysFile;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import com.bonus.canteen.core.kitchen.mapper.KitchenStaffIllegalWarningMapper;
import com.bonus.canteen.core.kitchen.domain.KitchenStaffIllegalWarning;
import com.bonus.canteen.core.kitchen.service.IKitchenStaffIllegalWarningService;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.annotation.Resource;
/**
* 厨房员工违规报警Service业务层处理
*
*
* @author xsheng
* @date 2025-06-16
*/
@Service
public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIllegalWarningService {
@Autowired
@Resource
private KitchenStaffIllegalWarningMapper kitchenStaffIllegalWarningMapper;
@Resource
private KitchenDeviceInfoMapper kitchenDeviceInfoMapper;
@Resource
private FileServiceClient fileServiceClient;
/**
* 查询厨房员工违规报警
*
*
* @param illegalWarningId 厨房员工违规报警主键
* @return 厨房员工违规报警
*/
@ -34,7 +67,7 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
/**
* 查询厨房员工违规报警列表
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 厨房员工违规报警
*/
@ -47,7 +80,7 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
/**
* 新增厨房员工违规报警
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 结果
*/
@ -64,7 +97,7 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
/**
* 修改厨房员工违规报警
*
*
* @param kitchenStaffIllegalWarning 厨房员工违规报警
* @return 结果
*/
@ -80,7 +113,7 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
/**
* 批量删除厨房员工违规报警
*
*
* @param illegalWarningIds 需要删除的厨房员工违规报警主键
* @return 结果
*/
@ -91,7 +124,7 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
/**
* 删除厨房员工违规报警信息
*
*
* @param illegalWarningId 厨房员工违规报警主键
* @return 结果
*/
@ -99,4 +132,104 @@ public class KitchenStaffIllegalWarningServiceImpl implements IKitchenStaffIlleg
public int deleteKitchenStaffIllegalWarningByIllegalWarningId(Long illegalWarningId) {
return kitchenStaffIllegalWarningMapper.deleteKitchenStaffIllegalWarningByIllegalWarningId(illegalWarningId);
}
@Override
public void uploadVideoPhoto(byte[] imageBytes, VideoPhotoDTO videoPhotoDTO) {
AjaxResult ar = fileServiceClient.uploadVideoFile(convertByteToMultipartFile(imageBytes,"demo.jpg"));
SysFile sysFile = ar.getDataAs(SysFile.class);
KitchenStaffIllegalWarning kitchenStaffIllegalWarning = new KitchenStaffIllegalWarning();
kitchenStaffIllegalWarning.setImgUrl(sysFile.getUrl());
kitchenStaffIllegalWarning.setRecordTime(new Date());
kitchenStaffIllegalWarning.setIllegalWarningType(2);
String ruleName = getFirstRuleName(videoPhotoDTO.getJsonText());
kitchenStaffIllegalWarning.setAlarmType( Long.valueOf(ViolationEnum.getKeyByDesc(ruleName)));
kitchenStaffIllegalWarning.setHandleState(2);
kitchenStaffIllegalWarning.setNotifyState(2);
kitchenStaffIllegalWarning.setCreateBy(SecurityUtils.getUsername());
kitchenStaffIllegalWarning.setCreateTime(DateUtils.getNowDate());
kitchenStaffIllegalWarning.setStaffId(11L);
KitchenDeviceInfo kitchenDeviceInfo = kitchenDeviceInfoMapper.selectKitchenDeviceInfoByChannelAndDeviceType(videoPhotoDTO.getChannel(), DeviceTypeEnum.CAMERA.getKey()+"");
if(kitchenDeviceInfo != null){
kitchenStaffIllegalWarning.setDeviceId(kitchenDeviceInfo.getDeviceId());
}else {
kitchenStaffIllegalWarning.setDeviceId(-1L);
}
kitchenStaffIllegalWarningMapper.insertKitchenStaffIllegalWarning(kitchenStaffIllegalWarning);
System.err.println("sysFile name=" + sysFile.getName()+" ,sysFile url="+sysFile.getUrl()+" ,ruleName="+ruleName);
//
// System.err.println("videoPhotoDTO=" + videoPhotoDTO);
}
private static MultipartFile convertByteToMultipartFile(byte[] imageBytes, String fileName) {
if (Objects.isNull(imageBytes)) {
throw new ServiceException("由于输入byte数组为空导致转换为MultipartFile失败");
}
String contentType = "image/jpeg";
FileItem item;
try {
FileItemFactory factory = new DiskFileItemFactory();
item = factory.createItem("file", contentType, false, fileName);
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(imageBytes.length);
OutputStream os = item.getOutputStream()) {
bos.write(imageBytes);
os.write(bos.toByteArray());
}
return new CommonsMultipartFile(item);
} catch (IOException e) {
throw new ServiceException("转换过程中发生错误");
}
}
public static boolean deleteFileByPath(String filePath) {
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println("文件删除成功: " + filePath);
return true;
} else {
System.out.println("文件删除失败: " + filePath);
return false;
}
} else {
System.out.println("文件不存在: " + filePath);
return false;
}
}
/**
* 提取第一个ruleName
*/
public static String getFirstRuleName(String jsonString) {
try {
return JsonPath.read(jsonString, "$.events.alertInfo[0].ruleInfo.ruleName");
} catch (Exception e) {
return null;
}
}
public MultipartFile convert(File file) {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("文件不存在");
}
String fileName = file.getName();
try {
String contentType = Files.probeContentType(file.toPath());
byte[] content = Files.readAllBytes(file.toPath());
return new MockMultipartFile(
"file", // 表单字段名
fileName, // 原始文件名
contentType, // 内容类型
content // 文件内容
);
}catch (Exception e){
throw new ServiceException("文件转换异常");
}
}
}

View File

@ -0,0 +1,177 @@
package com.bonus.canteen.core.kitchen.utils;
/**
* @author xliu
* @date 2025/9/24 16:28
*/
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* 字节数组与字符串转换工具类
*/
public class ByteStringUtils {
private ByteStringUtils() {
// 工具类防止实例化
}
// ==================== 字节数组转字符串 ====================
/**
* 使用UTF-8编码转换字节数组为字符串
*/
public static String bytesToUtf8String(byte[] bytes) {
return bytes != null ? new String(bytes, StandardCharsets.UTF_8) : null;
}
/**
* 使用指定编码转换字节数组为字符串
*/
public static String bytesToString(byte[] bytes, String charsetName) {
if (bytes == null) return null;
try {
return new String(bytes, charsetName);
} catch (java.io.UnsupportedEncodingException e) {
throw new IllegalArgumentException("不支持的编码: " + charsetName, e);
}
}
/**
* 使用Charset对象转换字节数组为字符串
*/
public static String bytesToString(byte[] bytes, Charset charset) {
return bytes != null ? new String(bytes, charset) : null;
}
/**
* 使用平台默认编码转换
*/
public static String bytesToStringDefault(byte[] bytes) {
return bytes != null ? new String(bytes) : null;
}
// ==================== 字符串转字节数组 ====================
/**
* 将字符串转换为UTF-8字节数组
*/
public static byte[] stringToUtf8Bytes(String str) {
return str != null ? str.getBytes(StandardCharsets.UTF_8) : null;
}
/**
* 将字符串转换为指定编码的字节数组
*/
public static byte[] stringToBytes(String str, String charsetName) {
if (str == null) return null;
try {
return str.getBytes(charsetName);
} catch (java.io.UnsupportedEncodingException e) {
throw new IllegalArgumentException("不支持的编码: " + charsetName, e);
}
}
/**
* 将字符串转换为指定Charset的字节数组
*/
public static byte[] stringToBytes(String str, Charset charset) {
return str != null ? str.getBytes(charset) : null;
}
// ==================== 十六进制转换 ====================
/**
* 字节数组转十六进制字符串
*/
public static String bytesToHexString(byte[] bytes) {
if (bytes == null) return null;
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
/**
* 十六进制字符串转字节数组
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.length() % 2 != 0) {
throw new IllegalArgumentException("十六进制字符串长度必须为偶数");
}
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i+1), 16));
}
return data;
}
// ==================== Base64编码解码 ====================
/**
* 字节数组转Base64字符串
*/
public static String bytesToBase64(byte[] bytes) {
return bytes != null ? Base64.getEncoder().encodeToString(bytes) : null;
}
/**
* Base64字符串转字节数组
*/
public static byte[] base64ToBytes(String base64String) {
return base64String != null ? Base64.getDecoder().decode(base64String) : null;
}
/**
* Base64 URL安全编码
*/
public static String bytesToBase64Url(byte[] bytes) {
return bytes != null ? Base64.getUrlEncoder().encodeToString(bytes) : null;
}
/**
* Base64 URL安全解码
*/
public static byte[] base64UrlToBytes(String base64UrlString) {
return base64UrlString != null ? Base64.getUrlDecoder().decode(base64UrlString) : null;
}
// ==================== 工具方法 ====================
/**
* 判断字节数组是否表示有效的UTF-8字符串
*/
public static boolean isValidUtf8(byte[] bytes) {
if (bytes == null) return false;
try {
Charset.availableCharsets().get("UTF-8").newDecoder()
.decode(java.nio.ByteBuffer.wrap(bytes));
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取字节数组的编码猜测
*/
public static String guessEncoding(byte[] bytes) {
// 简单的编码检测逻辑
if (isValidUtf8(bytes)) {
return "UTF-8";
}
// 可以添加更多编码检测逻辑
return "未知编码";
}
}

View File

@ -12,10 +12,18 @@ public class InitDevTask {
public void InitDev(){
boolean dd=initServer.hCNetSDK.NET_DVR_RemoteControl(initServer.lUserID,20005,null,0);
if(dd){
System.out.println("=========识别设备在线!");
System.out.println("=========门禁识别设备在线!");
return;
}else{
System.out.println("==========识别设备不在线!重新注册");
System.out.println("==========门禁识别设备不在线!重新注册");
}
boolean video=initServer.hCNetSDK.NET_DVR_RemoteControl(initServer.lUserID2,20005,null,0);
if(video){
System.out.println("=========智能摄像头识别设备在线!");
return;
}else{
System.out.println("==========智能摄像头识别设备不在线!重新注册");
}
if(initServer.hCNetSDK == null){
if(!initServer.CreateSDKInstance()){
@ -35,6 +43,7 @@ public class InitDevTask {
System.out.println("设置回调函数成功!");
}
}
initServer.Login(initServer.devIp,initServer.devUser,initServer.devPass,(short) 8000); //登陆
initServer.Login(initServer.devIp,initServer.devUser,initServer.devPass,(short) 8000,1); //登陆
initServer.Login(initServer.devIp2,initServer.devUser2,initServer.devPass2,(short) 8000,2); //登陆
}
}

View File

@ -1,24 +1,38 @@
package com.bonus.canteen.core.kitchen.utils.NetSDK;
import cn.hutool.core.thread.ThreadException;
import cn.hutool.extra.spring.SpringUtil;
import com.bonus.canteen.core.kitchen.domain.KitchenStaffEnterExitRecord;
import com.bonus.canteen.core.kitchen.dto.VideoPhotoDTO;
import com.bonus.canteen.core.kitchen.service.IKitchenStaffEnterExitRecordService;
import com.bonus.canteen.core.kitchen.service.IKitchenStaffIllegalWarningService;
import com.bonus.canteen.core.kitchen.utils.ByteStringUtils;
import com.bonus.canteen.core.kitchen.utils.ImageUtils;
import com.bonus.common.core.exception.ServiceException;
import com.sun.jna.Pointer;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.annotation.Resource;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
//布防回调函数
public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
IKitchenStaffIllegalWarningService kitchenStaffIllegalWarningService = SpringUtil.getBean(IKitchenStaffIllegalWarningService.class);
// @Resource
// private IKitchenStaffIllegalWarningService kitchenStaffIllegalWarningService;
//报警信息回调函数
@Override
public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
@ -128,6 +142,8 @@ public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
// deviceService server = SpringUtil.getBean(deviceService.class);
// System.out.println(adb.toString());
}
}catch (Exception e){
e.printStackTrace();
}
@ -221,9 +237,75 @@ public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
//报警事件json报文
System.out.println("仅测温报警事件:"+new String(dataByte));
break;
case HCNetSDK.COMM_UPLOAD_AIOP_VIDEO:
System.out.println("AI开放平台接入视频检测报警上传");
HCNetSDK.NET_AIOP_VIDEO_HEAD struAIOPVideo = new HCNetSDK.NET_AIOP_VIDEO_HEAD();
struAIOPVideo.write();
Pointer pAIOPVideo = struAIOPVideo.getPointer();
pAIOPVideo.write(0, pAlarmInfo.getByteArray(0, struAIOPVideo.size()), 0, struAIOPVideo.size());
struAIOPVideo.read();
System.out.println("视频任务ID" + new String(struAIOPVideo.szTaskID));
System.out.println("通道号:" + struAIOPVideo.dwChannel);
System.out.println("检测模型包ID" + new String(struAIOPVideo.szMPID));
String strTime = String.format("%04d", struAIOPVideo.struTime.wYear) +
String.format("%02d", struAIOPVideo.struTime.wMonth) +
String.format("%02d", struAIOPVideo.struTime.wDay) +
String.format("%02d", struAIOPVideo.struTime.wHour) +
String.format("%02d", struAIOPVideo.struTime.wMinute) +
String.format("%02d", struAIOPVideo.struTime.wSecond) +
String.format("%03d", struAIOPVideo.struTime.wMilliSec);
VideoPhotoDTO videoPhotoDTO=new VideoPhotoDTO();
//AIOPData数据
if (struAIOPVideo.dwAIOPDataSize > 0) {
FileOutputStream fout;
//将字节写入文件
long offset = 0;
ByteBuffer buffers = struAIOPVideo.pBufferAIOPData.getByteBuffer(offset, struAIOPVideo.dwAIOPDataSize);
byte[] bytes = new byte[struAIOPVideo.dwAIOPDataSize];
buffers.rewind();
buffers.get(bytes);
videoPhotoDTO.setJsonText(ByteStringUtils.bytesToString(bytes,"utf-8"));
}
//图片数据保存
if (struAIOPVideo.dwPictureSize > 0) {
//将字节写入文件
long offset = 0;
ByteBuffer buffers = struAIOPVideo.pBufferPicture.getByteBuffer(offset, struAIOPVideo.dwPictureSize);
byte[] bytes = new byte[struAIOPVideo.dwPictureSize];
buffers.rewind();
buffers.get(bytes);
videoPhotoDTO.setChannel(struAIOPVideo.dwChannel+"");
videoPhotoDTO.setRecordTime(strTime);
kitchenStaffIllegalWarningService.uploadVideoPhoto(bytes,videoPhotoDTO);
}
break;
default:
System.out.println("报警类型" + Integer.toHexString(lCommand));
break;
}
}
private static MultipartFile convertByteToMultipartFile(byte[] imageBytes, String fileName) {
if (Objects.isNull(imageBytes)) {
throw new ServiceException("由于输入byte数组为空导致转换为MultipartFile失败");
}
String contentType = "image/jpeg";
FileItem item;
try {
FileItemFactory factory = new DiskFileItemFactory();
item = factory.createItem("file", contentType, false, fileName);
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(imageBytes.length);
OutputStream os = item.getOutputStream()) {
bos.write(imageBytes);
os.write(bos.toByteArray());
}
return new CommonsMultipartFile(item);
} catch (IOException e) {
throw new ServiceException("转换过程中发生错误");
}
}
}

View File

@ -0,0 +1,226 @@
package com.bonus.canteen.core.kitchen.utils;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
/**
* @author xliu
* @date 2025/9/24 16:00
*/
public class TimestampUtils {
private static final DateTimeFormatter INPUT_FORMATTER =
DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
private static final DateTimeFormatter OUTPUT_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* 转换时间戳格式
* @param timestamp 原始时间戳 (yyyyMMddHHmmssSSS)
* @return 格式化后的日期字符串 (yyyy-MM-dd HH:mm:ss)
*/
public static String convertTimestamp(String timestamp) {
try {
LocalDateTime dateTime = LocalDateTime.parse(timestamp, INPUT_FORMATTER);
return dateTime.format(OUTPUT_FORMATTER);
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("时间戳格式不正确: " + timestamp, e);
}
}
/**
* 转换时间戳格式自定义输出格式
* @param timestamp 原始时间戳
* @param outputPattern 输出格式模式
* @return 格式化后的日期字符串
*/
public static String convertTimestamp(String timestamp, String outputPattern) {
try {
LocalDateTime dateTime = LocalDateTime.parse(timestamp, INPUT_FORMATTER);
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern(outputPattern);
return dateTime.format(customFormatter);
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("时间戳格式不正确: " + timestamp, e);
}
}
// 支持多种可能的时间戳格式
private static final DateTimeFormatter FORMATTER_17 =
DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); // 17位20250924165312000
private static final DateTimeFormatter FORMATTER_14 =
DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); // 14位20250924165312
private static final DateTimeFormatter FORMATTER_19 =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 标准格式
/**
* 智能解析时间戳自动检测格式
*/
public static LocalDateTime parseTimestamp(String timestamp) {
if (timestamp == null || timestamp.trim().isEmpty()) {
throw new IllegalArgumentException("时间戳不能为空");
}
String cleanTimestamp = timestamp.trim();
try {
// 根据长度尝试不同的格式
switch (cleanTimestamp.length()) {
case 17:
return LocalDateTime.parse(cleanTimestamp, FORMATTER_17);
case 14:
return LocalDateTime.parse(cleanTimestamp, FORMATTER_14);
case 19:
return LocalDateTime.parse(cleanTimestamp, FORMATTER_19);
default:
throw new DateTimeParseException("不支持的时间戳格式长度: " + cleanTimestamp.length(),
cleanTimestamp, 0);
}
} catch (DateTimeParseException e) {
// 尝试更灵活的解析方式
return flexibleParse(cleanTimestamp);
}
}
/**
* 灵活解析处理各种边界情况
*/
private static LocalDateTime flexibleParse(String timestamp) {
// 移除可能的分隔符
String clean = timestamp.replaceAll("[-:\\s]", "");
try {
// 尝试标准17位格式
if (clean.length() == 17) {
return LocalDateTime.parse(clean, FORMATTER_17);
}
// 如果长度不足补零
else if (clean.length() < 17) {
String padded = String.format("%-17s", clean).replace(' ', '0');
return LocalDateTime.parse(padded, FORMATTER_17);
}
// 如果长度超长截取
else if (clean.length() > 17) {
String truncated = clean.substring(0, 17);
return LocalDateTime.parse(truncated, FORMATTER_17);
}
} catch (DateTimeParseException e) {
// 最后尝试手动解析
return manualParse(timestamp);
}
throw new DateTimeParseException("无法解析时间戳: " + timestamp, timestamp, 0);
}
/**
* 手动解析最保险的方式
*/
private static LocalDateTime manualParse(String timestamp) {
try {
String clean = timestamp.trim().replaceAll("[^0-9]", "");
if (clean.length() < 14) {
throw new IllegalArgumentException("时间戳长度不足至少需要14位数字");
}
// 提取各个部分
int year = Integer.parseInt(clean.substring(0, 4));
int month = Integer.parseInt(clean.substring(4, 6));
int day = Integer.parseInt(clean.substring(6, 8));
int hour = Integer.parseInt(clean.substring(8, 10));
int minute = Integer.parseInt(clean.substring(10, 12));
int second = Integer.parseInt(clean.substring(12, 14));
// 毫秒可选
int millis = 0;
if (clean.length() > 14) {
String millisStr = clean.substring(14, Math.min(17, clean.length()));
millisStr = String.format("%-3s", millisStr).replace(' ', '0');
millis = Integer.parseInt(millisStr);
}
return LocalDateTime.of(year, month, day, hour, minute, second, millis * 1_000_000);
} catch (Exception e) {
throw new DateTimeParseException("手动解析时间戳失败: " + e.getMessage(), timestamp, 0);
}
}
/**
* 转换时间戳为 Date 对象修复版
*/
public static Date convertToDate(String timestamp) {
try {
LocalDateTime dateTime = parseTimestamp(timestamp);
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("时间戳格式不正确: " + timestamp +
",期望格式: yyyyMMddHHmmssSSS (17位)", e);
}
}
/**
* 转换时间戳为字符串
*/
public static String convertToString(String timestamp) {
try {
LocalDateTime dateTime = parseTimestamp(timestamp);
return dateTime.format(OUTPUT_FORMATTER);
} catch (DateTimeParseException e) {
throw new IllegalArgumentException("时间戳格式不正确: " + timestamp, e);
}
}
/**
* 安全转换返回null而不是抛出异常
*/
public static Date convertToDateSafely(String timestamp) {
try {
return convertToDate(timestamp);
} catch (Exception e) {
System.err.println("时间戳转换失败: " + timestamp + ", 错误: " + e.getMessage());
return null;
}
}
/**
* 验证时间戳格式
*/
public static boolean isValidTimestamp(String timestamp) {
try {
parseTimestamp(timestamp);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取时间戳的格式信息
*/
public static String getTimestampInfo(String timestamp) {
if (timestamp == null) return "null";
return String.format("原始: %s, 长度: %d, 是否有效: %s",
timestamp, timestamp.length(), isValidTimestamp(timestamp));
}
// 使用示例
public static void main(String[] args) {
String timestamp = "20250924165051000";
System.out.println("默认格式: " + convertTimestamp(timestamp));
System.out.println("中文格式: " + convertTimestamp(timestamp, "yyyy年MM月dd日 HH时mm分ss秒"));
System.out.println("简洁格式: " + convertTimestamp(timestamp, "yyyy/MM/dd HH:mm"));
System.out.println("date格式: " + convertToDate(timestamp));
//20250924165051000
// 输出:
// 默认格式: 2025-09-24 15:27:07
// 中文格式: 2025年09月24日 15时27分07秒
// 简洁格式: 2025/09/24 15:27
}
}

View File

@ -26,6 +26,11 @@ public class initServer implements CommandLineRunner {
public static String devIp = "192.168.1.69";
public static String devUser = "admin";
public static String devPass = "hzx12345";
public static int lUserID2 = -1;//用户句柄
public static String devIp2 = "192.168.10.89";
public static String devUser2 = "admin";
public static String devPass2 = "JYY202509";
@Override
public void run(String... args) throws Exception {
try{
@ -48,8 +53,10 @@ public class initServer implements CommandLineRunner {
}
}
// Login("192.168.0.199","admin","bouns@ltfk",(short) 8000); //登陆
Login(devIp,devUser,devPass,(short) 8000); //登陆
Login(devIp,devUser,devPass,(short) 8000,1); //登陆
Login(devIp2,devUser2,devPass2,(short) 8000,2); //登陆
Alarm.SetAlarm(lUserID);
Alarm.SetAlarm(lUserID2);
// getAllUser();
// UserManage.searchUserInfo(lUserID);
// UserManage.addUserInfo(lUserID,"15357932237","贾胜凯22");
@ -149,7 +156,7 @@ public class initServer implements CommandLineRunner {
* @param psw 密码
* @param port 端口默认8000
*/
public static void Login(String ipadress, String user, String psw, short port) {
public static void Login(String ipadress, String user, String psw, short port,int type) {
//注册
HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
String m_sDeviceIP = ipadress;//设备ip地址
@ -165,16 +172,26 @@ public class initServer implements CommandLineRunner {
m_strLoginInfo.bUseAsynLogin = false; //是否异步登录0- 1-
m_strLoginInfo.write();
HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID == -1){
System.out.println("登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
return;
if(type == 1){
lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID == -1){
System.out.println("门禁登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
}else{
System.out.println("门禁登录成功!");
m_strDeviceInfo.read();
iCharEncodeType = m_strDeviceInfo.byCharEncodeType;
}
}else{
System.out.println("登录成功!");
m_strDeviceInfo.read();
iCharEncodeType = m_strDeviceInfo.byCharEncodeType;
return;
lUserID2 = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID2 == -1){
System.out.println("智能识别登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
}else{
System.out.println("智能识别登录成功!");
m_strDeviceInfo.read();
iCharEncodeType = m_strDeviceInfo.byCharEncodeType;
}
}
}
}

View File

@ -205,4 +205,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{deviceId}
</foreach>
</update>
<select id="selectKitchenDeviceInfoByChannelAndDeviceType" resultMap="KitchenDeviceInfoResultk">
<include refid="selectKitchenDeviceInfoVo"/>
where channel = #{channel} and device_type=#{deviceType} and del_flag = '0'
</select>
</mapper>