From fc62a966dbb38491fb0a3dd8c22acccd86b6ab5c Mon Sep 17 00:00:00 2001 From: kunmeng Date: Fri, 21 Mar 2025 10:06:00 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=A2=9E=E5=8A=A0=20GetDVRDeviceConfig?= =?UTF-8?q?=E5=87=BD=E6=95=B0=202.=20=E5=A2=9E=E5=8A=A0=20NET=5FDVR=5FFind?= =?UTF-8?q?NextFile=5FV30=20=E5=87=BD=E6=95=B0=203.=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20NET=5FDVR=5FFindFile=5FV30=20=E5=87=BD=E6=95=B0=204.=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E6=96=B0=E7=9A=84=20Go=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=A8=A1=E5=9E=8B=205.=20=E8=A7=84=E8=8C=83=E5=8C=96?= =?UTF-8?q?=20Go=20=E6=95=B0=E6=8D=AE=E6=A8=A1=E5=9E=8B=206.=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=83=A8=E5=88=86=E7=9A=84=20C=20=E5=A4=B4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=AD=E7=9A=84=E7=BB=93=E6=9E=84=E4=BD=93,?= =?UTF-8?q?=E4=BB=A5=E4=BF=AE=E5=A4=8D=20CGo=20=E6=97=A0=E6=B3=95=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E5=87=BD=E6=95=B0=E5=8F=82=E6=95=B0=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98(https://stackoverflow.com/questions?= =?UTF-8?q?/59353668/get-the-struct-from-c-to-golang)=207.=20=E7=AE=80?= =?UTF-8?q?=E5=8C=96=E7=90=83=E6=9C=BA=E9=80=80=E5=87=BA=E7=99=BB=E9=99=86?= =?UTF-8?q?=208.=20=E5=AE=9E=E7=8E=B0=20NVR=20=E7=9B=B8=E5=85=B3=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=209.=20=E7=BC=96=E5=86=99=20NVR=20=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BallCamera.go | 15 +- Core/Type.go | 500 ++++++++++++++++++++++++++++++++++++++++++--- Core/core.go | 79 +++---- Nvr.go | 172 ++++++++++++++++ Nvr_test.go | 33 +++ include/HCNetSDK.h | 10 +- 6 files changed, 717 insertions(+), 92 deletions(-) create mode 100644 Nvr.go create mode 100644 Nvr_test.go diff --git a/BallCamera.go b/BallCamera.go index 31bdd81..9d57148 100644 --- a/BallCamera.go +++ b/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) } diff --git a/Core/Type.go b/Core/Type.go index 4243891..ed44526 100644 --- a/Core/Type.go +++ b/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)) } diff --git a/Core/core.go b/Core/core.go index ad110de..49bc32b 100644 --- a/Core/core.go +++ b/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])) +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") } - - // 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 + 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 } diff --git a/Nvr.go b/Nvr.go new file mode 100644 index 0000000..b9eb1f3 --- /dev/null +++ b/Nvr.go @@ -0,0 +1,172 @@ +package HikSDK + +/* +#cgo LDFLAGS: -Wl,--allow-multiple-definition +#include +#include +*/ +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 +} diff --git a/Nvr_test.go b/Nvr_test.go new file mode 100644 index 0000000..2a43712 --- /dev/null +++ b/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) +} diff --git a/include/HCNetSDK.h b/include/HCNetSDK.h index 14d2bf6..5cb4540 100644 --- a/include/HCNetSDK.h +++ b/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;//¼���ļ�����