# JNA
# 添加依赖
对于maven工程直接在pom.xml中添加如下代码:
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna
可以不用,只需要第二个依赖就好
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</dependency>
https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
</dependency>
2
3
4
5
6
7
8
9
10
11
非maven管理的项目手工添加jar包:
jna-4.5.2.jar、jna-platform-4.5.2.jar(我这是截至2018-09-05时最新版本)
# 根据dll中接口函数开发相应代码
public interface IDeviceServiceDll extends Library {
//IDeviceServiceDll deviceService = (IDeviceServiceDll)Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), IDeviceServiceDll.class);
IDeviceServiceDll deviceService = (IDeviceServiceDll)Native.loadLibrary("XNetSDK", IDeviceServiceDll.class);
//IDeviceServiceDll deviceService = (IDeviceServiceDll)Native.loadLibrary("XNetSDK3", IDeviceServiceDll.class);
2
3
4
5
初始化接口库,dll文件要放在java.library.path中的路径下,如jdk安装目录的bin下,或者当前项目的根目录下,引用时直接写dll文件的名字(不带后缀)。
# 开发接口
- 如以下接口1
返回值为int,入参是一个结构体指针,且该结构体中存在一个回调函数; 该回调函数C++中如下:
typedef int (CALLBACK *PXSDK_MessageCallBack) (XSDK_HANDLE hDevice, int nMsgId, int nParam1, int nParam2, int nParam3, const char *szString, void *pObject, int nSeq, void *pUserData);
JAVA中定义回调函数:
先定义回调函数对应的接口
public interface PXSDK_MessageCallBack extends Callback{
public void MessageHandle(int hDevice,int nMsgId,int nParam1,int nParam2,int nParam3,String szString,String pObject,int nSeq,String pUserData);
}
2
3
再定义其实现类:
public interface PXSDK_MessageCallBack extends Callback{
public void MessageHandle(int hDevice,int nMsgId,int nParam1,int nParam2,int nParam3,String szString,String pObject,int nSeq,String pUserData);
}
public class PXSDK_MessageCallBackImpl implements PXSDK_MessageCallBack{
@Override
public void MessageHandle(int hDevice, int nMsgId, int nParam1, int nParam2, int nParam3, String szString,
String pObject, int nSeq, String pUserData) {
// TODO 自动生成的方法存根
System.out.println("\n回调:"+hDevice+"\n"+pUserData+"\n"+nMsgId);
}
}
2
3
4
5
6
7
8
9
10
11
PS:接口继承的
Callback,也可以是StdCallCallback
# 定义该接口入参的结构体
public static class SXSDKInitParam extends Structure {
public int nLogLevel;
public PXSDK_MessageCallBack pMsgCallBack;
public String pUserData;
public static class ByReference extends SXSDKInitParam implements Structure.ByReference {}
public static class ByValue extends SXSDKInitParam implements Structure.ByValue {}
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("nLogLevel");
a.add("pMsgCallBack");
a.add("pUserData");
return a;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义该接口
public int XSDK_Init(SXSDKInitParam.ByReference pParam);
ByReference和ByValue,貌似目前没看出区别来,网传一个是针对指针,一个是针对结构体本身。
至此基本定义就结束,现在来测试。
# 调用测试
public static void main(String[] args) {
IDeviceServiceDll.SXSDKInitParam.ByReference initData = new IDeviceServiceDll.SXSDKInitParam.ByReference();
IDeviceServiceDll.PXSDK_MessageCallBack messageCallBack = new IDeviceServiceDll.PXSDK_MessageCallBackImpl();
initData.nLogLevel=3;
initData.pMsgCallBack = messageCallBack;
initData.pUserData = "什么鬼";
result = IDeviceServiceDll.deviceService.XSDK_Init(initData);
System.out.println("初始化函数返回值:"+result);
}
2
3
4
5
6
7
8
9
至此调用成功,返回正常调用结果值。
- 再如以下接口2
typedef struct SXSDKLoginParam
{
char sDevId[128]; // ip/dns/sn
int nDevPort;
char sUserName[64];
char sPassword[64];
EDEV_NET_TYPE nCnnType;//枚举类型,两个枚举量
}SXSDKLoginParam;
2
3
4
5
6
7
8
实现如下:
public static class SXSDKLoginParam extends Structure {
public byte[] sDevId = new byte[128];
public int nDevPort;
public byte[] sUserName = new byte[64];
public byte[] sPassword = new byte[64];
public int nCnnType;
public static class ByReference extends SXSDKLoginParam implements Structure.ByReference {}
public static class ByValue extends SXSDKLoginParam implements Structure.ByValue {}
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("sDevId");
a.add("nDevPort");
a.add("sUserName");
a.add("sPassword");
a.add("nCnnType");
return a;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
结构体中存在byte时,传值时需注意
IDeviceServiceDll.SXSDKLoginParam.ByReference loginData = new IDeviceServiceDll.SXSDKLoginParam.ByReference();
int hDevice = 0;
loginData.sDevId = Arrays.copyOf(device.getDeviceIp().getBytes(), 128);
loginData.nDevPort = Integer.valueOf(device.getDevicePort());
loginData.sUserName = Arrays.copyOf(device.getDeviceUserName().getBytes(), 64);
loginData.sPassword = Arrays.copyOf(device.getDevicePassword().getBytes(), 64);
loginData.nCnnType = EDEV_NET_TYPE.EDEV_CNN_TYPE_IP_DNS.getType();
hDevice = IDeviceServiceDll.deviceService.XSDK_DevLogin(loginData, loginTimeout, 0);
2
3
4
5
6
7
8
否则的话,传值会错乱,java传结构体给c,是把申请的连续内存整个传过去,c就依次找,
第一个值,c会在第一块128个字节的内存里找,到了第二个参数,内存位置就不对了,后面的参数值就会错的更离谱,但是基本上每次的值都一样,无论你传的是什么值。
# 类型对照表
| Native Type | Java Type | Native Representation |
|---|---|---|
| char | byte | 8-bit integer |
| wchar_t | char | 16/32-bit character |
| short | short | 16-bit integer |
| int | int | 32-bit integer |
| int | boolean | 32-bit integer (customizable) |
| long, __int64 | long | 64-bit integer |
| long long | long | 64-bit integer |
| float | float | 32-bit FP |
| double | double | 64-bit FP |
| pointer | Buffer/Pointer | |
| pointer | array[](array of primitive type) | |
| char* | String | |
| wchar_t* | WString | |
| char** | String[] | |
| wchar_t** | WString[] | |
| void* | Pointer | |
| void ** | PointerByReference | |
| int& | IntByReference | |
| int* | IntByReference | |
| struct | Structure | |
| (*fp)() | Callback | |
| varies | NativeMapped | |
| long | NativeLong | |
| pointer | PointerType |
# 支持常见的数据类型的映射
| Java类型 | C 类型 | 原生表现 |
|---|---|---|
| String | char* | /0结束的数组 (native encoding or jna.encoding) |
| WString | wchar_t* | /0结束的数组(unicode) |
| String[] | char** | /0结束的数组的数组 |
| WString[] | wchar_t** | /0结束的宽字符数组的数组 |
| Structure | struct*、struct | 指向结构体的指针 (参数或返回值) (或者明确指定是结构体指针)结构体(结构体的成员) (或者明确指定是结构体) |
| Union | union | 等同于结构体 |
| Structure[] | struct[] | 结构体的数组,邻接内存 |
| Callback | <T>(*fp)() | Java函数指针或原生函数指针 |
| NativeMapped | varies | 依赖于定义 |
| NativeLong | long | 平台依赖(32或64位整数) |
| PointerType | pointer | 和 Pointer相同 |
# 和操作系统数据类型的对应表
| Java 类型 | C 类型 | 原生表现 |
|---|---|---|
| boolean | int | 32位整数 (可定制) |
| byte | char | 8位整数 |
| char | wchar_t | 平台依赖 |
| short | short | 16位整数 |
| int | int | 32位整数 |
| long | long long, __int64 | 64位整数 |
| float | float | 32位浮点数 |
| double | double | 64位浮点数 |
| Buffer | Pointer | pointer平台依赖(32或 64位指针) |
<T>[](基本类型的数组) | pointer、array | 32或 64位指针(参数/返回值)邻接内存(结构体成员) |
BYTE,byte就是int值就可,例如:(byte)1;
# 出现结构体字段不匹配
看是否拼写不一致、再看java中结构体类中的变量是不是public。
public static class SXMediaRealPlayReq extends Structure{
public int nChannel;
public int nStreamType;
public int nRequestType;
public PXSDK_MediaCallBack pMediaCallback;
public Pointer pUserData;
public static class ByReference extends SXMediaRealPlayReq implements Structure.ByReference {}
public static class ByValue extends SXMediaRealPlayReq implements Structure.ByValue {}
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("nChannel");
a.add("nStreamType");
a.add("nRequestType");
a.add("pMediaCallback");
a.add("pUserData");
return a;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# c语言返回的结构体指针如何转换
以下是通用方法
public static <T extends Structure> T p2Structure(Pointer pParam, Class<T> clazz) throws InstantiationException, IllegalAccessException {
T result = clazz.newInstance();
result.write();//先写入内存
Pointer p = result.getPointer();//获取java结构体指针
p.write(0, pParam.getByteArray(0, result.size()), 0, result.size());//写入获取到的数据
result.read();
return result;
}
2
3
4
5
6
7
8
其中:pParam为c语言返回的结构体指针,T为java的结构体。
# 指针
原生代码中的指针,可以使用Pointer类型,或者PointerType类型及它们的子类型来模拟。
Pointer代表原生代码中的指针。其属性peer就是原生代码中指针的地址。
我们不可以直接创建Pointer对象,但可以用它表示原生函数中的任何指针。
Pointer类有2个子类:Function,Memory。
Function类代表原生函数的指针,可以通过invoke(Class,Object[],Map)这一系列的方法调用原生函数。
Memory类代表的是堆中的一段内存,它也是我们可以创建的Pointer子类。
创建一个Memory类的实例,就是在原生代码的内存区中分配一块指定大小的内存。这块内存会在GC释放这个Java对象时被释放。
Memory类在指针模拟中会被经常用到。
PointerType类代表的是一个类型安全的指针。
ByReference类是PointerType类的子类。
ByReference类代表指向堆内存的指针。
ByReference类非常简单。
ByteByReference, DoubleByReference,FloatByReference, IntByReference, LongByReference, NativeLongByReference,PointerByReference, ShortByReference, W32API.HANDLEByReference,X11.AtomByReference, X11.WindowByReference
ByteByReference等类故名思议,就是指向原生代码中的字节数据的指针。
PointerByReference类表示指向指针的指针。
在JNA中模拟指针,最常用到的就是Pointer类和PointerByReference类。Pointer类代表指向任何东西的指针,PointerByReference类表示指向指针的指针。Pointer类更加通用,事实上PointerByReference类内部也持有Pointer类的实例。
PointerByReference类可以嵌套使用,它所指向的指针,本身可能也是指向指针的指针。
# 结构体内部可以包含结构体对象的指针的数组
struct CompanyStruct{
long id;
wchar_t* name;
UserStruct* users[100];
int count;
};
2
3
4
5
6
模拟如下:
public static class CompanyStruct{
public NativeLong id;
public WString name;
public UserStruct.ByReference[] users=newUserStruct.ByReference[100];
public int count;
}
2
3
4
5
6
7
8
9
# 总结
JNA打破了Java和原生代码原本泾渭分明的界限,实现了Java和原生代码的强强联合,在各自擅长的领域分工合作,快速解决问题。
Java可以方便地利用原生代码的优势:执行速度快,可以直接操作硬件,机器码不容易被破解等。
原生代码可以通过回调Java函数,利用Java的优势:开发效率高,自动内存管理,跨平台,类库丰富,网络功能强大,支持多种脚本语言等。
JNA为Java开发者打开了一扇通向广袤的原生代码世界的大门。
# 实例
# 热成像示例
/**
* 设备网络地址信息
*/
public static class NET_INET_ADDR extends Structure {
public byte[] szHostIP = new byte[CONST_MAXLENGTH_IP];//IP地址(点分符形式)
public int nPORT;//端口号
public int nIPProtoVer;//IP协议版本(1:IPv4协议,2:IPv6协议)
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("szHostIP");
a.add("nPORT");
a.add("nIPProtoVer");
return a;
}
}
/**
* 设备信息
*/
public static class NET_DEVICE_INFO extends Structure {
public NET_INET_ADDR struInetAddr = new NET_INET_ADDR();
public byte[] szUserID = new byte[CONST_MAXLENGTH_USERID];//登陆设备的用户ID
public byte[] szPassword = new byte[CONST_MAXLENGTH_PASSWORD];//登陆设备的密码
public byte[] szDeviceID = new byte[CONST_MAXLENGTH_DEVICEID];//设备ID
public byte[] szDeviceName = new byte[CONST_MAXLENGTH_DEVICENAME];//设备名称
public int nDeviceType;//设备类型
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("struInetAddr");
a.add("szUserID");
a.add("szPassword");
a.add("szDeviceID");
a.add("szDeviceName");
a.add("nDeviceType");
return a;
}
}
/**
* 设备基本信息结构体
* @author huting@four-faith.com
*
* @date 2019年3月27日
* @time 下午2:02:27
*/
public static class NET_DEVICE_INFOEX extends Structure { //设备类型
public NET_DEVICE_INFO struDeviceInfo;
public int nRouterMappingEnableFlag;//路由器映射标志
public byte[] szRouterAddr = new byte[CONST_MAXLENGTH_IP];//路由器地址,IP地址或域名
public int nRouterMappingControlPort;//控制映射端口
public int nRouterMappingTCPAVPort;//TCP音视频映射端口
public int nRouterMappingRTSPPort;//RTSP映射端口
public int nRouterMappingRTPPort;//RTP映射端口
public int nRouterMappingRTCPPort;//RTCP映射端口
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("struDeviceInfo");
a.add("nRouterMappingEnableFlag");
a.add("szRouterAddr");
a.add("nRouterMappingControlPort");
a.add("nRouterMappingTCPAVPort");
a.add("nRouterMappingRTSPPort");
a.add("nRouterMappingRTPPort");
a.add("nRouterMappingRTCPPort");
return a;
}
}
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
回调函数
package com.ffCamera.service.cdll;
import com.ffCamera.service.SNNetSdk.NET_ALARM_INFO;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
/**
* SNNetSdk_捷安视讯热感报警信息回调类
* @author huting@four-faith.com
*
* @date 2019年2月19日
* @time 下午5:09:46
*/
public interface AlarmCallBack extends StdCallCallback {
/**
* 报警回调
*
* @param lCMSHandle CMS Alarm Handle
* @param lpAlarmInfo 报警信息
* @param lpUserData 用户指针
*/
public void invoke(NativeLong lCMSHandle, NET_ALARM_INFO lpAlarmInfo, Pointer lpUserData);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
实现
package com.ffCamera.service.cdll;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ffCamera.data.AlarmMajorType;
import com.ffCamera.data.SecurityAlarmMinorType;
import com.ffCamera.data.TableNameEnum;
import com.ffCamera.entity.TsBiVideo;
import com.ffCamera.entity.TsDataVideo;
import com.ffCamera.service.ITsBiVideoService;
import com.ffCamera.service.ITsDataVideoService;
import com.ffCamera.service.SNNetSdk.NET_ALARM_INFO;
import com.ffCamera.util.CommonUtils;
import com.ffCamera.util.UuidUtil;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
/**
* SNNetSdk_捷安视讯热感报警信息回调实现类
* @author huting@four-faith.com
*
* @date 2019年2月19日
* @time 下午5:09:00
*/
public class AlarmCallbackImpl implements AlarmCallBack {
public static Logger log = LoggerFactory.getLogger(AlarmCallbackImpl.class);
private ITsBiVideoService tsBiVideoService;
private ITsDataVideoService tsDataVideoService;
public AlarmCallbackImpl(ITsBiVideoService tsBiVideoService,ITsDataVideoService tsDataVideoService) {
// TODO 自动生成的构造函数存根
this.tsBiVideoService=tsBiVideoService;
this.tsDataVideoService=tsDataVideoService;
}
public AlarmCallbackImpl() {
// TODO 自动生成的构造函数存根
}
@Override
public void invoke(NativeLong lCMSHandle, NET_ALARM_INFO lpAlarmInfo, Pointer lpUserData) {
// TODO 自动生成的方法存根
if(lpAlarmInfo.nAlarmFlag==1) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String gatherTime = lpAlarmInfo.struAlarmTime.nYear+"-"+
(lpAlarmInfo.struAlarmTime.nMonth>9?lpAlarmInfo.struAlarmTime.nMonth:("0"+lpAlarmInfo.struAlarmTime.nMonth))+"-"+
(lpAlarmInfo.struAlarmTime.nDay>9?lpAlarmInfo.struAlarmTime.nDay:("0"+lpAlarmInfo.struAlarmTime.nDay))+" "+
(lpAlarmInfo.struAlarmTime.nHour>9?lpAlarmInfo.struAlarmTime.nHour:("0"+lpAlarmInfo.struAlarmTime.nHour))+":"+
(lpAlarmInfo.struAlarmTime.nMinute>9?lpAlarmInfo.struAlarmTime.nMinute:("0"+lpAlarmInfo.struAlarmTime.nMinute))+":"+
(lpAlarmInfo.struAlarmTime.nSecond>9?lpAlarmInfo.struAlarmTime.nSecond:("0"+lpAlarmInfo.struAlarmTime.nSecond));
try {
TsDataVideo tsDataVideo = new TsDataVideo();
if(tsBiVideoService==null) {
return;
}
//根据设备ID获取视频设备信息
TsBiVideo tsBiVideo = this.tsBiVideoService.queryByDeviceNo(CommonUtils.getCopyByte(lpAlarmInfo.szDeviceId));
TsDataVideo tmp = null;
do {
String uuid = UuidUtil.getId();
tsDataVideo.setId(uuid);
tmp = this.tsDataVideoService.queryById(uuid);
}while(tmp!=null && !CommonUtils.isEmptyOrWhitespaceOnly(tmp.getId()));
tsDataVideo.setProjectno(tsBiVideo.getProjectno());//项目编号
tsDataVideo.setOffcomno(tsBiVideo.getOffcomno());//单位编号
tsDataVideo.setName(tsBiVideo.getName());//报警设备名称
tsDataVideo.setNo(tsBiVideo.getNo());//设备唯一编号
tsDataVideo.setGathertime(sdf.parse(gatherTime));//报警信息采集时间
tsDataVideo.setAlarm(AlarmMajorType.getMessage(lpAlarmInfo.nMajorType)+"-"+SecurityAlarmMinorType.getMessage(lpAlarmInfo.nMinorType));//报警类型
this.tsDataVideoService.saveVideoAlarmInfo(tsDataVideo,TableNameEnum.TS_DATA_VIDEO.getIndex());
//删除相关报警信息,再新增最新报警信息
this.tsDataVideoService.deleteVideoLastByNo(tsBiVideo.getNo(), tsBiVideo.getProjectno());
this.tsDataVideoService.saveVideoAlarmInfo(tsDataVideo,TableNameEnum.TS_DATA_VIDEO_LAST.getIndex());
} catch (ParseException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
log.error(e.getMessage());
}
log.info("报警标志:"+lpAlarmInfo.nAlarmFlag);
log.info("报警类型:主-"+lpAlarmInfo.nMajorType+",子-"+lpAlarmInfo.nMinorType);
log.info("报警时间:"+
lpAlarmInfo.struAlarmTime.nYear+"-"+
lpAlarmInfo.struAlarmTime.nMonth+"-"+
lpAlarmInfo.struAlarmTime.nDay+" "+
lpAlarmInfo.struAlarmTime.nHour+":"+
lpAlarmInfo.struAlarmTime.nMinute+":"+
lpAlarmInfo.struAlarmTime.nSecond);
log.info("报警设备ID:"+CommonUtils.getCopyByte(lpAlarmInfo.szDeviceId));
log.info("报警设备地址:"+CommonUtils.getCopyByte(lpAlarmInfo.szDeviceIp));
log.info("报警源ID:"+CommonUtils.getCopyByte(lpAlarmInfo.szSourceId)+",报警源名称:"+CommonUtils.getCopyByte(lpAlarmInfo.szSourceName));
}
}
}
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
# 海康云台控制
BOOL NET_DVR_Init();
/**
* 初始化SDK,调用其他SDK函数的前提。
* TRUE表示成功,FALSE表示失败。
* 接口返回失败请调用NET_DVR_GetLastError获取错误码,通过错误码判断出错原因。
* @return
*/
boolean NET_DVR_Init();
LONG NET_DVR_Login_V30(
char *sDVRIP,
WORD wDVRPort,
char *sUserName,
char *sPassword,
LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo
);
struct{
BYTE sSerialNumber[SERIALNO_LEN];
BYTE byAlarmInPortNum;
BYTE byAlarmOutPortNum;
BYTE byDiskNum;
BYTE byDVRType;
BYTE byChanNum;
BYTE byStartChan;
BYTE byAudioChanNum;
BYTE byIPChanNum;
BYTE byZeroChanNum;
BYTE byMainProto;
BYTE bySubProto;
BYTE bySupport;
BYTE bySupport1;
BYTE bySupport2;
WORD wDevType;
BYTE bySupport3;
BYTE byMultiStreamProto;
BYTE byStartDChan;
BYTE byStartDTalkChan;
BYTE byHighDChanNum;
BYTE bySupport4;
BYTE byLanguageType;
BYTE byVoiceInChanNum;
BYTE byStartVoiceInChanNo;
BYTE byRes3[2];
BYTE byMirrorChanNum;
WORD wStartMirrorChanNo;
BYTE byRes2[2];
}NET_DVR_DEVICEINFO_V30,*LPNET_DVR_DEVICEINFO_V30;
```java
int NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword, NET_DVR_DEVICEINFO_V30 lpDeviceInfo);
/**
* NET_DVR_Login_V30()参数结构
*/
public static class NET_DVR_DEVICEINFO_V30 extends Structure
{
public byte[] sSerialNumber = new byte[HcNetSdkDllConstants.SERIALNO_LEN]; //序列号
public byte byAlarmInPortNum; //报警输入个数
public byte byAlarmOutPortNum; //报警输出个数
public byte byDiskNum; //硬盘个数
public byte byDVRType; //设备类型, 1:DVR 2:ATM DVR 3:DVS ......
public byte byChanNum; //模拟通道个数
public byte byStartChan; //起始通道号,例如DVS-1,DVR - 1
public byte byAudioChanNum; //语音通道数
public byte byIPChanNum; //最大数字通道个数
public byte[] byRes1 = new byte[24]; //保留
@Override
protected List<String> getFieldOrder() {
// TODO 自动生成的方法存根
List<String> a = new ArrayList<String>();
a.add("sSerialNumber");
a.add("byAlarmInPortNum");
a.add("byAlarmOutPortNum");
a.add("byDiskNum");
a.add("byDVRType");
a.add("byChanNum");
a.add("byStartChan");
a.add("byAudioChanNum");
a.add("byIPChanNum");
a.add("byRes1");
return a;
}
}
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
BOOL NET_DVR_PTZCruise_Other(
LONG lUserID,
LONG lChannel,
DWORD dwPTZCruiseCmd,
BYTE byCruiseRoute,
BYTE byCruisePoint,
WORD wInput
);
2
3
4
5
6
7
8
/**
* 云台巡航操作。(不需要开启预览)
* @param lUserID NET_DVR_Login_V40等登录接口的返回值
* @param lChannel 通道号
* @param dwPTZCruiseCmd 操作云台巡航命令,见PtzCruiseCmdEnum
* @param byCruiseRoute 巡航路径,最多支持32条路径(序号从1开始)
* @param byCruisePoint 巡航点,最多支持32个点(序号从1开始)
* @param wInput 不同巡航命令时的值不同,预置点(最大300)、时间(最大255)、速度(最大40)
* @return
*/
boolean NET_DVR_PTZCruise_Other(int lUserID,int lChannel,int dwPTZCruiseCmd,byte byCruiseRoute, byte byCruisePoint, short wInput);
2
3
4
5
6
7
8
9
10
11