From 8f77c1e993de08422fce577c1ea44c1de73b3311 Mon Sep 17 00:00:00 2001 From: 4670101279 Date: Fri, 24 Jun 2022 17:11:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=91=84=E5=83=8F=E6=9C=BA=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-code/pom.xml | 27 + .../camera/controller/CameraController.java | 136 ++ .../com/ruoyi/code/camera/domain/Camera.java | 63 + .../code/camera/mapper/CameraMapper.java | 17 + .../code/camera/scheduled/RegisterServer.java | 45 + .../code/camera/service/ICameraService.java | 27 + .../service/impl/CameraServiceImpl.java | 92 ++ .../src/main/java/utils/CameraUtil.java | 87 ++ ruoyi-code/src/main/java/utils/Play.java | 278 +++++ .../src/main/java/utils/RegisterUtil.java | 1064 ++++++++++++++++ .../main/java/utils/device_auto_register.java | 1107 +++++++++++++++++ .../resources/mapper.camera/CameraMapper.xml | 7 + 12 files changed, 2950 insertions(+) create mode 100644 ruoyi-code/pom.xml create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/controller/CameraController.java create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/domain/Camera.java create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/mapper/CameraMapper.java create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/scheduled/RegisterServer.java create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/service/ICameraService.java create mode 100644 ruoyi-code/src/main/java/com/ruoyi/code/camera/service/impl/CameraServiceImpl.java create mode 100644 ruoyi-code/src/main/java/utils/CameraUtil.java create mode 100644 ruoyi-code/src/main/java/utils/Play.java create mode 100644 ruoyi-code/src/main/java/utils/RegisterUtil.java create mode 100644 ruoyi-code/src/main/java/utils/device_auto_register.java create mode 100644 ruoyi-code/src/main/resources/mapper.camera/CameraMapper.xml diff --git a/ruoyi-code/pom.xml b/ruoyi-code/pom.xml new file mode 100644 index 0000000..f271723 --- /dev/null +++ b/ruoyi-code/pom.xml @@ -0,0 +1,27 @@ + + + + ruoyi + com.ruoyi + 3.8.1 + + 4.0.0 + + ruoyi-code + + + ruoyi-code + + + + + + + com.ruoyi + ruoyi-common + + + + diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/controller/CameraController.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/controller/CameraController.java new file mode 100644 index 0000000..1595be4 --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/controller/CameraController.java @@ -0,0 +1,136 @@ +package com.ruoyi.code.camera.controller; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.page.R; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.code.camera.domain.Camera; +import com.ruoyi.code.camera.service.ICameraService; +import com.sun.jna.NativeLong; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import utils.CameraUtil; +import utils.RegisterUtil; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 摄像机Controller + * + * @author ruoyi + * @date 2022-06-21 + */ +@RestController +@RequestMapping("/web/camera") +public class CameraController extends BaseController +{ + @Resource + private ICameraService cameraService; + + /** + * 查询列表 + */ + @PreAuthorize("@ss.hasPermi('web:camera:list')") + @RequestMapping("/list") + public R list(@RequestParam Map params){ + return cameraService.queryPage(params); + } + + /** + * 获取详细信息 + */ + @RequestMapping("/info/{id}") + @PreAuthorize("@ss.hasPermi('web:camera:query')") + public R info(@PathVariable("id") Long id){ + Camera camera = cameraService.getById(id); + + return R.ok().put("data", camera); + } + + + /** + * 导出列表 + */ + @PreAuthorize("@ss.hasPermi('web:camera:export')") + @Log(title = "列表", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, Camera camera) + { + List list = cameraService.list(); + ExcelUtil util = new ExcelUtil(Camera.class); + util.exportExcel(response, list, "列表数据"); + } + + /** + * 新增 + */ + @RequestMapping("/add") + @Log(title = "Camera", businessType = BusinessType.INSERT) + @PreAuthorize("@ss.hasPermi('web:camera:add')") + public R add(@RequestBody Camera camera){ + cameraService.save(camera); + return R.ok(); + } + + /** + * 修改 + */ + @RequestMapping("/edit") + @PreAuthorize("@ss.hasPermi('web:camera:edit')") + @Log(title = "Camera", businessType = BusinessType.UPDATE) + public R edit(@RequestBody Camera camera){ + cameraService.updateById(camera); + return R.ok(); + } + + /** + * 删除 + */ + @RequestMapping("/delete/{ids}") + @PreAuthorize("@ss.hasPermi('web:camera:remove')") + @Log(title = "Camera", businessType = BusinessType.DELETE) + public R delete(@PathVariable Long[] ids){ + cameraService.removeByIds(Arrays.asList(ids)); + return R.ok(); + } + + + @RequestMapping("register") + public R register(){ + return cameraService.register(); + } + + @RequestMapping("reboot/{id}") + public R reboot(@PathVariable Long id){ + Camera c = cameraService.getById(id); + if(StringUtils.isNotBlank(c.getLoginId())) { + System.out.println("reboot loginID:"+c.getLoginId()); + NativeLong nl = new NativeLong(Long.parseLong(c.getLoginId())); + boolean result = CameraUtil.deal(nl); + if(result){ + c.setLoginId(""); + c.setStatus(0); + cameraService.updateById(c); + return R.ok("设备重启成功,请等待几分钟后重新使用"); + } + } + return R.error("设备重启失败"); + } + + + @RequestMapping("showVideo/{id}") + public void showVideo(@PathVariable Long id){ + Camera c = cameraService.getById(id); + System.out.println("show loginID:"+c.getLoginId()); + RegisterUtil window = new RegisterUtil(); + window.m_frame.setVisible(true); + window.showVideo(new NativeLong(Long.parseLong(c.getLoginId()))); + } + +} diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/domain/Camera.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/domain/Camera.java new file mode 100644 index 0000000..8646198 --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/domain/Camera.java @@ -0,0 +1,63 @@ +package com.ruoyi.code.camera.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + + +/** + * 摄像机对象 camera + * + * @author ruoyi + * @date 2022-06-21 + */ +@Data +@TableName("camera") +public class Camera implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** $column.columnComment */ + @TableId(type = IdType.INPUT) + private Long id; + + /** 设备名 */ + private String name; + + /** 设备ip */ + private String ip; + + /** 设备端口 */ + private Integer port; + + /** 设备登录账号 */ + private String username; + + /** 设备登录密码 */ + private String password; + + /** 设备序列号 */ + private String devsn; + + /** 状态 */ + private Integer status; + + private String loginId; + + /** 首次注册时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date firstTime; + + /** 注册更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + +} diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/mapper/CameraMapper.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/mapper/CameraMapper.java new file mode 100644 index 0000000..01e3530 --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/mapper/CameraMapper.java @@ -0,0 +1,17 @@ +package com.ruoyi.code.camera.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.code.camera.domain.Camera; +import org.apache.ibatis.annotations.Mapper; + +/** + * Mapper接口 + * + * @author ruoyi + * @date 2022-06-21 + */ +@Mapper +public interface CameraMapper extends BaseMapper +{ + +} diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/scheduled/RegisterServer.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/scheduled/RegisterServer.java new file mode 100644 index 0000000..a991927 --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/scheduled/RegisterServer.java @@ -0,0 +1,45 @@ +package com.ruoyi.code.camera.scheduled; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.code.camera.domain.Camera; +import com.ruoyi.code.camera.service.ICameraService; +import com.ruoyi.common.core.page.R; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; + +/*@Author: tongw + *@CreateDate: 2020/8/11 8:58 + *@Description: + **/ + +@Component +@Configuration +@EnableScheduling +public class RegisterServer { + @Autowired + private ICameraService cameraService; + + @PostConstruct + public void synStart(){ + start(); + } + + private void start(){ + R result = cameraService.register(); + if("0".equals(result.get("code").toString())){ + System.out.println("主动注册服务已启动"); + }else{ + System.out.println("主动注册服务启动失败"); + } + } + +} diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/ICameraService.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/ICameraService.java new file mode 100644 index 0000000..3ecf969 --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/ICameraService.java @@ -0,0 +1,27 @@ +package com.ruoyi.code.camera.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.page.R; +import com.ruoyi.code.camera.domain.Camera; + +import java.util.Map; + +/** + * Service接口 + * + * @author ruoyi + * @date 2022-06-21 + */ +public interface ICameraService extends IService +{ + /** + * 查询 + */ + R queryPage(Map params); + + R register(); + + void online(String ip,int port,String username,String password,String devsn,String loginID); + + void outline(String loginID); +} diff --git a/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/impl/CameraServiceImpl.java b/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/impl/CameraServiceImpl.java new file mode 100644 index 0000000..68f794a --- /dev/null +++ b/ruoyi-code/src/main/java/com/ruoyi/code/camera/service/impl/CameraServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.code.camera.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.page.R; +import com.ruoyi.common.utils.Query; +import com.ruoyi.code.camera.domain.Camera; +import com.ruoyi.code.camera.mapper.CameraMapper; +import com.ruoyi.code.camera.service.ICameraService; +import org.springframework.stereotype.Service; +import utils.RegisterUtil; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * Service业务层处理 + * + * @author ruoyi + * @date 2022-06-21 + */ +@Service("cameraService") +public class CameraServiceImpl extends ServiceImpl implements ICameraService +{ + @Override + public R queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return R.ok().put("count", page.getTotal()).put("data", page.getRecords()); + } + + @Override + public R register(){ + //清空所有摄像机状态 + List list = list(); + list.forEach(d -> { + d.setLoginId(""); + d.setStatus(0); + }); + updateBatchById(list); + + RegisterUtil window = new RegisterUtil(); + //先停 + window.onBtnStopRegServer(); + //再开 + boolean result = window.onBtnStartRegServer(); + if(result){ + return R.ok("服务启动成功,请等待几分钟后重新使用"); + } + return R.error("服务启动失败"); + } + + @Override + public void online(String ip,int port,String username,String password,String devsn,String loginID){ + Date now = new Date(); + Camera c = getOne(new QueryWrapper().eq("devsn",devsn)); + if(c == null){ + c = new Camera(); + c.setIp(ip); + c.setPort(port); + c.setUsername(username); + c.setPassword(password); + c.setDevsn(devsn); + c.setStatus(1); + c.setLoginId(loginID); + c.setFirstTime(now); + c.setUpdateTime(now); + save(c); + }else{ + c.setIp(ip); + c.setPort(port); + c.setLoginId(loginID); + c.setStatus(1); + c.setUpdateTime(now); + updateById(c); + } + } + @Override + public void outline(String loginID){ + Camera c = getOne(new QueryWrapper().eq("login_id",loginID)); + if(c != null){ + c.setLoginId(""); + c.setStatus(0); + updateById(c); + } + } +} diff --git a/ruoyi-code/src/main/java/utils/CameraUtil.java b/ruoyi-code/src/main/java/utils/CameraUtil.java new file mode 100644 index 0000000..7834f0e --- /dev/null +++ b/ruoyi-code/src/main/java/utils/CameraUtil.java @@ -0,0 +1,87 @@ +package utils; + +import com.ruoyi.common.utils.DateUtils; +import com.sun.jna.NativeLong; +import com.sun.jna.ptr.IntByReference; +import sdk.java.lib.netmanager.NetLib; +import sdk.java.lib.netmanager.NetStructs; + +import java.util.Date; + +public class CameraUtil { + public static void main(String[] args) { + + NetLib.instance.Net_Init(null, null); + String strIp="36.133.93.214"; + int nPort= 27778; + String strUsername="admin"; + String strPassword="admin123"; + IntByReference error = null; + NativeLong loginID = NetLib.instance.Net_LoginDevice(strIp, nPort, strUsername, strPassword, null, error); + System.out.println(loginID); + + //重启设备 +// boolean bResult = NetLib.instance.Net_RebootDevice(loginID); +// System.out.println("Net_RebootDevice = " + bResult); + +// boolean r2 = NetLib.instance.Net_LogoutDevice(loginID); +// System.out.println("r2 = " + r2); +// NetLib.instance.Net_Exit(); + } + + public static boolean deal(NativeLong loginID){ + boolean res = NetLib.instance.Net_RebootDevice(loginID); + int error = NetLib.instance.Net_LastError(); + System.out.println("reboot errorCode = "+ error); + return res; + } + + private static void sleep(int nTime) + { + try { + Thread.sleep(nTime * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * 设置当前时间 + * @param loginID + */ + public static void setNowTime(NativeLong loginID){ + NetStructs.STU_TIME.ByReference stuTimeRef = new NetStructs.STU_TIME.ByReference(); + boolean bGet = NetLib.instance.Net_GetDeviceTime(loginID, stuTimeRef, 6000); + + System.out.printf("Get time = %b, time = %04d-%02d-%02d %02d:%02d:%02d\n", + bGet, stuTimeRef.nYear, stuTimeRef.nMonth, stuTimeRef.nDay, + stuTimeRef.nHour, stuTimeRef.nMinute, stuTimeRef.nSecond); + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + String time = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",new Date()); + // 修改时间 + stuTimeRef.nYear = Integer.parseInt(time.substring(0,4)); + stuTimeRef.nMonth = Integer.parseInt(time.substring(5,7)); + stuTimeRef.nDay = Integer.parseInt(time.substring(8,10)); + stuTimeRef.nHour = Integer.parseInt(time.substring(11,13)); + stuTimeRef.nMinute = Integer.parseInt(time.substring(14,16)); + stuTimeRef.nSecond = Integer.parseInt(time.substring(17,19)); + + System.out.println("Set time, time"+ + stuTimeRef.nYear+"-"+ stuTimeRef.nMonth+"-"+ stuTimeRef.nDay+" "+ + stuTimeRef.nHour+":"+ stuTimeRef.nMinute+":"+stuTimeRef.nSecond); + + NetLib.instance.Net_SetDeviceTime(loginID, stuTimeRef, 2000); + + // 再获取时间 + bGet = NetLib.instance.Net_GetDeviceTime(loginID, stuTimeRef, 2000); + System.out.println("Get time = %b, time =" + + stuTimeRef.nYear+"-"+ stuTimeRef.nMonth+"-"+ stuTimeRef.nDay+" "+ + stuTimeRef.nHour+":"+ stuTimeRef.nMinute+":"+stuTimeRef.nSecond); + } +} diff --git a/ruoyi-code/src/main/java/utils/Play.java b/ruoyi-code/src/main/java/utils/Play.java new file mode 100644 index 0000000..b6d2b27 --- /dev/null +++ b/ruoyi-code/src/main/java/utils/Play.java @@ -0,0 +1,278 @@ +package utils; + +import com.sun.jna.Native; +import com.sun.jna.NativeLong; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.IntByReference; +import sdk.java.lib.DataUtils; +import sdk.java.lib.netmanager.NetDelegates; +import sdk.java.lib.netmanager.NetEnums; +import sdk.java.lib.netmanager.NetLib; +import sdk.java.lib.playmanager.*; + +import javax.swing.*; +import java.awt.*; + +public class Play { + + private IntByReference m_nPlayPort = new IntByReference(0); // 当前设备的播放端口 + + + public static class DecodeCallBack implements PlayDelegates.fDecodeCallBack + { + @Override + public void invoke(int nPort, Pointer pFrameDecodeInfo, Pointer pFrameInfo, Pointer pUserData) + { + // pFrameDecodeInfo, pFrameInfo 均可获取帧类型、子帧类型 + // 如果是视频帧,子帧类型则为 I 帧、P 帧...,以枚举值 ENUM_SUB_FRAME_TYPE 为准 + + // pFrameDecodeInfo 解码帧内容 + // 如果是音频帧,有音频帧数据 + // 如果是视频帧,有视频帧 YUV 数据 + + // pFrameInfo 解码帧属性信息 + // 其中帧数据/裸数据可以自定义处理 + PlayStructs.FRAME_ATTRI_INFO_EX frameInfo = new PlayStructs.FRAME_ATTRI_INFO_EX(); + DataUtils.sdk_data_ptrToStructure(pFrameInfo, frameInfo); + + if(frameInfo.nFrameType == PlayEnums.ENUM_MEDIA_FRAME_TYPE.MEDIA_FRAME_TYPE_VIDEO) + { + if(frameInfo.nSubFrameType == PlayEnums.ENUM_SUB_FRAME_TYPE.SUB_FRAME_TYPE_VIDEO_I) + { + //System.out.println("Video Frame I"); + } + else if(frameInfo.nSubFrameType == PlayEnums.ENUM_SUB_FRAME_TYPE.SUB_FRAME_TYPE_VIDEO_P) + { + //System.out.println("Video Frame P"); + } + else if(frameInfo.nSubFrameType == PlayEnums.ENUM_SUB_FRAME_TYPE.SUB_FRAME_TYPE_VIDEO_B) + { + //System.out.println("Video Frame B"); + } + else if(frameInfo.nSubFrameType == PlayEnums.ENUM_SUB_FRAME_TYPE.SUB_FRAME_TYPE_VIDEO_S) + { + //System.out.println("Video Frame S"); + } + else if(frameInfo.nSubFrameType == PlayEnums.ENUM_SUB_FRAME_TYPE.SUB_FRAME_TYPE_VIDEO_MJPEG) + { + //System.out.println("Video Frame MJPEG"); + } + else + { + //System.out.println("Video Frame Unknown"); + } + } + else if(frameInfo.nFrameType == PlayEnums.ENUM_MEDIA_FRAME_TYPE.MEDIA_FRAME_TYPE_AUDIO) + { + //System.out.print("Audio Frame\n"); + } + } + } + + DecodeCallBack _cbDecodeCallBack = new DecodeCallBack(); + public static class GetIVSInfoCallBackFunc implements PlayDelegates.fGetIVSInfoCallBack + { + @Override + public void invoke(Pointer pBuf, int nType, int nLen, int nRealLen, Pointer pReserved, Pointer pUserData) + { + // 智能帧物体类型 + if(nType == PlayEnums.SA_DD_PARSE_TYPE.DD_PARSE_TYPE_INTL) + { + int nObjNum = nLen / new PlayStructs.SA_DD_INTL_OBJECT().size(); + System.out.printf("nObjNum = %d\n", nObjNum); + PlayStructs.SA_DD_INTL_OBJECT[]pObjArr = new PlayStructs.SA_DD_INTL_OBJECT[nObjNum]; + for(int i = 0; i < nObjNum; i++) + { + pObjArr[i] = new PlayStructs.SA_DD_INTL_OBJECT(); + } + DataUtils.sdk_data_ptrToStructureArray(pBuf, pObjArr); + + for (int i = 0; i < nObjNum; i++) + { + // 人脸物体 + if(PlayEnums.SA_DD_INTL_OBJECT_TYPE.DD_INITL_OBJECT_FACE == pObjArr[i].nAttriType) + { + PlayStructs.SA_DD_OBJECT_FACE pFaceObj = new PlayStructs.SA_DD_OBJECT_FACE(); + DataUtils.sdk_data_ptrToStructure(pObjArr[i].pData, pFaceObj); + + System.out.printf("left = %d, top = %d, right = %d, bottom = %d\n", pFaceObj.shape_rect.x - pFaceObj.shape_rect.xSize, + pFaceObj.shape_rect.y - pFaceObj.shape_rect.ySize, pFaceObj.shape_rect.x + pFaceObj.shape_rect.xSize, + pFaceObj.shape_rect.y + pFaceObj.shape_rect.ySize); + } + else + { + // ... + } + } + } + } + } + + GetIVSInfoCallBackFunc _cbGetIVSInfoCallBackFunc = new GetIVSInfoCallBackFunc(); + + // 播放回调 + private static class RealPlayDataCallBack implements NetDelegates.fRealPlayDataCallBack + { + @Override + public void invoke(NativeLong realHandle, int dataType, Pointer ptrBuffer, int bufferSize, NativeLong userdata) + { + if(0 != userdata.longValue()) + { + int nPort = (int) userdata.longValue(); + // 将码流数据传给play库来播放 + PlayLib.instance.PlayMS_InputData(nPort, ptrBuffer, bufferSize); + } + } + } + + private NativeLong m_realPlayHandle = new NativeLong(0); + RealPlayDataCallBack _realPlayDataCallBack = new RealPlayDataCallBack(); + + private Panel m_panel_video = null; + private NativeLong m_loginHandle = new NativeLong(0); + + public boolean startPlay() + { + if(0 == m_loginHandle.longValue()) + { + JOptionPane.showMessageDialog(null, "还未登录!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + Pointer ptrWnd = Native.getComponentPointer(m_panel_video); + + boolean bResult = PlayLib.instance.PlayMS_GetFreePort(m_nPlayPort); + + if(!bResult) + { + JOptionPane.showMessageDialog(null, "设备繁忙,不能网络播放!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + // 设置实时流模式 + PlayLib.instance.PlayMS_SetLogOption(3); + bResult = PlayLib.instance.PlayMS_SetStreamOpenMode(m_nPlayPort.getValue(), PlayDefs.STREAM_TYPE_REALTIME); + // 打开流,并初始化缓存池(大小 MIN_SOURCE_BUF_SIZE - MAX_SOURCE_BUF_SIZE) + bResult &= PlayLib.instance.PlayMS_OpenStream(m_nPlayPort.getValue(), 1024 * 1024 * 20); + // 在窗口 hwnd 播放流数据 + bResult &= PlayLib.instance.PlayMS_Play(m_nPlayPort.getValue(), ptrWnd); + // 设置解码回调函数,解码回调中获取帧内容和帧信息 + bResult &= PlayLib.instance.PlayMS_SetVisibleDecodeCallBack(m_nPlayPort.getValue(), _cbDecodeCallBack, null); + // 设置智能帧数据回调 + bResult &= PlayLib.instance.PlayMS_SetIVSCallBack(m_nPlayPort.getValue(), _cbGetIVSInfoCallBackFunc, null); + + if(!bResult) + { + JOptionPane.showMessageDialog(null, "播放视频失败!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + int channel = 0; // 目前通道号常用为 0 + int nType = NetEnums.EM_REALPLAY_STREAM_TYPE.REALPLAY_STREAM_TYPE_REAL; // 实时播放流 + m_realPlayHandle = NetLib.instance.Net_RealPlay(m_loginHandle, channel, null, nType); + + if(0 == m_realPlayHandle.longValue()) + { + JOptionPane.showMessageDialog(null, "实时播放失败!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + NetLib.instance.Net_SetRealDataCallBack(m_realPlayHandle, _realPlayDataCallBack, new NativeLong(this.m_nPlayPort.getValue())); + + /* + IntByReference nBrightness = new IntByReference(0); + IntByReference nContrast = new IntByReference(0); + IntByReference nHue = new IntByReference(0); + IntByReference nSaturation = new IntByReference(0); + if(getVideoBasicEffect(nBrightness, nContrast, nHue, nSaturation)) + { + // 最大为128,转换为0-100显示 + this.m_slider_brighness.setValue(calEffectValue(nBrightness.getValue())); + this.m_slider_contrast.setValue(calEffectValue(nContrast.getValue())); + this.m_slider_hue.setValue(calEffectValue(nHue.getValue())); + this.m_slider_saturation.setValue(calEffectValue(nSaturation.getValue())); + } + */ + + + System.out.println("播放实时视频成功!"); + return true; + } + + public boolean stopPlay() + { + if(0 < this.m_nPlayPort.getValue()) + { + PlayLib.instance.PlayMS_SetLogOption(3); + PlayLib.instance.PlayMS_Stop(this.m_nPlayPort.getValue()); + PlayLib.instance.PlayMS_ResetSourceBuffer(this.m_nPlayPort.getValue()); + PlayLib.instance.PlayMS_CloseStream(this.m_nPlayPort.getValue()); + } + + if(0 != m_loginHandle.longValue()) + { + boolean bRet = NetLib.instance.Net_StopRealPlay(m_realPlayHandle); + if(!bRet) + { + System.out.println("停止播放实时视频失败!"); + } + else + { + System.out.println("停止播放实时视频成功!"); + } + + this.m_panel_video.repaint(); + this.m_nPlayPort.setValue(0); + this.m_realPlayHandle = new NativeLong(0); + } + + return true; + } + + + + public boolean logout() + { + if(0 == m_loginHandle.longValue()) + { + return true; + } + + boolean bRet = NetLib.instance.Net_LogoutDevice(m_loginHandle); + if(!bRet) + { + System.out.println("设备登出失败!"); + } + else + { + System.out.println("设备登出成功!"); + } + + m_loginHandle = new NativeLong(0); + + return bRet; + } + + public boolean login() + { + String m_ip="192.168.1.64"; + int m_port= 27778; + String m_username="tongw"; + String m_password="tongw123"; + IntByReference m_error = null; + // 登录设备 + m_loginHandle = NetLib.instance.Net_LoginDevice(m_ip, m_port, m_username, m_password, null, m_error); + if(0 == m_loginHandle.longValue()) + { + JOptionPane.showMessageDialog(null, "登录失败!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + System.out.println("设备登录成功!"); + return true; + } + + public static void main(String[] args) { + + } +} diff --git a/ruoyi-code/src/main/java/utils/RegisterUtil.java b/ruoyi-code/src/main/java/utils/RegisterUtil.java new file mode 100644 index 0000000..6bf3210 --- /dev/null +++ b/ruoyi-code/src/main/java/utils/RegisterUtil.java @@ -0,0 +1,1064 @@ +package utils; + +import com.ruoyi.code.camera.domain.Camera; +import com.ruoyi.code.camera.service.ICameraService; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.BeanUtil; +import com.ruoyi.common.utils.StringUtils; +import com.sun.jna.Native; +import com.sun.jna.NativeLong; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import sdk.java.common.GlobalTool; +import sdk.java.lib.DataUtils; +import sdk.java.lib.netmanager.NetDelegates; +import sdk.java.lib.netmanager.NetEnums; +import sdk.java.lib.netmanager.NetEnums.EM_LOGIN_PROTOCAL_TYPE; +import sdk.java.lib.netmanager.NetEnums.EM_REALPLAY_STREAM_TYPE; +import sdk.java.lib.netmanager.NetLib; +import sdk.java.lib.netmanager.NetStructs; +import sdk.java.lib.playmanager.PlayDefs; +import sdk.java.lib.playmanager.PlayEnums.ENUM_RENDER_TYPE; +import sdk.java.lib.playmanager.PlayLib; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.*; + + +// 主动注册流程概要 +///////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * + * 1、服务端开启主动注册监听服务(即此demo); + * 2、设备端网络设置中,设置服务端IP和端口号,并使能主动注册;(步骤1、2没有固定的先后顺序); + * 3、服务端等待设备上送IP、端口号和设备SN; + * 4、服务端收到设备上送信息后,根据上送信息登陆设备,建立链接; + * 5、登陆成功后,正常使用其余接口; + * 6、接口调用。。。; + * 7、断开连接的方式有以下两种,需注意两种方式都需要服务端主动登出设备: + * 1)。设备端停止主动注册,服务端进入断线回调,并在回调中登出设备; + * 2)。服务端停止注册服务,并登出所有设备; + * + * 注:此demo中的设备用户名和密码默认为 admin 和 admin123,以便登陆时使用,实际使用中,需自行管理每台设备的用户名和密码 + * + */ +///////////////////////////////////////////////////////////////////////////////////////////////////// +@Component +public class RegisterUtil implements ActionListener { + +// private String m_jtfServerIP = "172.16.46.58"; + private String m_jtfServerIP = "192.168.1.11"; + private String m_jtfServerPort = "8020"; + private String m_jtfDevUsername = "admin"; + private String m_jtfDevPassword = "admin123"; + + public String getUserName() {return m_jtfDevUsername;} + public String getPassword() {return m_jtfDevPassword;} + + public JFrame m_frame; + private JButton m_btnStopServer; + private JButton m_btnStartServer; + + private JButton m_btnStopPlay; + private JButton m_btnStartPlay; + + private JLabel m_lblLoadPic; + private JCheckBox m_chkRealLoad; + + private JCheckBox m_chkIntelliDraw; + + private Panel m_panelVideo; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private JList m_listInfo; + private JScrollPane m_jspListInfo; + private Vector m_listInfoData = new Vector(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private int m_nCurSelDeviceIndex = -1; + private List m_listDevices = new ArrayList<>(); // 界面显示的设备列表 + private List m_listDevicesData = new ArrayList<>(); + + // 用于存放所有主动注册成功的设备的登陆ID,作为设备的唯一标识 + public List m_listLoginIDs = new ArrayList<>(); + public NativeLong getCurDeviceLoginID() + { + if(-1 == this.m_nCurSelDeviceIndex) + return new NativeLong(0); + return m_listLoginIDs.get(this.m_nCurSelDeviceIndex); + } + + public void setCurDeviceLoginID(NativeLong lLoginID) + { + if(-1 == this.m_nCurSelDeviceIndex) + return; + m_listLoginIDs.set(this.m_nCurSelDeviceIndex, lLoginID); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + public boolean bExit = true; + + private NativeLong m_lRegServerHandle = new NativeLong(0); // 主动注册服务句柄 + private NativeLong m_lPlayHandle = new NativeLong(0); // 当前设备的播放句柄 + private NativeLong m_lRealloadHandle = new NativeLong(0); // 当前设备的订阅句柄 + + private IntByReference m_nPlayPort = new IntByReference(0); // 当前设备的播放端口 + + private String m_strFilePath = "./TmpAutoReg"; + + // 将类对象存在map中,方便在回调中使用用户自定义变量作为key来获取类对象 + private static Map s_mapFlagToClass = new HashMap(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Create the application. + */ + public RegisterUtil() + { + initialize(); + initilizeRyNetLib(); + } + + protected void finalize() + { + destroyRyNetLib(); + } + + /** + * Initialize the contents of the frame. + */ + private void initialize() { + m_frame = new JFrame(); + m_frame.setTitle("查看实时视频"); + + m_frame.setSize(1400,1100) ; + Toolkit toolkit = Toolkit.getDefaultToolkit(); + int x = (int)(toolkit.getScreenSize().getWidth()-m_frame.getWidth())/2; + int y = (int)(toolkit.getScreenSize().getHeight()-m_frame.getHeight())/2; + m_frame.setLocation(x, y); + +// m_frame.setBounds(100, 100, 1400, 1100); + m_frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + m_frame.getContentPane().setLayout(null); + + m_panelVideo = new Panel(); + m_panelVideo.setBounds(0, 0, 1400, 1100); + m_panelVideo.setBackground(Color.BLACK); + m_frame.getContentPane().add(m_panelVideo); + + } + + + public boolean showVideo(NativeLong loginID){ + if(0 == loginID.longValue()) + { + System.out.println("还未登录!"); + return false; + } + + Pointer ptrWnd = Native.getComponentPointer(this.m_panelVideo); + + boolean bResult = PlayLib.instance.PlayMS_GetFreePort(m_nPlayPort); + + if(!bResult) + { + System.out.println("设备繁忙,不能网络播放!"); + return false; + } + + // 设置实时流模式 + PlayLib.instance.PlayMS_SetLogOption(7); + bResult = PlayLib.instance.PlayMS_SetStreamOpenMode(m_nPlayPort.getValue(), PlayDefs.STREAM_TYPE_REALTIME); + // 打开流,并初始化缓存池(大小 MIN_SOURCE_BUF_SIZE - MAX_SOURCE_BUF_SIZE) + bResult &= PlayLib.instance.PlayMS_OpenStream(m_nPlayPort.getValue(), 1024 * 1024 * 20); + // 在窗口 hwnd 播放流数据 + bResult &= PlayLib.instance.PlayMS_Play(m_nPlayPort.getValue(), ptrWnd); + + if(!bResult) + { + System.out.println("播放视频失败!"); + return false; + } + + int channel = 0; // 目前通道号常用为 0 + int nType = EM_REALPLAY_STREAM_TYPE.REALPLAY_STREAM_TYPE_REAL; // 实时播放流 + this.m_lPlayHandle = NetLib.instance.Net_RealPlay(loginID, channel, null, nType); + + if(0 == this.m_lPlayHandle.longValue()) + { + JOptionPane.showMessageDialog(null, "实时播放失败!", "提示", JOptionPane.ERROR_MESSAGE); + return false; + } + + NetLib.instance.Net_SetRealDataCallBack(this.m_lPlayHandle, _realPlayDataCallBack, new NativeLong(this.m_nPlayPort.getValue())); + System.out.println("播放实时视频成功."); + + return true; + } + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /* + * 设备断开连接后后,需要服务端主动登出设备,以保证下次能正常登陆 + * + */ + public class DisConnectCallBack implements NetDelegates.fDisConnectCallBack + { + @Override + public void invoke(NativeLong loginID, String ip, int port, NativeLong userdata) + { + int nFlag = (int) userdata.longValue(); + if(1 == nFlag) + { + s_mapFlagToClass.get(nFlag).appendNotifyInfo(String.format("设备已断连!")); + s_mapFlagToClass.get(nFlag).logout(loginID); + s_mapFlagToClass.get(nFlag).removeDevice(loginID, ip, port); + } + } + } + + DisConnectCallBack _cbDisConnectCallBack = new DisConnectCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 设备登陆信息 + public static class STU_LOGIN_INFO extends Structure + { + public String strIP; + public int nPort; + public String strUserName; + public String strPassword; + public String strDevSN; + + protected List getFieldOrder() + { + return Arrays.asList(new String [] { "strIP", "nPort", "strUserName", + "strPassword", "strDevSN"}); + } + + public static class ByReference extends STU_LOGIN_INFO implements Structure.ByReference + { + } + + public static class ByValue extends STU_LOGIN_INFO implements Structure.ByValue + { + } + }; + + /* + * 用于存放登陆信息的列表 + */ + public Vector m_listLoginInfos = new Vector(); + + /* + * 开启服务后,设备会主动建立连接,并上送自己的IP、端口和SN号(ptrParam)以便登陆使用。 + * 支持多设备登陆 + * + */ + public class RegServerCallBack implements NetDelegates.fRegServerCallBack + { + @Override + public void invoke(NativeLong handle, + String ip, + int port, + int command, + Pointer ptrParam, + int paramLen, + NativeLong userdata) + { + // 通过userData获取类对象,userData为调用Net_RegStartServer时传入的值 + int nFlag = (int) userdata.longValue(); + if(1 == nFlag) + { + /* + * 1、此处需判断指令,只有为1时,才执行登陆 + * 2、第一个参数handle不是开启注册服务的handle,而是每台设备的链接句柄; + * + */ + if(1 == command) + { + STU_LOGIN_INFO loginInfo = new STU_LOGIN_INFO(); + loginInfo.strIP = ip; + loginInfo.nPort = port; + loginInfo.strUserName = s_mapFlagToClass.get(nFlag).getUserName(); + loginInfo.strPassword = s_mapFlagToClass.get(nFlag).getPassword(); + loginInfo.strDevSN = DataUtils.sdk_data_ptrToString(ptrParam, 0, paramLen, null); + + // 保存登陆信息,并在单开的线程中实现登陆 + s_mapFlagToClass.get(nFlag).m_listLoginInfos.addElement(loginInfo); + } + } + } + } + RegServerCallBack _cbRegServerCallBack = new RegServerCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /* + * 登陆监听 + * 此处通过线程来实现登陆,是因为我们不建议用户在sdk接口的回调中,直接再去调用其他sdk的接口,而是通过另单开一个线程来接受数据,并执行登陆 + */ + public class LoginListenThread extends Thread + { + private RegisterUtil m_runDevAutoReg; + + public LoginListenThread(RegisterUtil runDevAutoReg) + { + m_runDevAutoReg = runDevAutoReg; + } + + @Override + public void run() + { + while(!m_runDevAutoReg.bExit) + { + if(m_runDevAutoReg.m_listLoginInfos.size() > 0) + { + STU_LOGIN_INFO loginInfo = m_runDevAutoReg.m_listLoginInfos.get(0); + System.out.println(loginInfo.strIP); + System.out.println(loginInfo.nPort); + System.out.println(loginInfo.strDevSN); + // 登陆 + m_runDevAutoReg.login(loginInfo.strIP, loginInfo.nPort, loginInfo.strDevSN); + + m_runDevAutoReg.m_listLoginInfos.removeElementAt(0); + } + } + } + + public void startLoginListenThread() + { + m_runDevAutoReg.bExit = false; + this.start(); + } + + public void stopLoginListenThread() + { + m_runDevAutoReg.bExit = true; + } + } + private LoginListenThread m_loginListenThread = null; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 播放回调 + private class RealPlayDataCallBack implements NetDelegates.fRealPlayDataCallBack + { + @Override + public void invoke(NativeLong realHandle, int dataType, Pointer ptrBuffer, int bufferSize, NativeLong userdata) + { + if(0 != userdata.longValue()) + { + int nPort = (int) userdata.longValue(); + // 将码流数据传给play库来播放 + PlayLib.instance.PlayMS_InputData(nPort, ptrBuffer, bufferSize); + } + } + } + + RealPlayDataCallBack _realPlayDataCallBack = new RealPlayDataCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 解析事件信息 + private Object ParseEventInfoStructure(int eventType, Pointer ptrEventInfo) + { + if(null == ptrEventInfo) + { + System.out.printf("Parse event info [type:%d], null.\n", eventType); + return null; + } + + Object obj = null; + + ////////////////////////////////////////////////////////////////////// + if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_WHOLE) + { + NetStructs.STU_EVENT_FACE_SNAP_WHOLE stu = new NetStructs.STU_EVENT_FACE_SNAP_WHOLE(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_PART) + { + NetStructs.STU_EVENT_FACE_SNAP_PART stu = new NetStructs.STU_EVENT_FACE_SNAP_PART(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_WHOLE) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE stu = new NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_CUTOUT) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT stu = new NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + ////////////////////////////////////////////////////////////////////// + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS) + { + NetStructs.STU_EVENT_TRAFFIC_PASS stu = new NetStructs.STU_EVENT_TRAFFIC_PASS(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS_CUTOUT) + { + NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT stu = new NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else + { + System.out.printf("Event[type:%d], not supported.\n", eventType); + return null; + } + + return obj; + } + + // 保存事件数据到本地(事件数据即图片数据) + private boolean SaveBufferToLocal(int eventType, Object eventInfoObj, Pointer ptrBuffer, int bufferSize) + { + System.out.printf("Save buffer, Event:%d.\n", eventType); + + if(null == eventInfoObj || null == ptrBuffer || 0 >= bufferSize) + { + System.out.printf("Illegal params, Event:%d.\n", eventType); + return false; + } + + String filename = null; + + // 人脸检测背景图 + if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_WHOLE) + { + NetStructs.STU_EVENT_FACE_SNAP_WHOLE info = (NetStructs.STU_EVENT_FACE_SNAP_WHOLE)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸检测抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_PART) + { + NetStructs.STU_EVENT_FACE_SNAP_PART info = (NetStructs.STU_EVENT_FACE_SNAP_PART)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸识别背景图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_WHOLE) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE info = (NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸识别抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_CUTOUT) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT info = (NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + ////////////////////////////////////// + // 交通卡口背景图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS) + { + NetStructs.STU_EVENT_TRAFFIC_PASS info = (NetStructs.STU_EVENT_TRAFFIC_PASS)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 交通卡口抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS_CUTOUT) + { + NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT info = (NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + + if(null == filename || filename.isEmpty()) + { + System.out.printf("Get file name fail, Event:%d.\n", eventType); + return false; + } + + if(!DataUtils.sdk_data_fileWrite(ptrBuffer, 0, 0, bufferSize, filename)) + { + System.out.printf("Save file[%s] fail, Event:%d.\n", filename, eventType); + return false; + } + + refreshImage(filename); + + return true; + } + + // 智能分析数据回调,图片订阅事件上报时触发 + private class AnalyzeDataFunc implements NetDelegates.fAnalyzeDataCallBack + { + @Override + public void invoke(NativeLong analyzeHandle, int eventType, Pointer ptrEventInfo, Pointer ptrBuffer, + int bufferSize, NativeLong userdata, int sequence, Pointer ptrReserved) { + + System.out.printf("Handle:%d, Event:%d.\n", analyzeHandle.intValue(), eventType); + + // 解析事件信息 + Object eventInfoObj = ParseEventInfoStructure(eventType, ptrEventInfo); + + // 保存事件数据 + // 建议新建一个事件信息和图片数据(拷贝)处理队列,另起线程处理; + // 建议不要在回调函数中进行影响性能的操作,这里作为演示 + SaveBufferToLocal(eventType, eventInfoObj, ptrBuffer, bufferSize); + + /*......*/ + } + } + + private AnalyzeDataFunc _analyzeDataFunc = new AnalyzeDataFunc(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private void initilizeRyNetLib() + { + s_mapFlagToClass.put(1, this); + + // 用户可以自定义 fDisConnectCB + NetLib.instance.Net_Init(_cbDisConnectCallBack, new NativeLong(1)); + + NetLib.instance.Net_SetLogFolder("D:\\soft\\control\\TmpAutoReg"); + + NetLib.instance.Net_SetLogOption(7); + +// GlobalTool.createDirectory(this.m_strFilePath); + } + + private void destroyRyNetLib() + { + NetLib.instance.Net_Exit(); + } + + void refreshEnables() + { +// boolean bStartServer = this.m_lRegServerHandle.longValue() != 0; +// boolean bLogin = getCurDeviceLoginID().longValue() != 0; +// boolean bPlay = this.m_lPlayHandle.longValue() != 0; +// boolean bRealload = this.m_lRealloadHandle.longValue() != 0; +// +// this.m_btnStartServer.setEnabled(!bStartServer); +// this.m_btnStopServer.setEnabled(bStartServer); +// +// this.m_btnStartPlay.setEnabled(bLogin && !bPlay); +// this.m_btnStopPlay.setEnabled(bLogin && bPlay); +// +// this.m_chkRealLoad.setEnabled(bLogin); +// this.m_chkRealLoad.setSelected(bRealload); +// +// this.m_chkIntelliDraw.setEnabled(bLogin && bPlay); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 提示信息 + public void appendNotifyInfo(String info) + { +// this.m_listInfoData.addElement(info); +// this.m_listInfo.setListData(m_listInfoData); +// this.m_listInfo.setSelectedIndex(m_listInfoData.size() - 1); +// +// Point p = new Point(); +// p.setLocation(0, this.m_listInfo.getHeight()); +// this.m_jspListInfo.getViewport().setViewPosition(p); + } + + public boolean login(String ip, int port, String strDevSN) + { + ICameraService cameraService = BeanUtil.getBean(ICameraService.class); + + String strUserName; + strUserName = this.m_jtfDevUsername; // 默认admin + String strUserPassword; + strUserPassword = this.m_jtfDevPassword; // 默认admin123 + IntByReference nErr = new IntByReference(0); + + // 此接口专为 主动注册登陆 接口,与 Net_LoginDevice 有区别 + NativeLong lLoginID = NetLib.instance.Net_LoginDeviceSpec( + ip, + port, + strUserName, + strUserPassword, + EM_LOGIN_PROTOCAL_TYPE.EM_LOGIN_PROTOCAL_TYPE_REG_SERVER, + strDevSN, + null, + nErr); + + if(0 != lLoginID.longValue()) + { + // ip port strUserName strUserPassword strDevSN + this.m_listLoginIDs.add(lLoginID); + this.m_listDevicesData.add(String.format("%s_%d_%s", ip, port, strDevSN)); + this.m_listDevices.addAll(this.m_listDevicesData); + + cameraService.online(ip,port,strUserName,strUserPassword,strDevSN,lLoginID.toString()); + int error = NetLib.instance.Net_LastError(); + System.out.println("errorCode = "+ error); + System.out.println(String.format("登陆成功, 设备ip = %s, port = %d, SN = %s.", ip, port, strDevSN)); + refreshEnables(); + } + else + { + int nErrCode = NetLib.instance.Net_LastError(); + System.out.printf(String.format("登陆失败, ip = %s, port = %d, SN = %s, errorCode = %d.", ip, port, strDevSN, nErrCode)); + } + System.out.println("======================================="); + System.out.println("device list : "+m_listDevicesData.toString()); + System.out.println("======================================="); + return true; + } + + public void logoutAll() + { + for(int i=0; i getLoginIDs(){ + List list = this.m_listLoginIDs; + return list; + } +} diff --git a/ruoyi-code/src/main/java/utils/device_auto_register.java b/ruoyi-code/src/main/java/utils/device_auto_register.java new file mode 100644 index 0000000..5dda8be --- /dev/null +++ b/ruoyi-code/src/main/java/utils/device_auto_register.java @@ -0,0 +1,1107 @@ +package utils; + +import com.sun.jna.Native; +import com.sun.jna.NativeLong; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import sdk.java.common.GlobalTool; +import sdk.java.lib.DataUtils; +import sdk.java.lib.netmanager.NetDelegates; +import sdk.java.lib.netmanager.NetEnums; +import sdk.java.lib.netmanager.NetEnums.EM_LOGIN_PROTOCAL_TYPE; +import sdk.java.lib.netmanager.NetEnums.EM_REALPLAY_STREAM_TYPE; +import sdk.java.lib.netmanager.NetLib; +import sdk.java.lib.netmanager.NetStructs; +import sdk.java.lib.playmanager.PlayDefs; +import sdk.java.lib.playmanager.PlayEnums.ENUM_RENDER_TYPE; +import sdk.java.lib.playmanager.PlayLib; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.*; + + +// 主动注册流程概要 +///////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * + * 1、服务端开启主动注册监听服务(即此demo); + * 2、设备端网络设置中,设置服务端IP和端口号,并使能主动注册;(步骤1、2没有固定的先后顺序); + * 3、服务端等待设备上送IP、端口号和设备SN; + * 4、服务端收到设备上送信息后,根据上送信息登陆设备,建立链接; + * 5、登陆成功后,正常使用其余接口; + * 6、接口调用。。。; + * 7、断开连接的方式有以下两种,需注意两种方式都需要服务端主动登出设备: + * 1)。设备端停止主动注册,服务端进入断线回调,并在回调中登出设备; + * 2)。服务端停止注册服务,并登出所有设备; + * + * 注:此demo中的设备用户名和密码默认为 admin 和 admin123,以便登陆时使用,实际使用中,需自行管理每台设备的用户名和密码 + * + */ +///////////////////////////////////////////////////////////////////////////////////////////////////// + +public class device_auto_register implements ActionListener { + + private JFrame m_frame; + + private String m_jtfServerIP = "192.168.1.11"; + private String m_jtfServerPort = "8020"; + private String m_jtfDevUsername = "admin"; + public String getUserName() {return m_jtfDevUsername;} + private String m_jtfDevPassword = "admin123"; + public String getPassword() {return m_jtfDevPassword;} + + private JButton m_btnStopServer; + private JButton m_btnStartServer; + + private JButton m_btnStopPlay; + private JButton m_btnStartPlay; + + private JLabel m_lblLoadPic; + private JCheckBox m_chkRealLoad; + + private JCheckBox m_chkIntelliDraw; + + private Panel m_panelVideo; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private JList m_listInfo; + private JScrollPane m_jspListInfo; + private Vector m_listInfoData = new Vector(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private int m_nCurSelDeviceIndex = -1; + private JList m_listDevices; // 界面显示的设备列表 + private Vector m_listDevicesData = new Vector(); + + // 用于存放所有主动注册成功的设备的登陆ID,作为设备的唯一标识 + public Vector m_listLoginIDs = new Vector(); + public NativeLong getCurDeviceLoginID() + { + if(-1 == this.m_nCurSelDeviceIndex) + return new NativeLong(0); + return m_listLoginIDs.get(this.m_nCurSelDeviceIndex); + } + + public void setCurDeviceLoginID(NativeLong lLoginID) + { + if(-1 == this.m_nCurSelDeviceIndex) + return; + m_listLoginIDs.set(this.m_nCurSelDeviceIndex, lLoginID); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + public boolean bExit = true; + + private NativeLong m_lRegServerHandle = new NativeLong(0); // 主动注册服务句柄 + private NativeLong m_lPlayHandle = new NativeLong(0); // 当前设备的播放句柄 + private NativeLong m_lRealloadHandle = new NativeLong(0); // 当前设备的订阅句柄 + + private IntByReference m_nPlayPort = new IntByReference(0); // 当前设备的播放端口 + + private String m_strFilePath = "./TmpAutoReg"; + + // 将类对象存在map中,方便在回调中使用用户自定义变量作为key来获取类对象 + private static Map s_mapFlagToClass = new HashMap(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Create the application. + */ + public device_auto_register() + { + initialize(); + initilizeRyNetLib(); + } + + protected void finalize() + { + destroyRyNetLib(); + } + + /** + * Initialize the contents of the frame. + */ + private void initialize() + { + m_frame = new JFrame(); + m_frame.setTitle("主动注册Demo"); + m_frame.setBounds(100, 100, 921, 691); + m_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + m_frame.getContentPane().setLayout(null); + + JLabel label = new JLabel("服务端地址:"); + label.setBounds(6, 11, 84, 26); + m_frame.getContentPane().add(label); + +// m_jtfServerIP = new JTextField(); +// m_jtfServerIP.setBounds(80, 11, 120, 26); +// m_frame.getContentPane().add(m_jtfServerIP); +// +// JLabel label_1 = new JLabel("服务端端口:"); +// label_1.setBounds(6, 47, 84, 26); +// m_frame.getContentPane().add(label_1); +// +// m_jtfServerPort = new JTextField(); +// m_jtfServerPort.setBounds(80, 47, 120, 26); +// m_frame.getContentPane().add(m_jtfServerPort); + + JLabel label_2 = new JLabel("设备用户名:"); + label_2.setBounds(6, 83, 84, 26); + m_frame.getContentPane().add(label_2); + +// m_jtfDevUsername = new JTextField(); +// m_jtfDevUsername.setBounds(80, 83, 120, 26); +// m_jtfDevUsername.setText("admin"); +// m_frame.getContentPane().add(m_jtfDevUsername); +// +// JLabel label_3 = new JLabel("设备密码:"); +// label_3.setBounds(6, 119, 84, 26); +// m_frame.getContentPane().add(label_3); +// +// m_jtfDevPassword = new JTextField(); +// m_jtfDevPassword.setBounds(80, 119, 120, 26); +// m_jtfDevPassword.setText("admin123"); +// m_frame.getContentPane().add(m_jtfDevPassword); + + m_btnStartServer = new JButton("打开服务"); + m_btnStartServer.addActionListener(this); + m_btnStartServer.setBounds(6, 158, 192, 26); + m_frame.getContentPane().add(m_btnStartServer); + + m_btnStopServer = new JButton("停止服务"); + m_btnStopServer.addActionListener(this); + m_btnStopServer.setBounds(6, 194, 192, 26); + m_btnStopServer.setEnabled(false); + m_frame.getContentPane().add(m_btnStopServer); + + m_btnStartPlay = new JButton("开始播放"); + m_btnStartPlay.addActionListener(this); + m_btnStartPlay.setBounds(6, 361, 192, 26); + m_btnStartPlay.setEnabled(false); + m_frame.getContentPane().add(m_btnStartPlay); + + m_btnStopPlay = new JButton("停止播放"); + m_btnStopPlay.addActionListener(this); + m_btnStopPlay.setBounds(6, 397, 192, 26); + m_btnStopPlay.setEnabled(false); + m_frame.getContentPane().add(m_btnStopPlay); + + m_chkRealLoad = new JCheckBox("开启图片实时订阅"); + m_chkRealLoad.addActionListener(this); + m_chkRealLoad.setBounds(6, 433, 192, 26); + m_chkRealLoad.setEnabled(false); + m_frame.getContentPane().add(m_chkRealLoad); + + m_lblLoadPic = new JLabel(); + m_lblLoadPic.setBounds(6, 469, 192, 144); + m_lblLoadPic.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + m_frame.getContentPane().add(m_lblLoadPic); + + m_chkIntelliDraw = new JCheckBox("开启智能数据绘制"); + m_chkIntelliDraw.addActionListener(this); + m_chkIntelliDraw.setBounds(6, 619, 194, 23); + m_chkIntelliDraw.setEnabled(false); + m_frame.getContentPane().add(m_chkIntelliDraw); + + m_panelVideo = new Panel(); + m_panelVideo.setBounds(211, 10, 686, 526); + m_panelVideo.setBackground(Color.BLACK); + m_frame.getContentPane().add(m_panelVideo); + + m_listInfo = new JList(); + m_listInfo.setBounds(211, 542, 686, 100); + m_jspListInfo = new JScrollPane(m_listInfo); + m_jspListInfo.setBounds(211, 542, 686, 100); + m_frame.getContentPane().add(m_jspListInfo); + + m_listDevices = new JList(); + m_listDevices.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) + { + if(1 == e.getClickCount()) + { + onSelChangeDevice(); + } + } + }); + m_listDevices.setBounds(6, 230, 194, 121); + JScrollPane jspListDevice = new JScrollPane(m_listDevices); + jspListDevice.setBounds(6, 230, 194, 121); + m_frame.getContentPane().add(jspListDevice); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /* + * 设备断开连接后后,需要服务端主动登出设备,以保证下次能正常登陆 + * + */ + public class DisConnectCallBack implements NetDelegates.fDisConnectCallBack + { + @Override + public void invoke(NativeLong loginID, String ip, int port, NativeLong userdata) + { + int nFlag = (int) userdata.longValue(); + if(1 == nFlag) + { + s_mapFlagToClass.get(nFlag).appendNotifyInfo(String.format("设备已断连!")); + s_mapFlagToClass.get(nFlag).logout(loginID); + s_mapFlagToClass.get(nFlag).removeDevice(loginID, ip, port); + } + } + } + + DisConnectCallBack _cbDisConnectCallBack = new DisConnectCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 设备登陆信息 + public static class STU_LOGIN_INFO extends Structure + { + public String strIP; + public int nPort; + public String strUserName; + public String strPassword; + public String strDevSN; + + protected List getFieldOrder() + { + return Arrays.asList(new String [] { "strIP", "nPort", "strUserName", + "strPassword", "strDevSN"}); + } + + public static class ByReference extends STU_LOGIN_INFO implements Structure.ByReference + { + } + + public static class ByValue extends STU_LOGIN_INFO implements Structure.ByValue + { + } + }; + + /* + * 用于存放登陆信息的列表 + */ + public Vector m_listLoginInfos = new Vector(); + + /* + * 开启服务后,设备会主动建立连接,并上送自己的IP、端口和SN号(ptrParam)以便登陆使用。 + * 支持多设备登陆 + * + */ + public class RegServerCallBack implements NetDelegates.fRegServerCallBack + { + @Override + public void invoke(NativeLong handle, + String ip, + int port, + int command, + Pointer ptrParam, + int paramLen, + NativeLong userdata) + { + // 通过userData获取类对象,userData为调用Net_RegStartServer时传入的值 + int nFlag = (int) userdata.longValue(); + if(1 == nFlag) + { + /* + * 1、此处需判断指令,只有为1时,才执行登陆 + * 2、第一个参数handle不是开启注册服务的handle,而是每台设备的链接句柄; + * + */ + if(1 == command) + { + STU_LOGIN_INFO loginInfo = new STU_LOGIN_INFO(); + loginInfo.strIP = ip; + loginInfo.nPort = port; + loginInfo.strUserName = s_mapFlagToClass.get(nFlag).getUserName(); + loginInfo.strPassword = s_mapFlagToClass.get(nFlag).getPassword(); + loginInfo.strDevSN = DataUtils.sdk_data_ptrToString(ptrParam, 0, paramLen, null); + + // 保存登陆信息,并在单开的线程中实现登陆 + s_mapFlagToClass.get(nFlag).m_listLoginInfos.addElement(loginInfo); + } + } + } + } + RegServerCallBack _cbRegServerCallBack = new RegServerCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + /* + * 登陆监听 + * 此处通过线程来实现登陆,是因为我们不建议用户在sdk接口的回调中,直接再去调用其他sdk的接口,而是通过另单开一个线程来接受数据,并执行登陆 + */ + public class LoginListenThread extends Thread + { + private device_auto_register m_runDevAutoReg; + + public LoginListenThread(device_auto_register runDevAutoReg) + { + m_runDevAutoReg = runDevAutoReg; + } + + @Override + public void run() + { + while(!m_runDevAutoReg.bExit) + { + if(m_runDevAutoReg.m_listLoginInfos.size() > 0) + { + STU_LOGIN_INFO loginInfo = m_runDevAutoReg.m_listLoginInfos.get(0); + + // 登陆 + m_runDevAutoReg.login(loginInfo.strIP, loginInfo.nPort, loginInfo.strDevSN); + + m_runDevAutoReg.m_listLoginInfos.removeElementAt(0); + } + } + } + + public void startLoginListenThread() + { + m_runDevAutoReg.bExit = false; + this.start(); + } + + public void stopLoginListenThread() + { + m_runDevAutoReg.bExit = true; + } + } + private LoginListenThread m_loginListenThread = null; + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 播放回调 + private class RealPlayDataCallBack implements NetDelegates.fRealPlayDataCallBack + { + @Override + public void invoke(NativeLong realHandle, int dataType, Pointer ptrBuffer, int bufferSize, NativeLong userdata) + { + if(0 != userdata.longValue()) + { + int nPort = (int) userdata.longValue(); + // 将码流数据传给play库来播放 + PlayLib.instance.PlayMS_InputData(nPort, ptrBuffer, bufferSize); + } + } + } + + RealPlayDataCallBack _realPlayDataCallBack = new RealPlayDataCallBack(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 解析事件信息 + private Object ParseEventInfoStructure(int eventType, Pointer ptrEventInfo) + { + if(null == ptrEventInfo) + { + System.out.printf("Parse event info [type:%d], null.\n", eventType); + return null; + } + + Object obj = null; + + ////////////////////////////////////////////////////////////////////// + if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_WHOLE) + { + NetStructs.STU_EVENT_FACE_SNAP_WHOLE stu = new NetStructs.STU_EVENT_FACE_SNAP_WHOLE(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_PART) + { + NetStructs.STU_EVENT_FACE_SNAP_PART stu = new NetStructs.STU_EVENT_FACE_SNAP_PART(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_WHOLE) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE stu = new NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_CUTOUT) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT stu = new NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + ////////////////////////////////////////////////////////////////////// + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS) + { + NetStructs.STU_EVENT_TRAFFIC_PASS stu = new NetStructs.STU_EVENT_TRAFFIC_PASS(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS_CUTOUT) + { + NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT stu = new NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT(); + DataUtils.sdk_data_ptrToStructure(ptrEventInfo, 0, stu); + + String strName = new String(stu.szEvent).trim(); + System.out.printf("Event info [type:%d, name:%s].\n", eventType, strName); + + obj = stu; + // ....................................... + } + else + { + System.out.printf("Event[type:%d], not supported.\n", eventType); + return null; + } + + return obj; + } + + // 保存事件数据到本地(事件数据即图片数据) + private boolean SaveBufferToLocal(int eventType, Object eventInfoObj, Pointer ptrBuffer, int bufferSize) + { + System.out.printf("Save buffer, Event:%d.\n", eventType); + + if(null == eventInfoObj || null == ptrBuffer || 0 >= bufferSize) + { + System.out.printf("Illegal params, Event:%d.\n", eventType); + return false; + } + + String filename = null; + + // 人脸检测背景图 + if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_WHOLE) + { + NetStructs.STU_EVENT_FACE_SNAP_WHOLE info = (NetStructs.STU_EVENT_FACE_SNAP_WHOLE)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸检测抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_SNAP_PART) + { + NetStructs.STU_EVENT_FACE_SNAP_PART info = (NetStructs.STU_EVENT_FACE_SNAP_PART)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸识别背景图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_WHOLE) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE info = (NetStructs.STU_EVENT_FACE_RECOGNIZE_WHOLE)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 人脸识别抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_FACE_RECOGNIZE_CUTOUT) + { + NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT info = (NetStructs.STU_EVENT_FACE_RECOGNIZE_CUTOUT)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + ////////////////////////////////////// + // 交通卡口背景图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS) + { + NetStructs.STU_EVENT_TRAFFIC_PASS info = (NetStructs.STU_EVENT_TRAFFIC_PASS)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + // 交通卡口抠图 + else if(eventType == NetEnums.EM_EVENT_SP_TYPE.EVENT_SP_TRAFFIC_PASS_CUTOUT) + { + NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT info = (NetStructs.STU_EVENT_TRAFFIC_PASS_CUTOUT)eventInfoObj; + + String strName = new String(info.szEvent).trim(); + filename = String.format("%s\\%s_%04d%02d%02d_%02d%02d%02d.jpg", this.m_strFilePath, strName, + info.stuTime.nYear, info.stuTime.nMonth, info.stuTime.nDay, + info.stuTime.nHour, info.stuTime.nMinute, info.stuTime.nSecond); + } + + if(null == filename || filename.isEmpty()) + { + System.out.printf("Get file name fail, Event:%d.\n", eventType); + return false; + } + + if(!DataUtils.sdk_data_fileWrite(ptrBuffer, 0, 0, bufferSize, filename)) + { + System.out.printf("Save file[%s] fail, Event:%d.\n", filename, eventType); + return false; + } + + refreshImage(filename); + + return true; + } + + // 智能分析数据回调,图片订阅事件上报时触发 + private class AnalyzeDataFunc implements NetDelegates.fAnalyzeDataCallBack + { + @Override + public void invoke(NativeLong analyzeHandle, int eventType, Pointer ptrEventInfo, Pointer ptrBuffer, + int bufferSize, NativeLong userdata, int sequence, Pointer ptrReserved) { + + System.out.printf("Handle:%d, Event:%d.\n", analyzeHandle.intValue(), eventType); + + // 解析事件信息 + Object eventInfoObj = ParseEventInfoStructure(eventType, ptrEventInfo); + + // 保存事件数据 + // 建议新建一个事件信息和图片数据(拷贝)处理队列,另起线程处理; + // 建议不要在回调函数中进行影响性能的操作,这里作为演示 + SaveBufferToLocal(eventType, eventInfoObj, ptrBuffer, bufferSize); + + /*......*/ + } + } + + private AnalyzeDataFunc _analyzeDataFunc = new AnalyzeDataFunc(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + private void initilizeRyNetLib() + { + s_mapFlagToClass.put(1, this); + + // 用户可以自定义 fDisConnectCB + NetLib.instance.Net_Init(_cbDisConnectCallBack, new NativeLong(1)); + + NetLib.instance.Net_SetLogOption(7); + + GlobalTool.createDirectory(this.m_strFilePath); + } + + private void destroyRyNetLib() + { + NetLib.instance.Net_Exit(); + } + + void refreshEnables() + { + boolean bStartServer = this.m_lRegServerHandle.longValue() != 0; + boolean bLogin = getCurDeviceLoginID().longValue() != 0; + boolean bPlay = this.m_lPlayHandle.longValue() != 0; + boolean bRealload = this.m_lRealloadHandle.longValue() != 0; + + this.m_btnStartServer.setEnabled(!bStartServer); + this.m_btnStopServer.setEnabled(bStartServer); + + this.m_btnStartPlay.setEnabled(bLogin && !bPlay); + this.m_btnStopPlay.setEnabled(bLogin && bPlay); + + this.m_chkRealLoad.setEnabled(bLogin); + this.m_chkRealLoad.setSelected(bRealload); + + this.m_chkIntelliDraw.setEnabled(bLogin && bPlay); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // 提示信息 + public void appendNotifyInfo(String info) + { + this.m_listInfoData.addElement(info); + this.m_listInfo.setListData(m_listInfoData); + this.m_listInfo.setSelectedIndex(m_listInfoData.size() - 1); + + Point p = new Point(); + p.setLocation(0, this.m_listInfo.getHeight()); + this.m_jspListInfo.getViewport().setViewPosition(p); + } + + public boolean login(String ip, int port, String strDevSN) + { + String strUserName; + strUserName = this.m_jtfDevUsername; // 默认admin + String strUserPassword; + strUserPassword = this.m_jtfDevPassword; // 默认admin123 + IntByReference nErr = new IntByReference(0); + + // 此接口专为 主动注册登陆 接口,与 Net_LoginDevice 有区别 + NativeLong lLoginID = NetLib.instance.Net_LoginDeviceSpec( + ip, + port, + strUserName, + strUserPassword, + EM_LOGIN_PROTOCAL_TYPE.EM_LOGIN_PROTOCAL_TYPE_REG_SERVER, + strDevSN, + null, + nErr); + + if(0 != lLoginID.longValue()) + { + this.m_listLoginIDs.addElement(lLoginID); + this.m_listDevicesData.addElement(String.format("%s_%d_%s", ip, port, strDevSN)); + this.m_listDevices.setListData(this.m_listDevicesData); + + System.out.println(String.format("登陆成功, 设备ip = %s, port = %d, SN = %s.", ip, port, strDevSN)); + refreshEnables(); + } + else + { + int nErrCode = NetLib.instance.Net_LastError(); + System.out.printf(String.format("登陆失败, ip = %s, port = %d, SN = %s, errorCode = %d.", ip, port, strDevSN, nErrCode)); + } + + return true; + } + + public void logoutAll() + { + for(int i=0; i + + + +