瀏覽代碼

Merge branch 'kun' of kunmeng/HikNetSDKPkg into master

kunmeng 1 月之前
父節點
當前提交
42ff097efc
共有 6 個文件被更改,包括 718 次插入93 次删除
  1. 2 13
      BallCamera.go
  2. 473 27
      Core/Type.go
  3. 33 48
      Core/core.go
  4. 172 0
      Nvr.go
  5. 33 0
      Nvr_test.go
  6. 5 5
      include/HCNetSDK.h

+ 2 - 13
BallCamera.go

@@ -299,7 +299,6 @@ func (this *BallCamera) PtzGotoPut(Action int, P, T, Z float64) error {
 		if err != nil {
 			return err
 		}
-		//println(PByte, TByte, ZByte)
 		pBuf := append([]byte{0xff, 0x01, 0x00, 0x4b}, PByte...)
 		tBuf := append([]byte{0xff, 0x01, 0x00, 0x4d}, TByte...)
 		zBuf := append([]byte{0xff, 0x01, 0x00, 0x4f}, ZByte...)
@@ -430,16 +429,6 @@ func verify(data []byte) (byte, error) {
 	return byte(checksum), nil
 }
 
-func (receiver *BallCamera) Logout() error {
-	//if receiver._type == BuKongQiu {
-	//	err := core.SerialStop(receiver.serialStartHandle)
-	//	if err != nil {
-	//		return err
-	//	}
-	//}
-	err := Core.Logout(receiver.userId)
-	if err != nil {
-		return err
-	}
-	return nil
+func (this *BallCamera) Logout() error {
+	return Core.Logout(this.userId)
 }

+ 473 - 27
Core/Type.go

@@ -1,5 +1,16 @@
 package Core
 
+/*
+#include "HCNetSDK.h"
+*/
+import "C"
+import "unsafe"
+
+const NAME_LEN = 32
+const PASSWD_LEN = 16
+const SERIALNO_LEN = 48
+const STREAM_ID_LEN = 32
+
 type DWORD uint32
 type WORD uint16
 type USHORT WORD
@@ -15,32 +26,467 @@ type UINT uint32
 // type LPDWORD unsigned int*
 type UINT64 uint64
 type INT64 int64
+
 type NET_DVR_DEVICEINFO_V30 struct {
-	SSerialNumber        [48]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           BYTE
-	WDevType             WORD
-	BySupport3           BYTE
-	ByMultiStreamProto   BYTE
-	ByStartDChan         BYTE
-	ByStartDTalkChan     BYTE
-	ByHighDChanNum       BYTE
-	BySupport4           BYTE
-	ByLanguageType       BYTE
-	ByVoiceInChanNum     BYTE
-	ByStartVoiceInChanNo BYTE
-	byMirrorChanNum      BYTE
-	wStartMirrorChanNo   WORD
+	cData             C.NET_DVR_DEVICEINFO_V30
+	SSerialNumber     []byte // 序列号
+	ByAlarmInPortNum  BYTE   // 模拟报警输入个数
+	ByAlarmOutPortNum BYTE   // 模拟报警输出个数
+	ByDiskNum         BYTE   // 硬盘个数
+	ByDVRType         BYTE   // 设备类型
+	ByChanNum         BYTE   // 设备模拟通道个数,数字(IP)通道最大个数为byIPChanNum + byHighDChanNum*256
+	ByStartChan       BYTE   // 模拟通道的起始通道号,从1开始。数字通道的起始通道号见下面参数byStartDChan
+	ByAudioChanNum    BYTE   // 设备语音对讲通道数
+	ByIPChanNum       BYTE   // 设备最大数字通道个数,低8位,高8位见byHighDChanNum。可以根据IP通道个数来判断是否调用NET_DVR_GetDVRConfig(配置命令NET_DVR_GET_IPPARACFG_V40)获取模拟和数字通道相关参数(NET_DVR_IPPARACFG_V40)。
+	ByZeroChanNum     BYTE   // 零通道编码个数
+	ByMainProto       BYTE   // 主码流传输协议类型:0- private,1- rtsp,2- 同时支持私有协议和rtsp协议取流(默认采用私有协议取流)
+	BySubProto        BYTE   // 子码流传输协议类型:0- private,1- rtsp,2- 同时支持私有协议和rtsp协议取流(默认采用私有协议取流)
+	BySupport         BYTE   // 能力,位与结果为0表示不支持,1表示支持
+	//bySupport & 0x1,表示是否支持智能搜索
+	//bySupport & 0x2,表示是否支持备份
+	//bySupport & 0x4,表示是否支持压缩参数能力获取
+	//bySupport & 0x8, 表示是否支持双网卡
+	//bySupport & 0x10, 表示支持远程SADP
+	//bySupport & 0x20, 表示支持Raid卡功能
+	//bySupport & 0x40, 表示支持IPSAN目录查找
+	//bySupport & 0x80, 表示支持rtp over rtsp
+	BySupport1 BYTE // 能力集扩充,位与结果为0表示不支持,1表示支持
+	//bySupport1 & 0x1, 表示是否支持snmp v30
+	//bySupport1 & 0x2, 表示是否支持区分回放和下载
+	//bySupport1 & 0x4, 表示是否支持布防优先级
+	//bySupport1 & 0x8, 表示智能设备是否支持布防时间段扩展
+	//bySupport1 & 0x10,表示是否支持多磁盘数(超过33个)
+	//bySupport1 & 0x20,表示是否支持rtsp over http
+	//bySupport1 & 0x80,表示是否支持车牌新报警信息,且还表示是否支持NET_DVR_IPPARACFG_V40配置
+	BySupport2 BYTE // 能力集扩充,位与结果为0表示不支持,1表示支持
+	//bySupport2 & 0x1, 表示解码器是否支持通过URL取流解码
+	//bySupport2 & 0x2, 表示是否支持FTPV40
+	//bySupport2 & 0x4, 表示是否支持ANR(断网录像)
+	//bySupport2 & 0x20, 表示是否支持单独获取设备状态子项
+	//bySupport2 & 0x40, 表示是否是码流加密设备
+	WDevType   WORD // 设备型号,详见下文列表
+	BySupport3 BYTE // 能力集扩充,位与结果为0表示不支持,1表示支持
+	//bySupport3 & 0x1, 表示是否支持多码流
+	//bySupport3 & 0x4, 表示是否支持按组配置,具体包含通道图像参数、报警输入参数、IP报警输入/输出接入参数、用户参数、设备工作状态、JPEG抓图、定时和时间抓图、硬盘盘组管理等
+	//bySupport3 & 0x20, 表示是否支持通过DDNS域名解析取流
+	ByMultiStreamProto BYTE // 是否支持多码流,按位表示,位与结果:0-不支持,1-支持
+	//byMultiStreamProto & 0x1, 表示是否支持码流3
+	//byMultiStreamProto & 0x2, 表示是否支持码流4
+	//byMultiStreamProto & 0x40,表示是否支持主码流
+	//byMultiStreamProto & 0x80,表示是否支持子码流
+	ByStartDChan     BYTE // 起始数字通道号,0表示无数字通道,比如DVR或IPC
+	ByStartDTalkChan BYTE // 起始数字对讲通道号,区别于模拟对讲通道号,0表示无数字对讲通道
+	ByHighDChanNum   BYTE // 数字通道个数,高8位
+	BySupport4       BYTE // 能力集扩展,按位表示,位与结果:0- 不支持,1- 支持
+	//bySupport4 & 0x01, 表示是否所有码流类型同时支持RTSP和私有协议
+	//bySupport4 & 0x10, 表示是否支持域名方式挂载网络硬盘
+	ByLanguageType BYTE // 支持语种能力,按位表示,位与结果:0- 不支持,1- 支持
+	//byLanguageType ==0,表示老设备,不支持该字段
+	//byLanguageType & 0x1,表示是否支持中文
+	//byLanguageType & 0x2,表示是否支持英文
+	ByVoiceInChanNum     BYTE // 音频输入通道数
+	ByStartVoiceInChanNo BYTE // 音频输入起始通道号,0表示无效
+	BySupport5           BYTE
+	BySupport6           BYTE
+	ByMirrorChanNum      BYTE // 镜像通道个数,录播主机中用于表示导播通道
+	WStartMirrorChanNo   WORD // 起始镜像通道号
+	BySupport7           BYTE
+	ByRes2               BYTE // 保留,置为0
+}
+
+func (this *NET_DVR_DEVICEINFO_V30) GetCPtr() *C.NET_DVR_DEVICEINFO_V30 {
+	return &this.cData
+}
+
+func (this *NET_DVR_DEVICEINFO_V30) Go() {
+	this.SSerialNumber = C.GoBytes(unsafe.Pointer(&this.cData.sSerialNumber), C.int(SERIALNO_LEN))
+	this.ByAlarmInPortNum = BYTE(this.cData.byAlarmInPortNum)
+	this.ByAlarmOutPortNum = BYTE(this.cData.byAlarmOutPortNum)
+	this.ByDiskNum = BYTE(this.cData.byDiskNum)
+	this.ByDVRType = BYTE(this.cData.byDVRType)
+	this.ByChanNum = BYTE(this.cData.byChanNum)
+	this.ByStartChan = BYTE(this.cData.byStartChan)
+	this.ByAudioChanNum = BYTE(this.cData.byAudioChanNum)
+	this.ByIPChanNum = BYTE(this.cData.byIPChanNum)
+	this.ByZeroChanNum = BYTE(this.cData.byZeroChanNum)
+	this.ByMainProto = BYTE(this.cData.byMainProto)
+	this.BySubProto = BYTE(this.cData.bySubProto)
+	this.BySupport = BYTE(this.cData.bySupport)
+	this.BySupport1 = BYTE(this.cData.bySupport1)
+	this.BySupport2 = BYTE(this.cData.bySupport2)
+	this.WDevType = WORD(this.cData.wDevType)
+	this.BySupport3 = BYTE(this.cData.bySupport3)
+	this.ByMultiStreamProto = BYTE(this.cData.byMultiStreamProto)
+	this.ByStartDChan = BYTE(this.cData.byStartDChan)
+	this.ByStartDTalkChan = BYTE(this.cData.byStartDTalkChan)
+	this.ByHighDChanNum = BYTE(this.cData.byHighDChanNum)
+	this.BySupport4 = BYTE(this.cData.bySupport4)
+	this.ByLanguageType = BYTE(this.cData.byLanguageType)
+	this.ByVoiceInChanNum = BYTE(this.cData.byVoiceInChanNum)
+	this.ByStartVoiceInChanNo = BYTE(this.cData.byStartVoiceInChanNo)
+	this.BySupport5 = BYTE(this.cData.bySupport5)
+	this.BySupport6 = BYTE(this.cData.bySupport6)
+	this.ByMirrorChanNum = BYTE(this.cData.byMirrorChanNum)
+	this.WStartMirrorChanNo = WORD(this.cData.wStartMirrorChanNo)
+	this.BySupport7 = BYTE(this.cData.bySupport7)
+	this.ByRes2 = BYTE(this.cData.byRes2)
+}
+
+type NET_DVR_NETAPPCFG struct {
+	cData               C.NET_DVR_NETAPPCFG
+	DwSize              DWORD
+	SDNSIp              []byte
+	StruNtpClientParam  NET_DVR_NTPPARA
+	StruDDNSClientParam NET_DVR_DDNSPARA
+	Res                 []byte
+}
+
+func (this *NET_DVR_NETAPPCFG) GetCPtr() *C.NET_DVR_NETAPPCFG {
+	return &this.cData
+}
+
+func (this *NET_DVR_NETAPPCFG) GetC() C.NET_DVR_NETAPPCFG {
+	return this.cData
+}
+
+func (this *NET_DVR_NETAPPCFG) Go() {
+	this.DwSize = DWORD(this.cData.dwSize)
+	this.SDNSIp = C.GoBytes(unsafe.Pointer(&this.cData.sDNSIp), C.int(16))
+	this.StruNtpClientParam.SetC(this.cData.struNtpClientParam)
+	this.StruDDNSClientParam.SetC(this.cData.struDDNSClientParam)
+	this.Res = C.GoBytes(unsafe.Pointer(&this.cData.res), C.int(464))
+}
+
+type NET_DVR_NTPPARA struct {
+	cData            C.NET_DVR_NTPPARA
+	SNTPServer       []byte
+	WInterval        WORD
+	ByEnableNTP      BYTE
+	CTimeDifferenceH int8
+	CTimeDifferenceM int8
+	Res1             BYTE
+	WNtpPort         WORD
+	Res2             []byte
+}
+
+// Set NET_DVR_NTPPARA 的 cData
+func (this *NET_DVR_NTPPARA) SetC(cData C.NET_DVR_NTPPARA) {
+	this.cData = cData
+	this.Go()
+}
+
+func (this *NET_DVR_NTPPARA) GetCPtr() *C.NET_DVR_NTPPARA {
+	return &this.cData
+}
+func (this *NET_DVR_NTPPARA) Go() {
+	this.SNTPServer = C.GoBytes(unsafe.Pointer(&this.cData.sNTPServer), C.int(64))
+	this.WInterval = WORD(this.cData.wInterval)
+	this.ByEnableNTP = BYTE(this.cData.byEnableNTP)
+	this.CTimeDifferenceH = int8(this.cData.cTimeDifferenceH)
+	this.CTimeDifferenceM = int8(this.cData.cTimeDifferenceM)
+	this.Res1 = BYTE(this.cData.res1)
+	this.WNtpPort = WORD(this.cData.wNtpPort)
+	this.Res2 = C.GoBytes(unsafe.Pointer(&this.cData.res2), C.int(8))
+}
+
+type NET_DVR_DDNSPARA struct {
+	cData        C.NET_DVR_DDNSPARA
+	SUserName    []byte
+	SPassword    []byte
+	SDomainName  []byte
+	ByEnableDDNS BYTE
+	Res          []byte
+}
+
+func (this *NET_DVR_DDNSPARA) SetC(cData C.NET_DVR_DDNSPARA) {
+	this.cData = cData
+	this.Go()
+}
+
+func (this *NET_DVR_DDNSPARA) GetCPtr() *C.NET_DVR_DDNSPARA {
+	return &this.cData
+}
+func (this *NET_DVR_DDNSPARA) Go() {
+	this.SUserName = C.GoBytes(unsafe.Pointer(&this.cData.sUsername), C.int(NAME_LEN))
+	this.SPassword = C.GoBytes(unsafe.Pointer(&this.cData.sPassword), C.int(PASSWD_LEN))
+	this.SDomainName = C.GoBytes(unsafe.Pointer(&this.cData.sDomainName), C.int(64))
+	this.ByEnableDDNS = BYTE(this.cData.byEnableDDNS)
+	this.Res = C.GoBytes(unsafe.Pointer(&this.cData.res), C.int(15))
+}
+
+type NET_DVR_MRD_SEARCH_PARAM struct {
+	cData          C.NET_DVR_MRD_SEARCH_PARAM
+	DwSize         DWORD
+	StruStreamInfo NET_DVR_STREAM_INFO
+	WYear          WORD
+	ByMonth        BYTE
+	ByDrawFrame    BYTE
+	ByStreamType   BYTE
+	ByLocalOrUTC   BYTE
+	ByRes          []byte
+}
+
+func (this *NET_DVR_MRD_SEARCH_PARAM) g2c() {
+	this.cData.dwSize = C.DWORD(this.DwSize)
+	this.cData.struStreamInfo = this.StruStreamInfo.GetC()
+	this.cData.wYear = C.WORD(this.WYear)
+	this.cData.byMonth = C.BYTE(this.ByMonth)
+	this.cData.byDrawFrame = C.BYTE(this.ByDrawFrame)
+	this.cData.byStreamType = C.BYTE(this.ByStreamType)
+	this.cData.byLocalOrUTC = C.BYTE(this.ByLocalOrUTC)
+	var cArray [30]C.BYTE
+	for i := 0; i < len(this.ByRes); i++ {
+		cArray[i] = C.BYTE(this.ByRes[i])
+	}
+	this.cData.byRes = cArray
+}
+func (this *NET_DVR_MRD_SEARCH_PARAM) SetC(cData C.NET_DVR_MRD_SEARCH_PARAM) {
+	this.cData = cData
+	this.Go()
+}
+
+func (this *NET_DVR_MRD_SEARCH_PARAM) GetCPtr() *C.NET_DVR_MRD_SEARCH_PARAM {
+	this.g2c()
+	return &this.cData
+}
+func (this *NET_DVR_MRD_SEARCH_PARAM) GetC() C.NET_DVR_MRD_SEARCH_PARAM {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_MRD_SEARCH_PARAM) Go() {
+	this.DwSize = DWORD(this.cData.dwSize)
+	this.StruStreamInfo.SetC(this.cData.struStreamInfo)
+	this.WYear = WORD(this.cData.wYear)
+	this.ByMonth = BYTE(this.cData.byMonth)
+	this.ByDrawFrame = BYTE(this.cData.byDrawFrame)
+	this.ByStreamType = BYTE(this.cData.byStreamType)
+	this.ByLocalOrUTC = BYTE(this.cData.byLocalOrUTC)
+	this.ByRes = C.GoBytes(unsafe.Pointer(&this.cData.byRes), C.int(30))
+}
+
+type NET_DVR_STREAM_INFO struct {
+	cData     C.NET_DVR_STREAM_INFO
+	DwSize    DWORD
+	ByID      []byte
+	DwChannel DWORD
+	ByRes     []byte
+}
+
+func (this *NET_DVR_STREAM_INFO) g2c() {
+	var byIDArray [STREAM_ID_LEN]C.BYTE
+	for i := 0; i < len(this.ByID); i++ {
+		byIDArray[i] = C.BYTE(this.ByID[i])
+	}
+	var byResArray [32]C.BYTE
+	for i := 0; i < len(this.ByRes); i++ {
+		byResArray[i] = C.BYTE(this.ByRes[i])
+	}
+	this.cData.dwSize = C.DWORD(this.DwSize)
+	this.cData.byID = byIDArray
+	this.cData.dwChannel = C.DWORD(this.DwChannel)
+	this.cData.byRes = byResArray
+}
+
+func (this *NET_DVR_STREAM_INFO) SetC(cData C.NET_DVR_STREAM_INFO) {
+	this.cData = cData
+	this.Go()
+}
+func (this *NET_DVR_STREAM_INFO) GetC() C.NET_DVR_STREAM_INFO {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_STREAM_INFO) GetCPtr() *C.NET_DVR_STREAM_INFO {
+	this.g2c()
+	return &this.cData
+}
+func (this *NET_DVR_STREAM_INFO) Go() {
+	this.DwSize = DWORD(this.cData.dwSize)
+	this.ByID = C.GoBytes(unsafe.Pointer(&this.cData.byID), C.int(STREAM_ID_LEN))
+	this.DwChannel = DWORD(this.cData.dwChannel)
+	this.ByRes = C.GoBytes(unsafe.Pointer(&this.cData.byRes), C.int(32))
+}
+
+type NET_DVR_MRD_SEARCH_RESULT struct {
+	cData                C.NET_DVR_MRD_SEARCH_RESULT
+	DwSize               DWORD
+	ByRecordDistribution []byte
+	ByHasEventRecode     []byte
+	ByRes                BYTE
+}
+
+func (this *NET_DVR_MRD_SEARCH_RESULT) g2c() {
+	var byRecordDistributionArray [32]C.BYTE
+	for i := 0; i < len(this.ByRecordDistribution); i++ {
+		byRecordDistributionArray[i] = C.BYTE(this.ByRecordDistribution[i])
+	}
+	var byHasEventRecodeArray [31]C.BYTE
+	for i := 0; i < len(this.ByHasEventRecode); i++ {
+		byHasEventRecodeArray[i] = C.BYTE(this.ByHasEventRecode[i])
+	}
+
+	this.cData.dwSize = C.DWORD(this.DwSize)
+	this.cData.byRecordDistribution = byRecordDistributionArray
+	this.cData.byHasEventRecode = byHasEventRecodeArray
+	this.cData.byRes = C.BYTE(this.ByRes)
+}
+func (this *NET_DVR_MRD_SEARCH_RESULT) SetC(cData C.NET_DVR_MRD_SEARCH_RESULT) {
+	this.cData = cData
+	this.Go()
+}
+func (this *NET_DVR_MRD_SEARCH_RESULT) GetC() C.NET_DVR_MRD_SEARCH_RESULT {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_MRD_SEARCH_RESULT) GetCPtr() *C.NET_DVR_MRD_SEARCH_RESULT {
+	this.g2c()
+	return &this.cData
+}
+func (this *NET_DVR_MRD_SEARCH_RESULT) Go() {
+	this.DwSize = DWORD(this.cData.dwSize)
+	this.ByRecordDistribution = C.GoBytes(unsafe.Pointer(&this.cData.byRecordDistribution), C.int(32))
+	this.ByHasEventRecode = C.GoBytes(unsafe.Pointer(&this.cData.byHasEventRecode), C.int(31))
+	this.ByRes = BYTE(this.cData.byRes)
+}
+
+type NET_DVR_FILECOND struct {
+	cData         C.NET_DVR_FILECOND
+	LChannel      LONG
+	DwFileType    DWORD
+	DwIsLocked    DWORD
+	DwUseCardNo   DWORD
+	SCardNumber   []byte
+	StruStartTime NET_DVR_TIME
+	StruStopTime  NET_DVR_TIME
+}
+
+func (this *NET_DVR_FILECOND) g2c() {
+	this.cData.lChannel = C.LONG(this.LChannel)
+	this.cData.dwFileType = C.DWORD(this.DwFileType)
+	this.cData.dwIsLocked = C.DWORD(this.DwIsLocked)
+	this.cData.dwUseCardNo = C.DWORD(this.DwUseCardNo)
+	var sCardNumberArray [32]C.BYTE
+	for i := 0; i < len(this.SCardNumber); i++ {
+		sCardNumberArray[i] = C.BYTE(this.SCardNumber[i])
+	}
+	this.cData.sCardNumber = sCardNumberArray
+	this.cData.struStartTime = this.StruStartTime.GetC()
+	this.cData.struStopTime = this.StruStopTime.GetC()
+}
+func (this *NET_DVR_FILECOND) SetC(cData C.NET_DVR_FILECOND) {
+	this.cData = cData
+	this.Go()
+}
+func (this *NET_DVR_FILECOND) GetC() C.NET_DVR_FILECOND {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_FILECOND) GetCPtr() *C.NET_DVR_FILECOND {
+	this.g2c()
+	return &this.cData
+}
+
+func (this *NET_DVR_FILECOND) Go() {
+	this.LChannel = LONG(this.cData.lChannel)
+	this.DwFileType = DWORD(this.cData.dwFileType)
+	this.DwIsLocked = DWORD(this.cData.dwIsLocked)
+	this.DwUseCardNo = DWORD(this.cData.dwUseCardNo)
+	this.SCardNumber = C.GoBytes(unsafe.Pointer(&this.cData.sCardNumber), C.int(64))
+	this.StruStartTime.SetC(this.cData.struStartTime)
+	this.StruStopTime.SetC(this.cData.struStopTime)
+}
+
+type NET_DVR_TIME struct {
+	cData    C.NET_DVR_TIME
+	DwYear   DWORD
+	DwMonth  DWORD
+	DwDay    DWORD
+	DwHour   DWORD
+	DwMinute DWORD
+	DwSecond DWORD
+}
+
+func (this *NET_DVR_TIME) g2c() {
+	this.cData.dwYear = C.DWORD(this.DwYear)
+	this.cData.dwMonth = C.DWORD(this.DwMonth)
+	this.cData.dwDay = C.DWORD(this.DwDay)
+	this.cData.dwHour = C.DWORD(this.DwHour)
+	this.cData.dwMinute = C.DWORD(this.DwMinute)
+	this.cData.dwSecond = C.DWORD(this.DwSecond)
+}
+func (this *NET_DVR_TIME) SetC(cData C.NET_DVR_TIME) {
+	this.cData = cData
+	this.Go()
+}
+func (this *NET_DVR_TIME) GetC() C.NET_DVR_TIME {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_TIME) GetCPtr() *C.NET_DVR_TIME {
+	this.g2c()
+	return &this.cData
+}
+func (this *NET_DVR_TIME) Go() {
+	this.DwYear = DWORD(this.cData.dwYear)
+	this.DwMonth = DWORD(this.cData.dwMonth)
+	this.DwDay = DWORD(this.cData.dwDay)
+	this.DwHour = DWORD(this.cData.dwHour)
+	this.DwMinute = DWORD(this.cData.dwMinute)
+	this.DwSecond = DWORD(this.cData.dwSecond)
+}
+
+type NET_DVR_FINDDATA_V30 struct {
+	cData         C.NET_DVR_FINDDATA_V30
+	SFileName     []byte
+	StruStartTime NET_DVR_TIME
+	StruStopTime  NET_DVR_TIME
+	DwFileSize    DWORD
+	SCardNum      []byte
+	ByLocked      BYTE
+	ByFileType    BYTE
+	ByRes         []byte
+}
+
+func (this *NET_DVR_FINDDATA_V30) g2c() {
+	var sFileNameArray [100]C.BYTE
+	for i := 0; i < len(this.SFileName); i++ {
+		sFileNameArray[i] = C.BYTE(this.SFileName[i])
+	}
+	this.cData.struStartTime = this.StruStartTime.GetC()
+	this.cData.struStopTime = this.StruStopTime.GetC()
+	this.cData.dwFileSize = C.DWORD(this.DwFileSize)
+	var sCardNumArray [32]C.BYTE
+	for i := 0; i < len(this.SCardNum); i++ {
+		sCardNumArray[i] = C.BYTE(this.SCardNum[i])
+	}
+	this.cData.byLocked = C.BYTE(this.ByLocked)
+	this.cData.byFileType = C.BYTE(this.ByFileType)
+	var byResArray [2]C.BYTE
+	for i := 0; i < len(this.ByRes); i++ {
+		byResArray[i] = C.BYTE(this.ByRes[i])
+	}
+	this.cData.byRes = byResArray
+}
+
+func (this *NET_DVR_FINDDATA_V30) SetC(cData C.NET_DVR_FINDDATA_V30) {
+	this.cData = cData
+	this.Go()
+}
+
+func (this *NET_DVR_FINDDATA_V30) GetC() C.NET_DVR_FINDDATA_V30 {
+	this.g2c()
+	return this.cData
+}
+func (this *NET_DVR_FINDDATA_V30) GetCPtr() *C.NET_DVR_FINDDATA_V30 {
+	this.g2c()
+	return &this.cData
+}
+func (this *NET_DVR_FINDDATA_V30) Go() {
+	this.SFileName = C.GoBytes(unsafe.Pointer(&this.cData.sFileName), C.int(100))
+	this.StruStartTime.SetC(this.cData.struStartTime)
+	this.StruStopTime.SetC(this.cData.struStopTime)
+	this.DwFileSize = DWORD(this.cData.dwFileSize)
+	this.SCardNum = C.GoBytes(unsafe.Pointer(&this.cData.sCardNum), C.int(32))
+	this.ByLocked = BYTE(this.cData.byLocked)
+	this.ByFileType = BYTE(this.cData.byFileType)
+	this.ByRes = C.GoBytes(unsafe.Pointer(&this.cData.byRes), C.int(12))
 }

+ 33 - 48
Core/core.go

@@ -49,13 +49,13 @@ func Login(Ip string, Port int, Username string, Password string) (LONG, NET_DVR
 	defer C.free(unsafe.Pointer(cUsername))
 	cPassword := C.CString(Password)
 	defer C.free(unsafe.Pointer(cPassword))
-	var DeviceInfo C.NET_DVR_DEVICEINFO_V30
-	cUserId := C.NET_DVR_Login_V30(cIp, C.WORD(Port), cUsername, cPassword, &DeviceInfo)
+	var DeviceInfo NET_DVR_DEVICEINFO_V30
+	cUserId := C.NET_DVR_Login_V30(cIp, C.WORD(Port), cUsername, cPassword, DeviceInfo.GetCPtr())
 	if LONG(cUserId) == -1 {
 		return -1, NET_DVR_DEVICEINFO_V30{}, LastError("NET_DVR_Login_V30")
 	}
-	DATA := CNET_DVR_DEVICEINFO_V30ToGO(&DeviceInfo)
-	return LONG(cUserId), DATA, nil
+	DeviceInfo.Go()
+	return LONG(cUserId), DeviceInfo, nil
 }
 
 func Logout(userId LONG) error {
@@ -67,6 +67,12 @@ func Logout(userId LONG) error {
 	}
 	return nil
 }
+func NET_DVR_FindClose_V30(QueryHandle LONG) error {
+	if C.NET_DVR_FindClose_V30(C.LONG(QueryHandle)) == C.FALSE {
+		return LastError("NET_DVR_FindClose_V30")
+	}
+	return nil
+}
 
 func SerialStart(UserId LONG, CallBack serialDataCallBack) (LONG, error) {
 	SerialStartParam := C.NET_DVR_SERIALSTART_V40{}
@@ -111,19 +117,10 @@ func (d *CDVR_PTZPOS) Go() DVR_PTZPOS {
 	}
 }
 func (d *CDVR_PTZPOS) Set(Action, PanPos, TiltPos, ZoomPos float64) {
-	//a1 := DEC2HEX(Action)
-	//a2 := DEC2HEX(PanPos)
-	//a3 := DEC2HEX(TiltPos)
-	//a4 := DEC2HEX(ZoomPos)
-	//println(a1, a2, a3, a4)
 	d.wAction = C.WORD(Action)
 	d.wPanPos = C.WORD(DEC2HEX(PanPos))
 	d.wTiltPos = C.WORD(DEC2HEX(TiltPos))
 	d.wZoomPos = C.WORD(DEC2HEX(ZoomPos))
-	//d.wAction = C.WORD(1)
-	//d.wPanPos = C.WORD(0x77)
-	//d.wTiltPos = C.WORD(0x88)
-	//d.wZoomPos = C.WORD(0x99)
 }
 
 type DVR_PTZPOS struct {
@@ -189,6 +186,14 @@ func SetDVRConfig(lUserID LONG, dwCommand DWORD, lChannel LONG, lpInBuffer unsaf
 	return nil
 }
 
+func GetDVRDeviceConfig(lUserID LONG, dwCommand DWORD, dwCount DWORD, lpInBuffer unsafe.Pointer, dwInBufferSize DWORD, lpStatusList unsafe.Pointer, lpOutBuffer unsafe.Pointer, dwOutBufferSize DWORD) error {
+	cResult := C.NET_DVR_GetDeviceConfig(C.LONG(lUserID), C.DWORD(dwCommand), C.DWORD(dwCount), C.LPVOID(lpInBuffer), C.DWORD(dwInBufferSize), C.LPVOID(lpStatusList), C.LPVOID(lpOutBuffer), C.DWORD(dwOutBufferSize))
+	if cResult != 1 {
+		return LastError("NET_DVR_GetDeviceConfig")
+	}
+	return nil
+}
+
 func LastError(funcName string) error {
 	cCode := C.NET_DVR_GetLastError()
 	if cCode == 0 {
@@ -214,39 +219,19 @@ func PTZControlWithSpeed_Other(lUserID LONG, lChannel LONG, dwPTZCommand DWORD,
 	return nil
 }
 
-func CNET_DVR_DEVICEINFO_V30ToGO(CData *C.NET_DVR_DEVICEINFO_V30) NET_DVR_DEVICEINFO_V30 {
-	var goData NET_DVR_DEVICEINFO_V30
-
-	// Copy the SSerialNumber field
-	for i := 0; i < 48; i++ {
-		goData.SSerialNumber[i] = BYTE(byte(CData.sSerialNumber[i]))
-	}
-
-	// Copy other fields
-	goData.ByAlarmInPortNum = BYTE(CData.byAlarmInPortNum)
-	goData.ByAlarmOutPortNum = BYTE(CData.byAlarmOutPortNum)
-	goData.ByDiskNum = BYTE(CData.byDiskNum)
-	goData.ByDVRType = BYTE(CData.byDVRType)
-	goData.ByChanNum = BYTE(CData.byChanNum)
-	goData.ByStartChan = BYTE(CData.byStartChan)
-	goData.ByAudioChanNum = BYTE(CData.byAudioChanNum)
-	goData.ByIPChanNum = BYTE(CData.byIPChanNum)
-	goData.ByZeroChanNum = BYTE(CData.byZeroChanNum)
-	goData.ByMainProto = BYTE(CData.byMainProto)
-	goData.BySubProto = BYTE(CData.bySubProto)
-	goData.BySupport = BYTE(CData.bySupport)
-	goData.BySupport1 = BYTE(CData.bySupport1)
-	goData.BySupport2 = BYTE(CData.bySupport2)
-	goData.WDevType = WORD(CData.wDevType)
-	goData.BySupport3 = BYTE(CData.bySupport3)
-	goData.ByMultiStreamProto = BYTE(CData.byMultiStreamProto)
-	goData.ByStartDChan = BYTE(CData.byStartDChan)
-	goData.ByStartDTalkChan = BYTE(CData.byStartDTalkChan)
-	goData.ByHighDChanNum = BYTE(CData.byHighDChanNum)
-	goData.BySupport4 = BYTE(CData.bySupport4)
-	goData.ByLanguageType = BYTE(CData.byLanguageType)
-	goData.ByVoiceInChanNum = BYTE(CData.byVoiceInChanNum)
-	goData.ByStartVoiceInChanNo = BYTE(CData.byStartVoiceInChanNo)
-
-	return goData
+func NET_DVR_FindFile_V30(lUserID LONG, lpFindFileInfo NET_DVR_FILECOND) (LONG, error) {
+	Handle := C.NET_DVR_FindFile_V30(C.LONG(lUserID), lpFindFileInfo.GetCPtr())
+	if Handle == -1 {
+		return 0, LastError("NET_DVR_FindFile_V30")
+	}
+	return LONG(Handle), nil
+}
+
+func NET_DVR_FindNextFile_V30(lFindHandle LONG, lpFindData *NET_DVR_FINDDATA_V30) (LONG, error) {
+	state := C.NET_DVR_FindNextFile_V30(C.LONG(lFindHandle), (*lpFindData).GetCPtr())
+	if state == -1 {
+		return 0, LastError("NET_DVR_FindNextFile_V30")
+	}
+	lpFindData.Go()
+	return LONG(state), nil
 }

+ 172 - 0
Nvr.go

@@ -0,0 +1,172 @@
+package HikSDK
+
+/*
+#cgo LDFLAGS: -Wl,--allow-multiple-definition
+#include <stdio.h>
+#include <string.h>
+*/
+import "C"
+import (
+	"gitea.com/kunmeng/HikNetSDKPkg/Core"
+	"time"
+	"unsafe"
+)
+
+type Nvr struct {
+	userId     Core.LONG
+	deviceInfo Core.NET_DVR_DEVICEINFO_V30
+}
+
+func NewNvr(Ip string, Port int, Username, Password string) (*Nvr, error) {
+	userId, deviceInfo, err := Core.Login(Ip, Port, Username, Password)
+	if err != nil {
+		return nil, err
+	}
+	return &Nvr{
+		userId:     userId,
+		deviceInfo: deviceInfo,
+	}, nil
+}
+
+func (this *Nvr) getNvrUTCDiff() (int, error) {
+	var data Core.NET_DVR_NETAPPCFG
+	var dataPtr = unsafe.Pointer(data.GetCPtr())
+	err := Core.GetDVRConfig(this.userId, 222, 0, dataPtr, Core.DWORD(unsafe.Sizeof(data.GetC())))
+	if err != nil {
+		return 0, err
+	}
+	data.Go()
+
+	return int(data.StruNtpClientParam.CTimeDifferenceH)*60 + int(data.StruNtpClientParam.CTimeDifferenceM)*map[int8]int{-1: -1, 0: 1}[data.StruNtpClientParam.CTimeDifferenceH>>7], nil
+}
+
+func (this *Nvr) CheckTimeRegionWithMonth(Year, Month, Channel uint16) ([]uint8, error) {
+
+	//	//// 查当月
+	var struSearchParam Core.NET_DVR_MRD_SEARCH_PARAM
+	struSearchParam.DwSize = Core.DWORD(unsafe.Sizeof(struSearchParam.GetC()))
+	struSearchParam.WYear = Core.WORD(Year)
+	struSearchParam.ByMonth = Core.BYTE(Month)
+	struSearchParam.StruStreamInfo.DwChannel = Core.DWORD(32 + Channel)
+	struSearchParam.ByLocalOrUTC = 1
+	struSearchParam.ByDrawFrame = 0
+	struSearchParam.ByStreamType = 0
+
+	var dataPtr = unsafe.Pointer(struSearchParam.GetCPtr())
+
+	var ResData Core.NET_DVR_MRD_SEARCH_RESULT
+	var ResDataPtr = unsafe.Pointer(ResData.GetCPtr())
+
+	err := Core.GetDVRDeviceConfig(this.userId, 6164, 0, dataPtr, Core.DWORD(unsafe.Sizeof(struSearchParam.GetC())), nil, ResDataPtr, Core.DWORD(unsafe.Sizeof(ResData.GetC())))
+	if err != nil {
+		return nil, err
+	}
+	ResData.Go()
+	var res []uint8
+	for i := 0; i < 32; i++ {
+		if ResData.ByRecordDistribution[i] != 0 {
+			res = append(res, uint8(i+1))
+		}
+	}
+	return res, nil
+}
+
+func (this *Nvr) CheckTimeRegionWithDay(Year, Month, Day, Channel uint16) ([]TimeRange, error) {
+	var Data Core.NET_DVR_FILECOND
+	Data.DwFileType = 0xff
+	Data.DwIsLocked = 0xff
+	Data.DwUseCardNo = 0
+	Data.LChannel = Core.LONG(32 + Channel)
+	StartTime := Core.NET_DVR_TIME{
+		DwYear:   Core.DWORD(Year),
+		DwMonth:  Core.DWORD(Month),
+		DwDay:    Core.DWORD(Day),
+		DwHour:   0,
+		DwMinute: 0,
+		DwSecond: 0,
+	}
+	StopTime := Core.NET_DVR_TIME{
+		DwYear:   Core.DWORD(Year),
+		DwMonth:  Core.DWORD(Month),
+		DwDay:    Core.DWORD(Day),
+		DwHour:   23,
+		DwMinute: 59,
+		DwSecond: 59,
+	}
+	Data.StruStartTime = StartTime
+	Data.StruStopTime = StopTime
+	QueryHandle, err := Core.NET_DVR_FindFile_V30(this.userId, Data)
+	if err != nil {
+		return nil, err
+	}
+	var FindData Core.NET_DVR_FINDDATA_V30
+	var state Core.LONG
+	state, err = Core.NET_DVR_FindNextFile_V30(QueryHandle, &FindData)
+	if err != nil {
+		return nil, err
+	}
+	ByUTCDiff, err := this.getNvrUTCDiff()
+	if err != nil {
+		return nil, err
+	}
+	var res []TimeRange
+	for state > 0 {
+		var StartTimeObj time.Time
+		var EndTimeObj time.Time
+
+		if state == 1001 {
+			break
+		}
+		if state == 1003 {
+			break
+		}
+		if state == 1004 {
+			break
+		}
+		if state == 1000 {
+			if uint16(FindData.StruStartTime.DwDay) != Day {
+				StartTimeObj = time.Date(int(FindData.StruStartTime.DwYear), time.Month(FindData.StruStartTime.DwMonth), int(FindData.StruStartTime.DwDay), 0, 0, 0, 0, time.UTC)
+			} else {
+				StartTimeObj = time.Date(int(FindData.StruStartTime.DwYear), time.Month(FindData.StruStartTime.DwMonth), int(FindData.StruStartTime.DwDay), int(FindData.StruStartTime.DwHour), int(FindData.StruStartTime.DwMinute), int(FindData.StruStartTime.DwSecond), 0, time.UTC)
+			}
+			if uint16(FindData.StruStopTime.DwDay) != Day {
+				EndTimeObj = time.Date(int(FindData.StruStopTime.DwYear), time.Month(FindData.StruStopTime.DwMonth), int(FindData.StruStopTime.DwDay), 0, 0, 0, 0, time.UTC)
+			} else {
+				EndTimeObj = time.Date(int(FindData.StruStopTime.DwYear), time.Month(FindData.StruStopTime.DwMonth), int(FindData.StruStopTime.DwDay), int(FindData.StruStopTime.DwHour), int(FindData.StruStopTime.DwMinute), int(FindData.StruStopTime.DwSecond), 0, time.UTC)
+			}
+			StartTimeObj = StartTimeObj.Add(time.Minute * time.Duration(ByUTCDiff))
+			EndTimeObj = EndTimeObj.Add(time.Minute * time.Duration(ByUTCDiff))
+			res = append(res, TimeRange{
+				StartTime: StartTimeObj,
+				EndTime:   EndTimeObj,
+			})
+		}
+		if state == 1002 {
+			FindData = Core.NET_DVR_FINDDATA_V30{}
+			state, err = Core.NET_DVR_FindNextFile_V30(QueryHandle, &FindData)
+			time.Sleep(time.Millisecond * 5)
+			continue
+		}
+
+		FindData = Core.NET_DVR_FINDDATA_V30{}
+		state, err = Core.NET_DVR_FindNextFile_V30(QueryHandle, &FindData)
+		if err != nil {
+			return res, err
+		}
+		time.Sleep(time.Millisecond * 5)
+	}
+
+	err = Core.NET_DVR_FindClose_V30(QueryHandle)
+	if err != nil {
+		return nil, err
+	}
+	return res, nil
+}
+func (this *Nvr) Logout() error {
+	return Core.Logout(this.userId)
+}
+
+type TimeRange struct {
+	StartTime time.Time
+	EndTime   time.Time
+}

+ 33 - 0
Nvr_test.go

@@ -0,0 +1,33 @@
+package HikSDK
+
+import (
+	"gitea.com/kunmeng/HikNetSDKPkg/Core"
+	"testing"
+)
+
+func TestNewNvr(t *testing.T) {
+	err := Core.Init()
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	nvr, err := NewNvr("192.168.211.124", 8000, "admin", "guanyaokeji8520")
+	if err != nil {
+		t.Error(err)
+	}
+	diff, err := nvr.getNvrUTCDiff()
+	if err != nil {
+		return
+	}
+	t.Log(diff)
+	month, err := nvr.CheckTimeRegionWithMonth(2025, 3, 1)
+	if err != nil {
+		return
+	}
+	t.Log(month)
+	timeList, err := nvr.CheckTimeRegionWithDay(2025, 3, 20, 1)
+	if err != nil {
+		return
+	}
+	t.Log(timeList)
+}

+ 5 - 5
include/HCNetSDK.h

@@ -12816,7 +12816,7 @@ typedef struct
 }NET_DVR_EMAILPARA, *LPNET_DVR_EMAILPARA;
 
 //�����������
-typedef struct 
+typedef struct NET_DVR_NETAPPCFG
 {
     DWORD  dwSize;
     char  sDNSIp[16];                /* DNS��������ַ */
@@ -13492,7 +13492,7 @@ typedef struct
 }NET_DVR_DEVICEINFO, *LPNET_DVR_DEVICEINFO;
 
 //NET_DVR_Login_V30()�����ṹ
-typedef struct
+typedef struct NET_DVR_DEVICEINFO_V30
 {
     BYTE sSerialNumber[SERIALNO_LEN];  //���к�
     BYTE byAlarmInPortNum;                //�����������
@@ -13580,7 +13580,7 @@ typedef struct
     // bySupport7 & 0x40  ��ʾ�豸�Ƿ�֧�� ���ӣ����������
     // bySupport7 & 0x80  ��ʾ�豸�Ƿ�֧�� ���ļ���
     BYTE  byRes2;        //����
-}NET_DVR_DEVICEINFO_V30, *LPNET_DVR_DEVICEINFO_V30;
+} NET_DVR_DEVICEINFO_V30,*LPNET_DVR_DEVICEINFO_V30;
 
 typedef struct tagNET_DVR_DEVICEINFO_V40
 {
@@ -13781,7 +13781,7 @@ typedef struct
 }NET_DVR_FIND_DATA, *LPNET_DVR_FIND_DATA;
 
 //¼���ļ�����(9000)
-typedef struct 
+typedef struct NET_DVR_FINDDATA_V30
 {
     char sFileName[100];//���
     NET_DVR_TIME struStartTime;//�ļ��Ŀ�ʼʱ��
@@ -13843,7 +13843,7 @@ typedef struct
 
 
 //¼���ļ����������ṹ
-typedef struct 
+typedef struct NET_DVR_FILECOND
 {
     LONG lChannel;//ͨ����
     DWORD dwFileType;//¼���ļ�����