Files
HikNetSDKPkg/Core/core.go
kunmeng fc62a966db 1. 增加 GetDVRDeviceConfig函数
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 接口测试用例
2025-03-21 10:06:00 +08:00

238 lines
7.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}