1
zhanghua
2024-09-26 c775c6953d9759e70f08acbfa8f6d7490aaae3d1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
package com.netsdk.demo.customize.surfaceEventDemo;
 
import com.netsdk.demo.customize.surfaceEventDemo.frame.SurfaceMainFrame;
import com.netsdk.demo.customize.surfaceEventDemo.module.AttachModule;
import com.netsdk.demo.customize.surfaceEventDemo.module.LogonModule;
import com.netsdk.demo.customize.surfaceEventDemo.module.RealPlayModule;
import com.netsdk.demo.customize.surfaceEventDemo.module.SdkUtilModule;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Native;
 
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
 
/**
 * @author 47040
 * @since Created in 2021/5/11 9:30
 */
public class SurfaceFrameDemo {
 
    private final SurfaceMainFrame frame;
 
    private final LogonModule logonModule = new LogonModule();
 
    private final RealPlayModule realPlayModule = new RealPlayModule();
 
    private final AttachModule attachModule = new AttachModule();
 
    public SurfaceFrameDemo() {
 
        // sdk 初始化
        SdkUtilModule.init();
 
        frame = new SurfaceMainFrame(m_strIp, m_nPort, m_strUser, m_strPassword);
        // 主界面退出 事件
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.out.println("Window Closing");
                realPlayModule.stopPlay(m_hPlayHandle);  // 停止播放
                logonModule.logout(m_hLoginHandle);      // 设备登出
                SdkUtilModule.cleanup();                 // 清理 SDK 资源
                frame.dispose();
                System.exit(0);
            }
        });
 
        /////////////// 登录相关 事件 ///////////////
        ///////////////////////////////////////////
 
        // 登入按钮 事件
        frame.getLoginPanel().getLoginBtn().addActionListener(e -> {
            m_strIp = frame.getLoginPanel().getIpAddress();
            m_nPort = frame.getLoginPanel().getPort();
            m_strUser = frame.getLoginPanel().getUsername();
            m_strPassword = frame.getLoginPanel().getPassword();
            // 登录
            m_hLoginHandle = logonModule.login(m_strIp, m_nPort, m_strUser, m_strPassword, m_stDeviceInfo);
            if (m_hLoginHandle.longValue() == 0) {
                JOptionPane.showMessageDialog(frame, "登录失败,错误码 :" + String.format("[%s]", ToolKits.getErrorCode()));
                return;
            }
 
            // 初始化订阅句柄Map
            attachHandelMap.clear();
            for (int i = 0; i < m_stDeviceInfo.byChanNum; i++) {
                attachHandelMap.put(i, new NetSDKLib.LLong(0));
            }
 
            frame.getLoginPanel().getLoginBtn().setEnabled(false); // 更新登录按钮状态
            frame.getLoginPanel().getLogoutBtn().setEnabled(true); // 更新登出按钮状态
            frame.getControlPanel().setEnabled(true);              // 启用播放控制组件
            frame.getControlPanel().resetChannelComboBox(m_stDeviceInfo.byChanNum); // 更新通道下拉框
        });
        // 登出按钮 事件
        frame.getLoginPanel().getLogoutBtn().addActionListener(e -> {
            realPlayModule.stopPlay(m_hPlayHandle);                 // 停止播放
            frame.getRealPlayPanel().getCanvasPanel().repaint();    // 刷新画布
            frame.getControlPanel().setEnabled(false);              // 禁用播放控制组件
            logonModule.logout(m_hLoginHandle);                     // 登出设备
            if (m_hLoginHandle.longValue() == 0) {          // 登出成功则更新 登录/登出 按钮状态
 
                // 清空订阅句柄Map
                attachHandelMap.clear();
 
                frame.getLoginPanel().getLoginBtn().setEnabled(true);
                frame.getLoginPanel().getLogoutBtn().setEnabled(false);
            }
        });
 
        /////////////// 播放控制 事件 ///////////////
        ///////////////////////////////////////////
        // 通道号切换 切换通道下拉框选项时触发
        frame.getControlPanel().getChannelComboBox().addActionListener(e -> {
            channel = ((JComboBox<?>) e.getSource()).getSelectedIndex();
            System.out.println("selected channel changed , now it is : " + channel);
        });
        // 开始播放 事件
        frame.getControlPanel().getPlayBtn().addActionListener(e -> {
            // 开始预览
            m_hPlayHandle = realPlayModule.realPlay(m_hLoginHandle, channel, playType,
                    Native.getComponentPointer(frame.getRealPlayPanel().getCanvasPanel()));
            if (m_hPlayHandle.longValue() == 0) {
                JOptionPane.showMessageDialog(frame, "播放失败,错误码 :" + String.format("[%s]", ToolKits.getErrorCode()));
            }
        });
        // 停止播放 事件
        frame.getControlPanel().getStopPlayBtn().addActionListener(e -> {
            realPlayModule.stopPlay(m_hPlayHandle);               // 停止播放
            frame.getRealPlayPanel().getCanvasPanel().repaint();  // 刷新画布
        });
 
        ////////////// 智能事件订阅 事件//////////////
        ////////////////////////////////////////////
        // 订阅
        frame.getControlPanel().getAttachBtn().addActionListener(e -> {
 
            for (int channel : attachHandelMap.keySet()) {
                NetSDKLib.LLong m_hAttachHandel = attachHandelMap.get(channel);
 
                attachModule.DetachEventRealLoadPic(m_hAttachHandel);
                // 需求要求直接订阅全通道
                m_hAttachHandel = attachModule.AttachEventRealLoadPic(m_hLoginHandle, channel, SurfaceAnalyzerDataCallBack.getInstance());
                if (m_hAttachHandel.longValue() == 0) {
                    for (int chl : attachHandelMap.keySet()) {
                        attachModule.DetachEventRealLoadPic(attachHandelMap.get(chl));
                    }
                    JOptionPane.showMessageDialog(frame, "订阅失败,错误码 :" + String.format("[%s]", ToolKits.getErrorCode()));
                    return;
                }
                attachHandelMap.put(channel, m_hAttachHandel);
            }
 
            frame.getControlPanel().getAttachBtn().setEnabled(false);
            frame.getControlPanel().getDetachBtn().setEnabled(true);
 
            taskIsOpen = true;
            new Thread(this::eventListTask).start();
            new Thread(this::eventInfoListTask).start();
            new Thread(this::eventInfoGroupTask).start();
 
            JOptionPane.showMessageDialog(frame, "全通道订阅成功");
        });
        // 退订
        frame.getControlPanel().getDetachBtn().addActionListener(e -> {
 
            for (int channel : attachHandelMap.keySet()) {
                attachModule.DetachEventRealLoadPic(attachHandelMap.get(channel));
            }
            frame.getControlPanel().getAttachBtn().setEnabled(true);
            frame.getControlPanel().getDetachBtn().setEnabled(false);
 
            int count = 100;  // 等待队列数据清空,但最多等待10s
            while (count > 0) {
                try {
                    if (eventList.size() == 0 && eventInfoList.size() == 0 && eventGroupList.size() == 0)
                        break;
                    count--;
                    Thread.sleep(100);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
            }
            taskIsOpen = false;
        });
        // 清空
        frame.getControlPanel().getClearBtn().addActionListener(e -> {
            frame.getGroupListPanel().clearTableContent();
            frame.getEventPicPanel().clearPic();
            frame.getEventGroupPanel().clearAll();
            EventResource.clearAll();
        });
    }
 
    // 设备信息
    private final NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
 
    // 登录句柄
    private static NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0);
 
    // 播放句柄
    private static NetSDKLib.LLong m_hPlayHandle = new NetSDKLib.LLong(0);
 
    // 订阅句柄组 key-通道 value-句柄
    private static final Map<Integer, NetSDKLib.LLong> attachHandelMap = new ConcurrentHashMap<>();
 
    // 预览通道号
    int channel = 0;
 
    // 预览类型
    int playType = NetSDKLib.NET_RealPlayType.NET_RType_Realplay;   // 实时预览模式
 
    // 来自回调函数的推送事件队列
    private final LinkedBlockingQueue<SurfaceEventInfo> eventList = EventResource.getSurfaceEventQueue();
 
    // 用于表格展示的队列
    private final LinkedBlockingQueue<List<SurfaceEventInfo>> eventInfoList = EventResource.getSurfaceEventListQueue();
 
    // 用于事件组展示的队列
    private final LinkedBlockingQueue<List<SurfaceEventInfo>> eventGroupList = EventResource.getSurfaceEventGroupQueue();
 
    // 判断Task是否执行的开关
    private Boolean taskIsOpen = false;
 
    // 获取数据并传递到各个队列中
    public void eventListTask() {
        // 为了控制获取事件的顺序,这里我起了个死循环强制线性处理
        // 这么做只是为了Demo设计简便,异步顺序控制有很多更好的方法
        while (taskIsOpen) {
            try {
                // 稍微延迟一下,避免循环的太快
                Thread.sleep(10);
                // 阻塞获取
                SurfaceEventInfo surfaceEventInfo = eventList.poll(50, TimeUnit.MILLISECONDS);
                if (surfaceEventInfo == null) continue;
 
                // 放入表格展示的队列
                EventResource.AddEventListEle(surfaceEventInfo);
                // 放入缓存并检查 事件组
                EventResource.AddCacheAndCheckGroupEvents(surfaceEventInfo);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    // 表格和事件图片展示任务
    private void eventInfoListTask() {
        while (taskIsOpen) {
            try {
                // 稍微延迟一下,避免循环的太快
                Thread.sleep(10);
                // 阻塞获取
                List<SurfaceEventInfo> eventInfos = eventInfoList.poll(50, TimeUnit.MILLISECONDS);
                if (eventInfos == null) continue;
 
                String[][] data = new String[eventInfos.size()][5];
                for (int i = 0; i < eventInfos.size(); i++) {
                    data[i][0] = String.valueOf(eventInfos.get(i).getEventID());
                    data[i][1] = String.valueOf(eventInfos.get(i).getChannel());
                    data[i][2] = eventInfos.get(i).getEventName();
                    data[i][3] = eventInfos.get(i).getUTC();
                    data[i][4] = eventInfos.get(i).getBriefInfo();
                }
                // 更新表格
                frame.getGroupListPanel().updateTableContent(data);
                // 更新图片 来源是最上面的(最新)的事件
                SurfaceEventInfo eventInfo = eventInfos.get(0);
                if (eventInfo.getImagesData() != null) {
                    frame.getEventPicPanel().showPicOnCanvas(eventInfo.getImagesData());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    // 事件组内容展示任务
    private void eventInfoGroupTask() {
        while (taskIsOpen) {
            try {
                // 稍微延迟一下,避免循环的太快
                Thread.sleep(10);
                // 阻塞获取
                List<SurfaceEventInfo> groupList = eventGroupList.poll(50, TimeUnit.MILLISECONDS);
                if (groupList == null) continue;
 
                // 先清空
                frame.getEventGroupPanel().clearAll();
                for (int i = 0; i < groupList.size(); i++) {
                    SurfaceEventInfo eventInfo = groupList.get(i);
                    String detailInfo = eventInfo.getDetailInfo();
                    frame.getEventGroupPanel().getGroupPanels().get(i).setDetail(detailInfo);
                    if (eventInfo.getImagesData() != null)
                        frame.getEventGroupPanel().getGroupPanels().get(i).showPicOnCanvas(eventInfo.getImagesData());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
 
    ////////////////// 登陆参数 //////////////////
    /////////////////////////////////////////////
    private String m_strIp = "10.18.128.96";
    private Integer m_nPort = 37777;
    private String m_strUser = "admin";
    private String m_strPassword = "admin654321";
 
    public static void main(String[] args) {
        SwingUtilities.invokeLater(SurfaceFrameDemo::new);
    }
}