1. 导出Core包
This commit is contained in:
42
Core/CallBack.go
Normal file
42
Core/CallBack.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package Core
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -I../include
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "HCNetSDK.h"
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func charPtrToByteSlice(cstr *C.char, dwBufSize DWORD) []byte {
|
||||
goSlice := C.GoBytes(unsafe.Pointer(cstr), C.int(dwBufSize))
|
||||
return goSlice
|
||||
}
|
||||
|
||||
var serialCallBackHooks = make(map[LONG]serialDataCallBack)
|
||||
|
||||
type serialDataCallBack func(lSerialHandle LONG, lChannel LONG, pRecvDataBuffer []byte, dwBufSize DWORD, pUser unsafe.Pointer)
|
||||
|
||||
//export fSerialDataCallBackGo
|
||||
func fSerialDataCallBackGo(lSerialHandle C.LONG, lChannel C.LONG, pRecvDataBuffer *C.char, dwBufSize C.DWORD, pUser *C.void) {
|
||||
callback := serialCallBackHooks[LONG(lSerialHandle)]
|
||||
println(DWORD(dwBufSize))
|
||||
if callback != nil {
|
||||
callback(LONG(lSerialHandle), LONG(lChannel), charPtrToByteSlice(pRecvDataBuffer, DWORD(dwBufSize)), DWORD(dwBufSize), unsafe.Pointer(pUser))
|
||||
}
|
||||
}
|
||||
|
||||
var exceptionCallBackHooks = make(map[int]ExceptionCallBack)
|
||||
|
||||
type ExceptionCallBack func(dwType uint32, lUserID int32, lHandle int32, pUser interface{})
|
||||
|
||||
//export fExceptionCallBackGo
|
||||
func fExceptionCallBackGo(dwType C.DWORD, lUserID C.LONG, lHandle C.LONG, pUser *C.void) {
|
||||
callback := exceptionCallBackHooks[int(lUserID)]
|
||||
if callback != nil {
|
||||
callback(uint32(dwType), int32(lUserID), int32(lHandle), pUser)
|
||||
}
|
||||
}
|
||||
46
Core/Type.go
Normal file
46
Core/Type.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package Core
|
||||
|
||||
type DWORD uint32
|
||||
type WORD uint16
|
||||
type USHORT WORD
|
||||
type SHORT int16
|
||||
|
||||
type LONG int32
|
||||
|
||||
type BYTE uint8
|
||||
type UINT uint32
|
||||
|
||||
// type LPVOID void*
|
||||
// type HANDLE void*
|
||||
// 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
|
||||
}
|
||||
252
Core/core.go
Normal file
252
Core/core.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package Core
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -I../include
|
||||
#cgo LDFLAGS: -L${SRCDIR}/../libs/x86_64 -lHCCore -lhcnetsdk -lhpr -lNPQos -lSuperRender
|
||||
#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 C.NET_DVR_DEVICEINFO_V30
|
||||
cUserId := C.NET_DVR_Login_V30(cIp, C.WORD(Port), cUsername, cPassword, &DeviceInfo)
|
||||
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
|
||||
}
|
||||
|
||||
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 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) {
|
||||
//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 {
|
||||
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 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 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
|
||||
}
|
||||
30
Core/error.go
Normal file
30
Core/error.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package Core
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 构造HcnetError
|
||||
func NewHcnetError(Code int, Msg string, FuncName string) *HcnetError {
|
||||
return &HcnetError{Code: Code, Msg: Msg, FuncName: FuncName}
|
||||
}
|
||||
|
||||
// 海康网络sdk自定义错误
|
||||
type HcnetError struct {
|
||||
Code int `json:"Code"` // 错误码
|
||||
Msg string `json:"Msg"` // 错误码描述
|
||||
FuncName string `json:"FuncName"`
|
||||
}
|
||||
|
||||
func (p *HcnetError) Error() string {
|
||||
return strconv.FormatInt(int64(p.Code), 10) + "," + p.Msg
|
||||
}
|
||||
|
||||
func (p *HcnetError) IsPasswordError() bool {
|
||||
return p.Code == 1
|
||||
}
|
||||
|
||||
func (p *HcnetError) IsDeviceOfflineError() bool {
|
||||
return p.Code == 7
|
||||
}
|
||||
Reference in New Issue
Block a user