package Core /* #cgo CFLAGS: -I../include #cgo LDFLAGS: -lHCCore -lhcnetsdk #include #include #include #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 }