 fc62a966db
			
		
	
	fc62a966db
	
	
	
		
			
			2. 增加 NET_DVR_FindNextFile_V30 函数 3. 增加 NET_DVR_FindFile_V30 函数 4. 增加 新的 Go 数据模型 5. 规范化 Go 数据模型 6. 调整部分的 C 头文件中的结构体,以修复 CGo 无法识别函数参数类型的问题(https://stackoverflow.com/questions/59353668/get-the-struct-from-c-to-golang) 7. 简化球机退出登陆 8. 实现 NVR 相关接口 9. 编写 NVR 接口测试用例
		
			
				
	
	
		
			238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package Core
 | ||
| 
 | ||
| /*
 | ||
| #cgo CFLAGS: -I../include
 | ||
| #cgo LDFLAGS: -lHCCore -lhcnetsdk
 | ||
| #include <stdio.h>
 | ||
| #include <stdlib.h>
 | ||
| #include <stddef.h>
 | ||
| #include "HCNetSDK.h"
 | ||
| 
 | ||
| extern void fSerialDataCallBackGo(LONG lSerialHandle,LONG lChannel,char *pRecvDataBuffer,DWORD dwBufSize,void *pUser);
 | ||
| void FSerialDataCallBackCGo(LONG lSerialHandle,LONG lChannel,char *pRecvDataBuffer,DWORD dwBufSize,void *pUser){
 | ||
|     fSerialDataCallBackGo(lSerialHandle, lChannel, pRecvDataBuffer, dwBufSize,pUser);
 | ||
| };
 | ||
| 
 | ||
| // 异常回调函数
 | ||
| extern void fExceptionCallBackGo(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser);
 | ||
| void FExceptionCallBackCgo(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
 | ||
| {
 | ||
|     fExceptionCallBackGo(dwType, lUserID, lHandle, pUser);
 | ||
| }
 | ||
| */
 | ||
| import "C"
 | ||
| import (
 | ||
| 	"math"
 | ||
| 	"unsafe"
 | ||
| )
 | ||
| 
 | ||
| // Init 初始化SDK,调用其他SDK函数的前提。
 | ||
| func Init() error {
 | ||
| 	if C.NET_DVR_Init() != 1 {
 | ||
| 		return LastError("NET_DVR_Init")
 | ||
| 	}
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // Cleanup 释放SDK资源,在程序结束之前调用。在调用时不能同时调用其他任何SDK接口。 Init 和 Cleanup 需要配对使用,即程序里面调用多少次 Init ,退出时就需要调用多少次 Cleanup。
 | ||
| func Cleanup() error {
 | ||
| 	if C.NET_DVR_Cleanup() != 1 {
 | ||
| 		return LastError("NET_DVR_Cleanup")
 | ||
| 	}
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| func Login(Ip string, Port int, Username string, Password string) (LONG, NET_DVR_DEVICEINFO_V30, error) {
 | ||
| 	cIp := C.CString(Ip)
 | ||
| 	defer C.free(unsafe.Pointer(cIp))
 | ||
| 	cUsername := C.CString(Username)
 | ||
| 	defer C.free(unsafe.Pointer(cUsername))
 | ||
| 	cPassword := C.CString(Password)
 | ||
| 	defer C.free(unsafe.Pointer(cPassword))
 | ||
| 	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")
 | ||
| 	}
 | ||
| 	DeviceInfo.Go()
 | ||
| 	return LONG(cUserId), DeviceInfo, nil
 | ||
| }
 | ||
| 
 | ||
| func Logout(userId LONG) error {
 | ||
| 	if userId > -1 {
 | ||
| 		cResult := C.NET_DVR_Logout(C.LONG(userId))
 | ||
| 		if cResult != 1 {
 | ||
| 			return LastError("NET_DVR_Logout")
 | ||
| 		}
 | ||
| 	}
 | ||
| 	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{}
 | ||
| 	SerialStartParam.dwSize = C.DWORD(unsafe.Sizeof(SerialStartParam))
 | ||
| 	SerialStartParam.dwSerialType = C.DWORD(2) //1:232串口;2:485串口
 | ||
| 	SerialStartParam.bySerialNum = C.BYTE(1)   //串口编号(设备支持多个RS232串口时有效)
 | ||
| 	// 填充 byRes 字段
 | ||
| 	for i := 0; i < 255; i++ {
 | ||
| 		SerialStartParam.byRes[i] = C.BYTE(0) // 示例值,逐个赋值
 | ||
| 	}
 | ||
| 	SerialStartHandle := C.NET_DVR_SerialStart_V40(C.LONG(UserId), unsafe.Pointer(&SerialStartParam), C.LONG(unsafe.Sizeof(SerialStartParam)), C.fSerialDataCallBack(C.FSerialDataCallBackCGo), nil)
 | ||
| 	if LONG(SerialStartHandle) == -1 {
 | ||
| 		return -1, LastError("NET_DVR_SerialStart_V40")
 | ||
| 	}
 | ||
| 	serialCallBackHooks[LONG(SerialStartHandle)] = CallBack
 | ||
| 	return LONG(SerialStartHandle), nil
 | ||
| }
 | ||
| 
 | ||
| func SerialSend(lSerialHandle LONG, hexbyte []byte) error {
 | ||
| 	if C.NET_DVR_SerialSend(C.LONG(lSerialHandle), 1, (*C.char)(unsafe.Pointer(&hexbyte[0])), C.DWORD(len(hexbyte))) == C.FALSE {
 | ||
| 		return LastError("NET_DVR_SerialSend")
 | ||
| 	}
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| func SerialStop(lSerialHandle LONG) error {
 | ||
| 	if int(C.NET_DVR_SerialStop(C.LONG(lSerialHandle))) != 1 {
 | ||
| 		return LastError("SerialStop")
 | ||
| 	}
 | ||
| 	delete(serialCallBackHooks, lSerialHandle)
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| type CDVR_PTZPOS C.NET_DVR_PTZPOS
 | ||
| 
 | ||
| func (d *CDVR_PTZPOS) Go() DVR_PTZPOS {
 | ||
| 	return DVR_PTZPOS{
 | ||
| 		WAction:  1,
 | ||
| 		WPanPos:  HEX2DEC(WORD(d.wPanPos)),
 | ||
| 		WTiltPos: HEX2DEC(WORD(d.wTiltPos)),
 | ||
| 		WZoomPos: HEX2DEC(WORD(d.wZoomPos)),
 | ||
| 	}
 | ||
| }
 | ||
| func (d *CDVR_PTZPOS) Set(Action, PanPos, TiltPos, ZoomPos float64) {
 | ||
| 	d.wAction = C.WORD(Action)
 | ||
| 	d.wPanPos = C.WORD(DEC2HEX(PanPos))
 | ||
| 	d.wTiltPos = C.WORD(DEC2HEX(TiltPos))
 | ||
| 	d.wZoomPos = C.WORD(DEC2HEX(ZoomPos))
 | ||
| }
 | ||
| 
 | ||
| type DVR_PTZPOS struct {
 | ||
| 	WAction  int
 | ||
| 	WPanPos  float64
 | ||
| 	WTiltPos float64
 | ||
| 	WZoomPos float64
 | ||
| }
 | ||
| 
 | ||
| // DEC2HEX 将十进制浮点数转换为十六进制整数
 | ||
| func DEC2HEX(dec float64) WORD {
 | ||
| 	// 提取千位(对应十进制的百位)
 | ||
| 	bai := uint16(dec / math.Pow(10, 2))
 | ||
| 	dec -= float64(bai) * math.Pow(10, 2)
 | ||
| 
 | ||
| 	// 提取百位(对应十进制的十位)
 | ||
| 	shi := uint16(dec / math.Pow(10, 1))
 | ||
| 	dec -= float64(shi) * math.Pow(10, 1)
 | ||
| 
 | ||
| 	// 提取十位(对应十进制的个位)
 | ||
| 	ge := uint16(dec / math.Pow(10, 0))
 | ||
| 	dec -= float64(ge) * math.Pow(10, 0)
 | ||
| 
 | ||
| 	// 提取个位(对应十进制的十分位)
 | ||
| 	xiao := uint16(dec * 10)
 | ||
| 
 | ||
| 	// 合成十六进制数
 | ||
| 	hex := WORD(bai)<<12 | WORD(shi)<<8 | WORD(ge)<<4 | WORD(xiao)
 | ||
| 	return hex
 | ||
| }
 | ||
| 
 | ||
| // HEX2DEC 将十六进制整数转换为十进制浮点数
 | ||
| func HEX2DEC(hex WORD) float64 {
 | ||
| 	// 提取十六进制数的千位(对应十进制的百位)
 | ||
| 	bai := byte(hex >> 12)
 | ||
| 	hex = hex - WORD(bai)*WORD(math.Pow(16, 3))
 | ||
| 	// 提取十六进制数的百位(对应十进制的十位)
 | ||
| 	shi := byte(hex >> 8)
 | ||
| 	hex = hex - WORD(shi)*WORD(math.Pow(16, 2))
 | ||
| 	// 提取十六进制数的十位(对应十进制的个位)
 | ||
| 	ge := byte(hex >> 4)
 | ||
| 	hex = hex - WORD(ge)*WORD(math.Pow(16, 1))
 | ||
| 	// 提取十六进制数的个位(对应十进制的十分位)
 | ||
| 	xiao := byte(hex)
 | ||
| 
 | ||
| 	// 计算对应的十进制浮点数
 | ||
| 	return float64(bai)*math.Pow(10, 2) + float64(shi)*math.Pow(10, 1) + float64(ge)*math.Pow(10, 0) + float64(xiao)*math.Pow(10, -1)
 | ||
| }
 | ||
| 
 | ||
| func GetDVRConfig(lUserID LONG, dwCommand DWORD, lChannel LONG, lpOutBuffer unsafe.Pointer, dwOutBufferSize DWORD) error {
 | ||
| 	bytesReturned := C.DWORD(0)
 | ||
| 	cResult := C.NET_DVR_GetDVRConfig(C.LONG(lUserID), C.DWORD(dwCommand), C.LONG(lChannel), C.LPVOID(lpOutBuffer), C.DWORD(dwOutBufferSize), &bytesReturned)
 | ||
| 	if cResult != 1 {
 | ||
| 		return LastError("NET_DVR_GetDVRConfig")
 | ||
| 	}
 | ||
| 	return nil
 | ||
| }
 | ||
| func SetDVRConfig(lUserID LONG, dwCommand DWORD, lChannel LONG, lpInBuffer unsafe.Pointer, dwOutBufferSize DWORD) error {
 | ||
| 	cResult := C.NET_DVR_SetDVRConfig(C.LONG(lUserID), C.DWORD(dwCommand), C.LONG(lChannel), C.LPVOID(lpInBuffer), C.DWORD(dwOutBufferSize))
 | ||
| 	if cResult != 1 {
 | ||
| 		return LastError("NET_DVR_SetDVRConfig")
 | ||
| 	}
 | ||
| 	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 {
 | ||
| 		return nil
 | ||
| 	}
 | ||
| 
 | ||
| 	var text string
 | ||
| 	if cCode == 3 {
 | ||
| 		text = "sdk not init."
 | ||
| 	} else {
 | ||
| 		cCode2 := C.LONG(cCode)
 | ||
| 		cText := C.NET_DVR_GetErrorMsg(&cCode2)
 | ||
| 		text = C.GoString(cText)
 | ||
| 	}
 | ||
| 	return NewHcnetError(int(cCode), text, funcName)
 | ||
| }
 | ||
| 
 | ||
| func PTZControlWithSpeed_Other(lUserID LONG, lChannel LONG, dwPTZCommand DWORD, dwStop DWORD, dwSpeed DWORD) error {
 | ||
| 	state := C.NET_DVR_PTZControlWithSpeed_Other(C.LONG(lUserID), C.LONG(lChannel), C.DWORD(dwPTZCommand), C.DWORD(dwStop), C.DWORD(dwSpeed))
 | ||
| 	if state == C.FALSE {
 | ||
| 		return LastError("NET_DVR_PTZControlWithSpeed_Other")
 | ||
| 	}
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| 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
 | ||
| }
 |