package com.netsdk.demo.customize;
|
|
import java.awt.Container;
|
import java.awt.Dimension;
|
import java.awt.Toolkit;
|
|
import javax.swing.JWindow;
|
|
import com.netsdk.demo.util.CaseMenu;
|
import com.netsdk.lib.NetSDKLib;
|
import com.netsdk.lib.ToolKits;
|
import com.netsdk.lib.NetSDKLib.*;
|
import com.sun.jna.Native;
|
import com.sun.jna.NativeLong;
|
import com.sun.jna.Pointer;
|
import com.sun.jna.ptr.IntByReference;
|
|
public class VTOTalk {
|
static NetSDKLib netsdkApi = NetSDKLib.NETSDK_INSTANCE;
|
static NetSDKLib configApi = NetSDKLib.CONFIG_INSTANCE;
|
|
private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
|
|
// 登录句柄
|
private static LLong loginHandle = new LLong(0);
|
|
// 语音对讲句柄
|
public static LLong m_hTalkHandle = new LLong(0);
|
|
private static boolean m_bRecordStatus = false;
|
|
private static LLong m_hRealPlayHandle = new LLong(0);
|
|
private static JWindow wnd = new JWindow();
|
|
String address = "172.23.30.60"; // 172.26.6.104
|
int port = 37777;
|
String username = "admin";
|
String password = "admin123";
|
|
private static class DisconnectCallback implements NetSDKLib.fDisConnect {
|
private static DisconnectCallback instance = new DisconnectCallback();
|
private DisconnectCallback() {}
|
public static DisconnectCallback getInstance() {
|
return instance;
|
}
|
|
public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){
|
System.out.printf("Device[%s:%d] Disconnect!\n" , pchDVRIP , nDVRPort);
|
}
|
}
|
|
private static class HaveReconnectCallback implements NetSDKLib.fHaveReConnect {
|
private static HaveReconnectCallback instance = new HaveReconnectCallback();
|
private HaveReconnectCallback() {}
|
public static HaveReconnectCallback getInstance() {
|
return instance;
|
}
|
|
public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){
|
System.out.printf("Device[%s:%d] HaveReconnected!\n" , pchDVRIP , nDVRPort);
|
}
|
}
|
|
public void EndTest() {
|
System.out.println("End Test");
|
if( loginHandle.longValue() != 0)
|
{
|
netsdkApi.CLIENT_Logout(loginHandle);
|
}
|
System.out.println("See You...");
|
|
netsdkApi.CLIENT_Cleanup();
|
System.exit(0);
|
}
|
|
public void InitTest() {
|
//初始化SDK库
|
netsdkApi.CLIENT_Init(DisconnectCallback.getInstance(), null);
|
|
//设置断线自动重练功能
|
netsdkApi.CLIENT_SetAutoReconnect(HaveReconnectCallback.getInstance(), null);
|
|
// 向设备登入
|
int nSpecCap = 0;
|
IntByReference nError = new IntByReference(0);
|
loginHandle = netsdkApi.CLIENT_LoginEx2(address, port, username,
|
password, nSpecCap, null, deviceInfo, nError);
|
|
if(loginHandle.longValue() == 0) {
|
System.err.printf("Login Device [%s:%d] Failed ! Last Error[%x]\n", address, port, netsdkApi.CLIENT_GetLastError());
|
// 释放SDK资源,在关闭工程时调用
|
EndTest();
|
return;
|
}
|
|
System.out.printf("Login Device [%s:%d] Success. \n", address, port);
|
}
|
|
/**
|
* 获取接口错误码
|
* @return
|
*/
|
public static String getErrorCode() {
|
return " { error code: ( 0x80000000|" + (netsdkApi.CLIENT_GetLastError() & 0x7fffffff) +" ). 参考 NetSDKLib.java }";
|
}
|
|
|
/**
|
* \if ENGLISH_LANG
|
* Start Talk
|
* \else
|
* 开始通话
|
* \endif
|
*/
|
public static boolean startTalk() {
|
|
// 设置语音对讲编码格式
|
NetSDKLib.NETDEV_TALKDECODE_INFO talkEncode = new NetSDKLib.NETDEV_TALKDECODE_INFO();
|
talkEncode.encodeType = NetSDKLib.NET_TALK_CODING_TYPE.NET_TALK_PCM;
|
talkEncode.dwSampleRate = 8000;
|
talkEncode.nAudioBit = 16;
|
talkEncode.nPacketPeriod = 25;
|
talkEncode.write();
|
if(netsdkApi.CLIENT_SetDeviceMode(loginHandle, NetSDKLib.EM_USEDEV_MODE.NET_TALK_ENCODE_TYPE, talkEncode.getPointer())) {
|
System.out.println("Set Talk Encode Type Succeed!");
|
} else {
|
System.err.println("Set Talk Encode Type Failed!" + getErrorCode());
|
return false;
|
}
|
|
// 设置客户端对讲方式
|
if (netsdkApi.CLIENT_SetDeviceMode(loginHandle, NetSDKLib.EM_USEDEV_MODE.NET_TALK_CLIENT_MODE, null)) {
|
System.out.println("Set Talk Client Mode Succeed!");
|
} else {
|
System.err.println("Set Talk Client Mode Failed!" + getErrorCode());
|
return false;
|
}
|
|
// 设置对讲模式
|
NetSDKLib.NET_SPEAK_PARAM speak = new NetSDKLib.NET_SPEAK_PARAM();
|
speak.nMode = 0;
|
speak.bEnableWait = false;
|
speak.write();
|
|
if (netsdkApi.CLIENT_SetDeviceMode(loginHandle, NetSDKLib.EM_USEDEV_MODE.NET_TALK_SPEAK_PARAM, speak.getPointer())) {
|
System.out.println("Set Talk Speak Mode Succeed!");
|
} else {
|
System.err.println("Set Talk Speak Mode Failed!" + getErrorCode());
|
return false;
|
}
|
|
m_hTalkHandle = netsdkApi.CLIENT_StartTalkEx(loginHandle, AudioDataCB.getInstance(), null);
|
|
if(m_hTalkHandle.longValue() == 0) {
|
System.err.println("Start Talk Failed!" + getErrorCode());
|
return false;
|
} else {
|
System.out.println("Start Talk Success");
|
if(netsdkApi.CLIENT_RecordStart()){
|
System.out.println("Start Record Success");
|
m_bRecordStatus = true;
|
} else {
|
System.err.println("Start Local Record Failed!" + getErrorCode());
|
stopTalk();
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
/**
|
* \if ENGLISH_LANG
|
* Stop Talk
|
* \else
|
* 结束通话
|
* \endif
|
*/
|
public static void stopTalk() {
|
if(m_hTalkHandle.longValue() == 0) {
|
return;
|
}
|
|
if (m_bRecordStatus){
|
netsdkApi.CLIENT_RecordStop();
|
m_bRecordStatus = false;
|
}
|
|
if(netsdkApi.CLIENT_StopTalkEx(m_hTalkHandle)) {
|
m_hTalkHandle.setValue(0);
|
}else {
|
System.err.println("Stop Talk Failed!" + getErrorCode());
|
}
|
}
|
|
/**
|
* \if ENGLISH_LANG
|
* Audio Data Callback
|
* \else
|
* 语音对讲的数据回调
|
* \endif
|
*/
|
private static class AudioDataCB implements NetSDKLib.pfAudioDataCallBack {
|
|
private AudioDataCB() {}
|
private static AudioDataCB audioCallBack = new AudioDataCB();
|
|
public static AudioDataCB getInstance() {
|
return audioCallBack;
|
}
|
|
public void invoke(LLong lTalkHandle, Pointer pDataBuf, int dwBufSize, byte byAudioFlag, Pointer dwUser){
|
|
if(lTalkHandle.longValue() != m_hTalkHandle.longValue()) {
|
return;
|
}
|
|
/**
|
* 0:本地录音库采集的音频数据
|
* 1:收到的设备发过来的音频数据
|
* 2:对讲呼叫响应数据
|
* 3:收到的设备发过来的视频数据
|
*/
|
if (byAudioFlag == 0) { // 将收到的本地PC端检测到的声卡数据发送给设备端
|
|
LLong lSendSize = netsdkApi.CLIENT_TalkSendData(m_hTalkHandle, pDataBuf, dwBufSize);
|
if(lSendSize.longValue() != (long)dwBufSize) {
|
System.err.println("send incomplete" + lSendSize.longValue() + ":" + dwBufSize);
|
} else {
|
System.out.println("本地音频发送给设备");
|
}
|
} else if (byAudioFlag == 1 || byAudioFlag == 3) { // 将收到的设备端发送过来的语音数据传给SDK解码播放
|
netsdkApi.CLIENT_AudioDecEx(m_hTalkHandle, pDataBuf, dwBufSize);
|
System.out.println("设备发送过来数据解码播放");
|
} else if(byAudioFlag == 2) {
|
System.out.println("device responded...");
|
}
|
}
|
}
|
|
/**
|
* 实时预览
|
*/
|
public void RealPlay() {
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
screenSize.height /= 2;
|
screenSize.width /= 2;
|
wnd.setSize(screenSize);
|
centerWindow(wnd);
|
wnd.setVisible(true);
|
|
m_hRealPlayHandle = netsdkApi.CLIENT_RealPlayEx(loginHandle, 0, Native.getComponentPointer(wnd), 0);
|
if (m_hRealPlayHandle.longValue() == 0) {
|
System.err.println("实时预览失败, " + getErrorCode());
|
return;
|
} else {
|
System.out.println("实时预览成功!");
|
}
|
|
// dwFlag 数据类型
|
// 1 原始数据标志
|
// 2 带有帧信息的数据标志
|
// 4 YUV 数据标志
|
// 8 PCM 音频数据标志
|
int dwFlag = 1;
|
if(netsdkApi.CLIENT_SetRealDataCallBackEx(m_hRealPlayHandle, RealDataCallBack.getInstance(), null, dwFlag)) {
|
System.out.println("设置预览回调成功!");
|
} else {
|
System.err.println("设置预览回调失败!" + netsdkApi.CLIENT_GetLastError());
|
}
|
}
|
|
// 实时预览数据回调函数
|
private static class RealDataCallBack implements NetSDKLib.fRealDataCallBackEx {
|
private RealDataCallBack() {}
|
|
private static class RealDataCallBackHolder {
|
private static RealDataCallBack instance = new RealDataCallBack();
|
}
|
|
public static RealDataCallBack getInstance() {
|
return RealDataCallBackHolder.instance;
|
}
|
|
@Override
|
public void invoke(LLong lRealHandle, int dwDataType,
|
Pointer pBuffer, int dwBufSize, int param, Pointer dwUser) {
|
// dwDataType 数据类型
|
// 0 原始数据
|
// 1 带有帧信息的数据
|
// 2 yuv数据
|
// 3 pcm音频数据
|
System.out.println("dwDataType:" + dwDataType);
|
|
// 视频数据, 可以根据需要的 dwDataType 过滤, 具体需要哪种数据, 在 CLIENT_SetRealDataCallBackEx 里设置
|
byte[] data = pBuffer.getByteArray(0, dwBufSize);
|
System.out.println(new String(data).trim());
|
}
|
}
|
|
public static void centerWindow(Container window) {
|
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
|
int w = window.getSize().width;
|
int h = window.getSize().height;
|
int x = (dim.width - w) / 2;
|
int y = (dim.height - h) / 2;
|
window.setLocation(x, y);
|
}
|
|
public void stopRealPlay() {
|
if(m_hRealPlayHandle.longValue() != 0) {
|
netsdkApi.CLIENT_StopRealPlayEx(m_hRealPlayHandle);
|
m_hRealPlayHandle.setValue(0);
|
|
wnd.setVisible(false);
|
}
|
}
|
|
|
/**
|
* 设置二维码的解码信息
|
*/
|
public void SetQrcode() {
|
int emtype = NET_EM_ACCESS_CTL_MANAGER.NET_EM_ACCESS_CTL_SET_QRCODEDECODE_INFO;
|
/*
|
* 入参
|
*/
|
NET_IN_SET_QRCODE_DECODE_INFO stIn = new NET_IN_SET_QRCODE_DECODE_INFO();
|
|
// 加密方式
|
stIn.emCipher = NET_ENUM_QRCODE_CIPHER.NET_ENUM_QRCODE_CIPHER_AES256;
|
|
// 秘钥, 必须32位,用户自己定义,用于二维码加密
|
// 但是加密密钥变化的周期不能小于1天;因为访客拿到二维码的时候,最长可能会使用二维码一天的,所以如果变化,最少一天以上再变
|
String key = "0123456789ABCDEF0123456789ABCDEF";
|
System.arraycopy(key.getBytes(), 0, stIn.szKey, 0, key.getBytes().length);
|
|
/*
|
* 出参
|
*/
|
NET_OUT_SET_QRCODE_DECODE_INFO stOut = new NET_OUT_SET_QRCODE_DECODE_INFO();
|
|
stIn.write();
|
stOut.write();
|
boolean bRet = netsdkApi.CLIENT_OperateAccessControlManager(loginHandle, emtype, stIn.getPointer(), stOut.getPointer(), 5000);
|
stIn.read();
|
stOut.read();
|
|
if(bRet) {
|
System.out.println("设置二维码的解码信息成功.");
|
} else {
|
System.err.println("设置二维码的解码信息失败, " + getErrorCode());
|
}
|
}
|
|
/**
|
* 二维码加密
|
*/
|
public void EncryptString() {
|
/*
|
* 入参
|
*/
|
NET_IN_ENCRYPT_STRING stIn = new NET_IN_ENCRYPT_STRING();
|
// 卡号
|
String card = "B56E78BD";
|
System.arraycopy(card.getBytes(), 0, stIn.szCard, 0, card.getBytes().length);
|
|
// 秘钥, 必须32位,要跟SetQrcode()里的密钥一样
|
String key = "0123456789ABCDEF0123456789ABCDEF";
|
System.arraycopy(key.getBytes(), 0, stIn.szKey, 0, key.getBytes().length);
|
|
/*
|
* 出参
|
*/
|
NET_OUT_ENCRYPT_STRING stOut = new NET_OUT_ENCRYPT_STRING();
|
|
if(netsdkApi.CLIENT_EncryptString(stIn, stOut, 4000)) {
|
System.out.println("加密后的字符串:" + new String(stOut.szEncryptString).trim());
|
}
|
}
|
|
/**
|
* 订阅报警信息
|
* @return
|
*/
|
public void startListen() {
|
// 设置报警回调函数
|
netsdkApi.CLIENT_SetDVRMessCallBack(fAlarmDataCB.getCallBack(), null);
|
|
// 订阅报警
|
boolean bRet = netsdkApi.CLIENT_StartListenEx(loginHandle);
|
if (!bRet) {
|
System.err.println("订阅报警失败! LastError = 0x%x\n" + netsdkApi.CLIENT_GetLastError());
|
}
|
else {
|
System.out.println("订阅报警成功.");
|
}
|
}
|
|
/**
|
* 取消订阅报警信息
|
* @return
|
*/
|
public void stopListen() {
|
// 停止订阅报警
|
boolean bRet = netsdkApi.CLIENT_StopListen(loginHandle);
|
if (bRet) {
|
System.out.println("取消订阅报警信息.");
|
}
|
}
|
|
/**
|
* 报警信息回调函数原形,建议写成单例模式
|
*/
|
private static class fAlarmDataCB implements NetSDKLib.fMessCallBack{
|
private fAlarmDataCB(){}
|
|
private static class fAlarmDataCBHolder {
|
private static fAlarmDataCB callback = new fAlarmDataCB();
|
}
|
|
public static fAlarmDataCB getCallBack() {
|
return fAlarmDataCBHolder.callback;
|
}
|
|
public boolean invoke(int lCommand, LLong lLoginID, Pointer pStuEvent, int dwBufLen, String strDeviceIP, NativeLong nDevicePort, Pointer dwUser){
|
System.out.printf("command = %x\n", lCommand);
|
switch (lCommand)
|
{
|
case NetSDKLib.NET_ALARM_TALKING_INVITE : // 设备请求对方发起对讲事件
|
{
|
NetSDKLib.ALARM_TALKING_INVITE_INFO msg = new NetSDKLib.ALARM_TALKING_INVITE_INFO();
|
ToolKits.GetPointerData(pStuEvent, msg);
|
|
System.out.println("呼叫的房间号 :" + new String(msg.szCallID).trim());
|
|
break;
|
}
|
}
|
|
return true;
|
}
|
}
|
|
public void RunTest() {
|
CaseMenu menu = new CaseMenu();
|
|
menu.addItem(new CaseMenu.Item(this , "设置二维码的解码信息", "SetQrcode"));
|
menu.addItem(new CaseMenu.Item(this , "二维码加密", "EncryptString"));
|
|
menu.addItem(new CaseMenu.Item(this , "对讲", "startTalk"));
|
menu.addItem(new CaseMenu.Item(this , "停止对讲", "stopTalk"));
|
|
menu.addItem(new CaseMenu.Item(this , "预览", "RealPlay"));
|
menu.addItem(new CaseMenu.Item(this , "停止预览", "stopRealPlay"));
|
|
menu.addItem(new CaseMenu.Item(this , "报警订阅", "startListen"));
|
menu.addItem(new CaseMenu.Item(this , "取消报警订阅", "stopListen"));
|
|
menu.run();
|
}
|
|
|
public static void main(String[]args) {
|
VTOTalk demo = new VTOTalk();
|
demo.InitTest();
|
demo.RunTest();
|
demo.EndTest();
|
}
|
}
|