智能识别摄像头相关代码提交
This commit is contained in:
		
							parent
							
								
									57c0bf4dda
								
							
						
					
					
						commit
						202ecaa85a
					
				| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询厨房设备基础信息列表
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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("文件转换异常");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 "未知编码";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);	//登陆
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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("转换过程中发生错误");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue