package HikNetSDK import ( "errors" "fmt" "sync" "unsafe" ) type HIKBallCamera struct { core unsafe.Pointer State bool BallCameraCfg BallCamera mux sync.RWMutex } func NewHIKBallCamera(BallCameraCfg BallCamera) *HIKBallCamera { return &HIKBallCamera{ core: newHIKBallCamera(), BallCameraCfg: BallCameraCfg, State: false, mux: sync.RWMutex{}, } } func (hikBC *HIKBallCamera) Login() (bool, uint, error) { var ErrorCode uint ErrorInfo := make([]byte, 128) ErrorInfoPtr := &ErrorInfo[0] hikBC.mux.Lock() hikBC.State = initBallCamera(hikBC.core, hikBC.BallCameraCfg.Ip, hikBC.BallCameraCfg.Port, hikBC.BallCameraCfg.User, hikBC.BallCameraCfg.Password, hikBC.BallCameraCfg.Type, unsafe.Pointer(&ErrorCode), ErrorInfoPtr) outState := hikBC.State hikBC.mux.Unlock() return outState, ErrorCode, errors.New(goString(ErrorInfoPtr)) } func (hikBC *HIKBallCamera) Logout() (bool, uint, error) { var ErrorCode uint ErrorInfo := make([]byte, 128) ErrorInfoPtr := &ErrorInfo[0] hikBC.mux.Lock() hikBC.State = ballCameraLogout(hikBC.core, unsafe.Pointer(&ErrorCode), ErrorInfoPtr) outState := hikBC.State hikBC.mux.Unlock() return outState, ErrorCode, errors.New(goString(ErrorInfoPtr)) } // goString 将 `char*` 转换为 Go 字符串 func goString(cstr *byte) string { if cstr == nil { return "" } // 找到 C 字符串的长度(以 null 结尾) data := unsafe.Slice(cstr, 128) // 假设最大长度 128,实际可根据情况调整 for i, b := range data { if b == 0 { // 遇到 null 终止符 return string(data[:i]) } } return string(data) // 如果没有 null 终止符,返回整个 slice } func (hikBC *HIKBallCamera) opt(action func() bool) bool { hikBC.mux.RLock() if hikBC.State { hikBC.mux.RUnlock() hikBC.mux.Lock() hikBC.State = action() hikBC.mux.Unlock() } else { hikBC.mux.RUnlock() } return hikBC.State } func (hikBC *HIKBallCamera) PTZGet(P, T, Z *float32) bool { return hikBC.opt(func() bool { return ptzGet(hikBC.core, unsafe.Pointer(P), unsafe.Pointer(T), unsafe.Pointer(Z)) }) } func (hikBC *HIKBallCamera) PtzTo(Action int, P, T, Z float32) bool { return hikBC.opt(func() bool { return ptzTo(hikBC.core, Action, P, T, Z) }) } func (hikBC *HIKBallCamera) StartBus(Direction, Speed int) bool { return hikBC.opt(func() bool { return startBus(hikBC.core, Direction, Speed) }) } func (hikBC *HIKBallCamera) StopBus(Direction int) bool { return hikBC.opt(func() bool { return stopBus(hikBC.core, Direction) }) } func (hikBC *HIKBallCamera) OneClickToSeeInFullView(point Point) bool { TransPoint := hikBC.WarpingPtByHomography(hikBC.BallCameraCfg.Matrix.Matrix, point) return hikBC.PtzTo(5, float32(hikBC.mapping(hikBC.BallCameraCfg.Matrix.PStart, hikBC.BallCameraCfg.Matrix.PMax, TransPoint.X, hikBC.BallCameraCfg.Matrix.PPositiveDirection, "inv")), float32(hikBC.mapping(hikBC.BallCameraCfg.Matrix.TStart, hikBC.BallCameraCfg.Matrix.TMax, TransPoint.Y, hikBC.BallCameraCfg.Matrix.TPositiveDirection, "inv")), 0.0, ) } func (hikBC *HIKBallCamera) PTZ2FullView() (Point, error) { var ptz PTZ if !hikBC.PTZGet(&ptz.P, &ptz.T, &ptz.Z) { return Point{}, fmt.Errorf("PTZ Get Error") } return hikBC.WarpingPtByHomography(hikBC.BallCameraCfg.Matrix.InvMatrix, Point{ X: hikBC.mapping(hikBC.BallCameraCfg.Matrix.PStart, hikBC.BallCameraCfg.Matrix.PMax, float64(ptz.P), hikBC.BallCameraCfg.Matrix.PPositiveDirection, ""), Y: hikBC.mapping(hikBC.BallCameraCfg.Matrix.TStart, hikBC.BallCameraCfg.Matrix.TMax, float64(ptz.T), hikBC.BallCameraCfg.Matrix.TPositiveDirection, "")}), nil } func (hikBC *HIKBallCamera) WarpingPtByHomography(matrix []float64, p Point) Point { var x, y, z float64 x = matrix[0]*p.X + matrix[1]*p.Y + 1.*matrix[2] y = matrix[3]*p.X + matrix[4]*p.Y + 1.*matrix[5] z = matrix[6]*p.X + matrix[7]*p.Y + 1.*matrix[8] x /= z y /= z return Point{X: x, Y: y} } func (hikBC *HIKBallCamera) mapping(startV float64, max float64, value float64, direction string, method string) float64 { if direction == "+" { if method == "inv" { if value > (max - startV) { return value - (max - startV) } else { return startV + value // 映射 } } else { if value > startV { return value - startV } else { return (max - startV) + value // 映射 } } } else { if value > startV { return startV + max - value } else { return startV - value } } }