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
+
+
+
+