123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- package HikSDK
- /*
- #cgo LDFLAGS: -Wl,--allow-multiple-definition
- #include <stdio.h>
- #include <string.h>
- */
- import "C"
- import (
- "encoding/binary"
- "errors"
- "fmt"
- "gitea.com/kunmeng/HikNetSDKPkg/Core"
- "sync"
- "time"
- "unsafe"
- )
- const (
- Base = 0
- BuKongQiu = 1
- )
- type PTZEnumObj struct {
- PTZ_LEFT int
- PTZ_RIGHT int
- PTZ_UP int
- PTZ_DOWN int
- PTZ_UP_LEFT int
- PTZ_UP_RIGHT int
- PTZ_DOWN_LEFT int
- PTZ_DOWN_RIGHT int
- PTZ_ZOOM_IN int
- PTZ_ZOOM_OUT int
- PTZ_Focus_Far int
- PTZ_Focus_Near int
- }
- func (receiver *PTZEnumObj) toHikPTZEnum(v int) int {
- switch v {
- case PTZEnum.PTZ_LEFT:
- return HikPTZEnum.PAN_LEFT
- case PTZEnum.PTZ_RIGHT:
- return HikPTZEnum.PAN_RIGHT
- case PTZEnum.PTZ_UP:
- return HikPTZEnum.TILT_UP
- case PTZEnum.PTZ_DOWN:
- return HikPTZEnum.TILT_DOWN
- case PTZEnum.PTZ_ZOOM_IN:
- return HikPTZEnum.ZOOM_IN
- case PTZEnum.PTZ_ZOOM_OUT:
- return HikPTZEnum.ZOOM_OUT
- case PTZEnum.PTZ_Focus_Far:
- return HikPTZEnum.FOCUS_FAR
- case PTZEnum.PTZ_Focus_Near:
- return HikPTZEnum.FOCUS_NEAR
- case PTZEnum.PTZ_UP_LEFT:
- return HikPTZEnum.UP_LEFT
- case PTZEnum.PTZ_UP_RIGHT:
- return HikPTZEnum.UP_RIGHT
- case PTZEnum.PTZ_DOWN_LEFT:
- return HikPTZEnum.DOWN_LEFT
- case PTZEnum.PTZ_DOWN_RIGHT:
- return HikPTZEnum.DOWN_RIGHT
- default:
- return -1
- }
- }
- var PTZEnum = PTZEnumObj{
- PTZ_LEFT: 1,
- PTZ_RIGHT: 2,
- PTZ_UP: 3,
- PTZ_DOWN: 4,
- PTZ_UP_LEFT: 5,
- PTZ_UP_RIGHT: 6,
- PTZ_DOWN_LEFT: 7,
- PTZ_DOWN_RIGHT: 8,
- PTZ_ZOOM_IN: 9,
- PTZ_ZOOM_OUT: 10,
- PTZ_Focus_Far: 11,
- PTZ_Focus_Near: 12,
- }
- var HikPTZEnum = struct {
- LIGHT_PWRON int //接通灯光电源
- WIPER_PWRON int //接通雨刷开关
- FAN_PWRON int //接通风扇开关
- HEATER_PWRON int //接通加热器开关
- AUX_PWRON1 int //接通辅助设备开关
- AUX_PWRON2 int //接通辅助设备开关
- ZOOM_IN int //焦距变大(倍率变大)
- ZOOM_OUT int //焦距变小(倍率变小)
- FOCUS_NEAR int //焦点前调
- FOCUS_FAR int //焦点后调
- IRIS_OPEN int //光圈扩大
- IRIS_CLOSE int //光圈缩小
- TILT_UP int //云台上仰
- TILT_DOWN int //云台下俯
- PAN_LEFT int //云台左转
- PAN_RIGHT int //云台右转
- UP_LEFT int //云台上仰和左转
- UP_RIGHT int //云台上仰和右转
- DOWN_LEFT int //云台下俯和左转
- DOWN_RIGHT int //云台下俯和右转
- PAN_AUTO int //云台左右自动扫描
- TILT_DOWN_ZOOM_IN int //云台下俯和焦距变大(倍率变大)
- TILT_DOWN_ZOOM_OUT int //云台下俯和焦距变小(倍率变小)
- PAN_LEFT_ZOOM_IN int //云台左转和焦距变大(倍率变大)
- PAN_LEFT_ZOOM_OUT int //云台左转和焦距变小(倍率变小)
- PAN_RIGHT_ZOOM_IN int //云台右转和焦距变大(倍率变大)
- PAN_RIGHT_ZOOM_OUT int //云台右转和焦距变小(倍率变小)
- UP_LEFT_ZOOM_IN int //云台上仰和左转和焦距变大(倍率变大)
- UP_LEFT_ZOOM_OUT int //云台上仰和左转和焦距变小(倍率变小)
- UP_RIGHT_ZOOM_IN int //云台上仰和右转和焦距变大(倍率变大)
- UP_RIGHT_ZOOM_OUT int //云台上仰和右转和焦距变小(倍率变小)
- DOWN_LEFT_ZOOM_IN int //云台下俯和左转和焦距变大(倍率变大)
- DOWN_LEFT_ZOOM_OUT int //云台下俯和左转和焦距变小(倍率变小)
- DOWN_RIGHT_ZOOM_IN int //云台下俯和右转和焦距变大(倍率变大)
- DOWN_RIGHT_ZOOM_OUT int //云台下俯和右转和焦距变小(倍率变小)
- TILT_UP_ZOOM_IN int //云台上仰和焦距变大(倍率变大)
- TILT_UP_ZOOM_OUT int //云台上仰和焦距变小(倍率变小)
- }{LIGHT_PWRON: 2,
- WIPER_PWRON: 3,
- FAN_PWRON: 4,
- HEATER_PWRON: 5,
- AUX_PWRON1: 6,
- AUX_PWRON2: 7,
- ZOOM_IN: 11,
- ZOOM_OUT: 12,
- FOCUS_NEAR: 13,
- FOCUS_FAR: 14,
- IRIS_OPEN: 15,
- IRIS_CLOSE: 16,
- TILT_UP: 21,
- TILT_DOWN: 22,
- PAN_LEFT: 23,
- PAN_RIGHT: 24,
- UP_LEFT: 25,
- UP_RIGHT: 26,
- DOWN_LEFT: 27,
- DOWN_RIGHT: 28,
- PAN_AUTO: 29,
- TILT_DOWN_ZOOM_IN: 58,
- TILT_DOWN_ZOOM_OUT: 59,
- PAN_LEFT_ZOOM_IN: 60,
- PAN_LEFT_ZOOM_OUT: 61,
- PAN_RIGHT_ZOOM_IN: 62,
- PAN_RIGHT_ZOOM_OUT: 63,
- UP_LEFT_ZOOM_IN: 64,
- UP_LEFT_ZOOM_OUT: 65,
- UP_RIGHT_ZOOM_IN: 66,
- UP_RIGHT_ZOOM_OUT: 67,
- DOWN_LEFT_ZOOM_IN: 68,
- DOWN_LEFT_ZOOM_OUT: 69,
- DOWN_RIGHT_ZOOM_IN: 70,
- DOWN_RIGHT_ZOOM_OUT: 71,
- TILT_UP_ZOOM_IN: 72,
- TILT_UP_ZOOM_OUT: 73,
- }
- type BallCamera struct {
- userId Core.LONG
- _type uint8
- deviceInfo Core.NET_DVR_DEVICEINFO_V30
- mu sync.Mutex
- expectedType byte
- }
- func NewBallCamera(Ip string, Port int, Username, Password string, Type uint8) (*BallCamera, error) {
- UserId, DeviceInfo, err := Core.Login(Ip, Port, Username, Password)
- if err != nil {
- return nil, err
- }
- return &BallCamera{
- userId: UserId,
- _type: Type,
- deviceInfo: DeviceInfo,
- }, nil
- }
- type PTZ struct {
- P float32
- T float32
- Z float32
- }
- func (this *BallCamera) GetPTZ() (PTZ, error) {
- if this._type == BuKongQiu {
- var data PTZ
- ch := make(chan bool)
- SerialStartHandle, err := Core.SerialStart(this.userId, func(lSerialHandle Core.LONG, lChannel Core.LONG, pRecvDataBuffer []byte, dwBufSize Core.DWORD, pUser unsafe.Pointer) {
- if dwBufSize != 7 {
- ch <- false
- return
- }
- Type := pRecvDataBuffer[3]
- this.mu.Lock()
- expected := this.expectedType
- this.mu.Unlock()
- if Type != expected {
- ch <- false
- return
- }
- switch Type {
- case 0x59:
- data.P = float32(binary.BigEndian.Uint16(pRecvDataBuffer[4:6])) / 100.
- case 0x5B:
- data.T = float32(binary.BigEndian.Uint16(pRecvDataBuffer[4:6])) / 100.
- case 0x5D:
- data.Z = float32(binary.BigEndian.Uint16(pRecvDataBuffer[4:6])) / 100.
- default:
- ch <- false
- }
- ch <- true
- })
- if err != nil {
- return data, err
- }
- defer func() {
- err = Core.SerialStop(SerialStartHandle)
- if err != nil {
- println(err.Error())
- }
- time.Sleep(1 * time.Second)
- }()
- // 获取P值
- this.mu.Lock()
- this.expectedType = 0x59
- this.mu.Unlock()
- if err := this.retrySend(SerialStartHandle, []byte{0xff, 0x01, 0x00, 0x51, 0x00, 0x00, 0x52}, 5, ch); err != nil {
- return data, fmt.Errorf("获取P值失败: %w", err)
- }
- this.mu.Lock()
- this.expectedType = 0x5B
- this.mu.Unlock()
- if err := this.retrySend(SerialStartHandle, []byte{0xff, 0x01, 0x00, 0x53, 0x00, 0x00, 0x54}, 5, ch); err != nil {
- return data, fmt.Errorf("获取T值失败: %w", err)
- }
- this.mu.Lock()
- this.expectedType = 0x5D
- this.mu.Unlock()
- if err := this.retrySend(SerialStartHandle, []byte{0xff, 0x01, 0x00, 0x55, 0x00, 0x00, 0x56}, 5, ch); err != nil {
- return data, fmt.Errorf("获取Z值失败: %w", err)
- }
- return data, nil
- }
- var data Core.CDVR_PTZPOS
- var dataPtr = unsafe.Pointer(&data)
- err := Core.GetDVRConfig(this.userId, 293, 1, dataPtr, Core.DWORD(unsafe.Sizeof(data)))
- if err != nil {
- return PTZ{}, err
- }
- res := data.Go()
- return PTZ{
- P: float32(res.WPanPos),
- T: float32(res.WTiltPos),
- Z: float32(res.WZoomPos),
- }, nil
- }
- func padding(n int) ([]byte, error) {
- if n < 0 || n > 65535 {
- return []byte{0x00, 0x00}, errors.New("n must be in the range 0-65535")
- }
- return []byte{byte(n >> 8), byte(n & 0xFF)}, nil
- }
- func (this *BallCamera) PtzGotoPut(Action int, P, T, Z float64) error {
- if this._type == BuKongQiu {
- SerialStartHandle, err := Core.SerialStart(this.userId, func(lSerialHandle Core.LONG, lChannel Core.LONG, pRecvDataBuffer []byte, dwBufSize Core.DWORD, pUser unsafe.Pointer) {
- })
- if err != nil {
- return err
- }
- defer func() {
- err = Core.SerialStop(SerialStartHandle)
- if err != nil {
- println(err.Error())
- }
- time.Sleep(1 * time.Second)
- }()
- PByte, err := padding(int(P * 100))
- if err != nil {
- return err
- }
- TByte, err := padding(int(T * 100))
- if err != nil {
- return err
- }
- ZByte, err := padding(int(Z * 100))
- if err != nil {
- return err
- }
- pBuf := append([]byte{0xff, 0x01, 0x00, 0x4b}, PByte...)
- tBuf := append([]byte{0xff, 0x01, 0x00, 0x4d}, TByte...)
- zBuf := append([]byte{0xff, 0x01, 0x00, 0x4f}, ZByte...)
- pBufv, err := verify(pBuf)
- if err != nil {
- return err
- }
- tBufv, err := verify(tBuf)
- if err != nil {
- return err
- }
- zBufv, err := verify(zBuf)
- if err != nil {
- return err
- }
- pBuf = append(pBuf, pBufv)
- tBuf = append(tBuf, tBufv)
- zBuf = append(zBuf, zBufv)
- switch Action {
- case 1:
- err = Core.SerialSend(SerialStartHandle, pBuf)
- if err != nil {
- return err
- }
- err = Core.SerialSend(SerialStartHandle, tBuf)
- if err != nil {
- return err
- }
- err = Core.SerialSend(SerialStartHandle, zBuf)
- if err != nil {
- return err
- }
- break
- case 2:
- err = Core.SerialSend(SerialStartHandle, pBuf)
- if err != nil {
- return err
- }
- break
- case 3:
- err = Core.SerialSend(SerialStartHandle, tBuf)
- if err != nil {
- return err
- }
- break
- case 4:
- err = Core.SerialSend(SerialStartHandle, zBuf)
- if err != nil {
- return err
- }
- break
- case 5:
- err = Core.SerialSend(SerialStartHandle, pBuf)
- if err != nil {
- return err
- }
- err = Core.SerialSend(SerialStartHandle, tBuf)
- if err != nil {
- return err
- }
- break
- default:
- return errors.New("action error")
- }
- return nil
- }
- var data Core.CDVR_PTZPOS
- data.Set(float64(Action), P, T, Z)
- var dataPtr = unsafe.Pointer(&data)
- err := Core.SetDVRConfig(this.userId, 292, 1, dataPtr, Core.DWORD(unsafe.Sizeof(data)))
- if err != nil {
- return err
- }
- return nil
- }
- func (this *BallCamera) retrySend(handle Core.LONG, cmd []byte, maxRetries int, ch <-chan bool) error {
- for retry := 0; retry < maxRetries; retry++ {
- if err := Core.SerialSend(handle, cmd); err != nil {
- return err
- }
- select {
- case success := <-ch:
- if success {
- return nil
- }
- if retry == maxRetries-1 {
- return fmt.Errorf("达到最大重试次数 %d", maxRetries)
- }
- case <-time.After(2 * time.Second): // 添加超时机制
- if retry == maxRetries-1 {
- return fmt.Errorf("响应超时,重试 %d 次后失败", maxRetries)
- }
- }
- }
- return nil
- }
- func (receiver *BallCamera) StartBus(direction int, speed int) error {
- err := Core.PTZControlWithSpeed_Other(receiver.userId, Core.LONG(receiver.deviceInfo.ByStartChan), Core.DWORD(PTZEnum.toHikPTZEnum(direction)), Core.DWORD(0), Core.DWORD(speed))
- if err != nil {
- return err
- }
- return nil
- }
- func (receiver *BallCamera) StopBus(direction int, speed int) error {
- err := Core.PTZControlWithSpeed_Other(receiver.userId, Core.LONG(receiver.deviceInfo.ByStartChan), Core.DWORD(PTZEnum.toHikPTZEnum(direction)), Core.DWORD(1), Core.DWORD(speed))
- if err != nil {
- return err
- }
- return nil
- }
- func verify(data []byte) (byte, error) {
- if len(data) < 6 {
- return 0, fmt.Errorf("data too short")
- }
- sum := 0
- for i := 1; i < 6; i++ {
- sum += int(data[i])
- }
- // 取模并转换为16进制
- checksum := sum % 0x100
- return byte(checksum), nil
- }
- func (this *BallCamera) Logout() error {
- return Core.Logout(this.userId)
- }
- func (this *BallCamera) Status() bool {
- return Core.NET_DVR_RemoteControl(this.userId)
- }
|