Quellcode durchsuchen

1. 添加 球机的一点即视 和 逆运算接口
2. 添加 Nvr 和 球机 的配置结构体 和一些基本结构体类型
3. 修改 Nvr 和 球机 的 Login 方法
4. 修复 球机部分 MOVE 操作无法停止
5. 修复 HikBase Login 返回值错误

王帅锟 vor 6 Monaten
Ursprung
Commit
bd6cff81ec
6 geänderte Dateien mit 615 neuen und 450 gelöschten Zeilen
  1. 13 11
      .gitignore
  2. 14 14
      CMakeLists.txt
  3. 104 12
      Hikvision.go
  4. 72 0
      Type.go
  5. 377 377
      src/HIKBallCamera.cpp
  6. 35 36
      src/HIKBase.cpp

+ 13 - 11
.gitignore

@@ -1,12 +1,14 @@
-/.idea
-/cmake-build-debug-visual-studio
-/cmake-build-release-visual-studio
-*.lib
-*.dll
-*.so
-*.a
-*.zip
-/build
-/arm64_linux_lib
-/arm64_windows_lib
+/.idea
+/.cache
+/.fleet
+/cmake-build-debug-visual-studio
+/cmake-build-release-visual-studio
+*.lib
+*.dll
+*.so
+*.a
+*.zip
+/build
+/arm64_linux_lib
+/arm64_windows_lib
 /amd64_linux_lib

+ 14 - 14
CMakeLists.txt

@@ -44,21 +44,21 @@ if(OS STREQUAL "Windows")
     target_link_libraries(HikNetSDKPkg PRIVATE "HCNetSDK.lib")
     target_link_libraries(HikNetSDKPkg PRIVATE "HCCore.lib")
     target_link_libraries(HikNetSDKPkg PRIVATE "GdiPlus.lib")
-elseif (Arch STREQUAL "x86_64")
+elseif (Arch STREQUAL "x86_64" OR Arch STREQUAL "amd64")
     target_link_directories(HikNetSDKPkg PRIVATE "./amd64_linux_lib")
-    target_link_libraries(HikNetSDKPkg "libHCCore.so")
-    target_link_libraries(HikNetSDKPkg "libhcnetsdk.so")
-    target_link_libraries(HikNetSDKPkg "libhpr.so")
-    target_link_libraries(HikNetSDKPkg "libz.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libHCCore.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libhcnetsdk.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libhpr.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libz.so")
 elseif (Arch STREQUAL "aarch64")
     target_link_directories(HikNetSDKPkg PRIVATE "./arm64_linux_lib")
-    target_link_libraries(HikNetSDKPkg "libAudioRender.so")
-    target_link_libraries(HikNetSDKPkg "libcrypto.so")
-    target_link_libraries(HikNetSDKPkg "libHCCore.so")
-    target_link_libraries(HikNetSDKPkg "libhcnetsdk.so")
-    target_link_libraries(HikNetSDKPkg "libhpr.so")
-    target_link_libraries(HikNetSDKPkg "libPlayCtrl.so")
-    target_link_libraries(HikNetSDKPkg "libssl.so")
-    target_link_libraries(HikNetSDKPkg "libSuperRender.so")
-    target_link_libraries(HikNetSDKPkg "libz.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libAudioRender.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libcrypto.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libHCCore.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libhcnetsdk.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libhpr.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libPlayCtrl.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libssl.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libSuperRender.so")
+    target_link_libraries(HikNetSDKPkg PRIVATE "libz.so")
 endif ()

+ 104 - 12
Hikvision.go

@@ -51,9 +51,9 @@ func init() {
 func getSystemLibrary() string {
 	switch runtime.GOOS {
 	case "linux":
-		if runtime.GOARCH == "amd64" || runtime.GOARCH == "386"{
+		if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
 			return "libHikNetSDKPkg_linux_amd64.so"
-		}else{
+		} else {
 			return " libHikNetSDKPkg_linux_arm64.so"
 		}
 	case "windows":
@@ -64,17 +64,19 @@ func getSystemLibrary() string {
 }
 
 type HIKBallCamera struct {
-	core unsafe.Pointer
+	core          unsafe.Pointer
+	BallCameraCfg BallCamera
 }
 
-func NewHIKBallCamera() *HIKBallCamera {
+func NewHIKBallCamera(BallCameraCfg BallCamera) *HIKBallCamera {
 	return &HIKBallCamera{
-		core: newHIKBallCamera(),
+		core:          newHIKBallCamera(),
+		BallCameraCfg: BallCameraCfg,
 	}
 }
 
-func (h *HIKBallCamera) Login(ip string, port string, username string, password string, BallMachineType string) bool {
-	return initBallCamera(h.core, ip, port, username, password, BallMachineType)
+func (h *HIKBallCamera) Login() bool {
+	return initBallCamera(h.core, h.BallCameraCfg.Ip, h.BallCameraCfg.Port, h.BallCameraCfg.User, h.BallCameraCfg.Password, h.BallCameraCfg.Type)
 }
 func (h *HIKBallCamera) PtzTo(Action int, P, T, Z float32) bool {
 	return ptzTo(h.core, Action, P, T, Z)
@@ -90,17 +92,19 @@ func (h *HIKBallCamera) StartBus(Direction, Speed int) bool {
 }
 
 type HIKNvr struct {
-	core unsafe.Pointer
+	core      unsafe.Pointer
+	NvrConfig Nvr
 }
 
-func NewHIKNvr() *HIKNvr {
+func NewHIKNvr(nvrConfig Nvr) *HIKNvr {
 	return &HIKNvr{
-		core: newHIKNvr(),
+		core:      newHIKNvr(),
+		NvrConfig: nvrConfig,
 	}
 }
 
-func (h *HIKNvr) Login(ip string, port string, username string, password string, nvrType int) bool {
-	return initNvr(h.core, ip, port, username, password, nvrType)
+func (h *HIKNvr) Login() bool {
+	return initNvr(h.core, h.NvrConfig.Ip, h.NvrConfig.Port, h.NvrConfig.User, h.NvrConfig.Password, h.NvrConfig.Channel)
 }
 
 func (h *HIKNvr) CheckTimeRegionWithMonth(year int, month int) string {
@@ -109,3 +113,91 @@ func (h *HIKNvr) CheckTimeRegionWithMonth(year int, month int) string {
 func (h *HIKNvr) CheckTimeRegionWithDay(year int, month int, day int) string {
 	return checkTimeRegionWithDay(h.core, year, month, day)
 }
+
+func (h *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 (h *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
+		}
+	}
+}
+
+func (h *HIKBallCamera) OneClickToSeeInFullView(point Point) bool {
+	TransPoint := h.WarpingPtByHomography(h.BallCameraCfg.Matrix.Matrix, point)
+	return h.PtzTo(5,
+		float32(h.mapping(h.BallCameraCfg.Matrix.PStart, h.BallCameraCfg.Matrix.PMax, TransPoint.X, h.BallCameraCfg.Matrix.PPositiveDirection, "inv")),
+		float32(h.mapping(h.BallCameraCfg.Matrix.TStart, h.BallCameraCfg.Matrix.TMax, TransPoint.Y, h.BallCameraCfg.Matrix.TPositiveDirection, "inv")),
+		0.0,
+	)
+}
+
+func (h *HIKBallCamera) PTZ2FullView() (Point, error) {
+	var ptz PTZ
+	if !h.PTZGet(&ptz.P, &ptz.T, &ptz.Z) {
+		return Point{}, fmt.Errorf("PTZ Get Error")
+	}
+	h.WarpingPtByHomography(h.BallCameraCfg.Matrix.InvMatrix, Point{
+		X: h.mapping(h.BallCameraCfg.Matrix.PStart, h.BallCameraCfg.Matrix.PMax, float64(ptz.P), h.BallCameraCfg.Matrix.PPositiveDirection, ""),
+		Y: h.mapping(h.BallCameraCfg.Matrix.TStart, h.BallCameraCfg.Matrix.TMax, float64(ptz.T), h.BallCameraCfg.Matrix.TPositiveDirection, "")})
+	return Point{}, nil
+}
+
+func (hikBC *HIKBallCamera) invert3x3() bool {
+
+	a := hikBC.BallCameraCfg.Matrix.Matrix[0]
+	b := hikBC.BallCameraCfg.Matrix.Matrix[1]
+	c := hikBC.BallCameraCfg.Matrix.Matrix[2]
+	d := hikBC.BallCameraCfg.Matrix.Matrix[3]
+	e := hikBC.BallCameraCfg.Matrix.Matrix[4]
+	f := hikBC.BallCameraCfg.Matrix.Matrix[5]
+	g := hikBC.BallCameraCfg.Matrix.Matrix[6]
+	h := hikBC.BallCameraCfg.Matrix.Matrix[7]
+	i := hikBC.BallCameraCfg.Matrix.Matrix[8]
+
+	det := a*(e*i-f*h) - b*(d*i-f*g) + c*(d*h-e*g)
+
+	if det == 0 {
+		return false
+	}
+
+	invDet := 1.0 / det
+	hikBC.BallCameraCfg.Matrix.InvMatrix = []float64{
+		(e*i - f*h) * invDet,
+		(c*h - b*i) * invDet,
+		(b*f - c*e) * invDet,
+		(f*g - d*i) * invDet,
+		(a*i - c*g) * invDet,
+		(c*d - a*f) * invDet,
+		(d*h - e*g) * invDet,
+		(b*g - a*h) * invDet,
+		(a*e - b*d) * invDet,
+	}
+	return true
+}

+ 72 - 0
Type.go

@@ -0,0 +1,72 @@
+package HikNetSDK
+
+import "encoding/json"
+
+type HikCfg struct {
+	Nvr        []Nvr        `json:"Nvr"`
+	BallCamera []BallCamera `json:"BallCamera"`
+}
+
+type Nvr struct {
+	Name     string `json:"name"`
+	Ip       string `json:"ip"`
+	Port     string `json:"port"`
+	User     string `json:"user"`
+	Password string `json:"Password"`
+	Channel  int    `json:"Channel"`
+}
+
+type BallCamera struct {
+	Type     string `json:"Type"`
+	Name     string `json:"name"`
+	Ip       string `json:"ip"`
+	Port     string `json:"port"`
+	User     string `json:"user"`
+	Password string `json:"Password"`
+	RtspUrl  string `json:"RtspUrl"`
+	Matrix   Matrix `json:"Matrix"`
+	Channel  int    `json:"Channel"`
+}
+
+type Matrix struct {
+	PStart             float64   `json:"P_Start"`
+	PMax               float64   `json:"P_Max"`
+	PPositiveDirection string    `json:"p_Positive_Direction"`
+	TStart             float64   `json:"T_Start"`
+	TMax               float64   `json:"T_Max"`
+	TPositiveDirection string    `json:"T_Positive_Direction"`
+	Matrix             []float64 `json:"Matrix"`
+	InvMatrix          []float64 `json:"InvMatrix"`
+}
+
+type PTZ struct {
+	P float32 `json:"P"`
+	T float32 `json:"T"`
+	Z float32 `json:"Z"`
+}
+
+type MoveCfg struct {
+	Speed     int `json:"Speed"`
+	Direction int `json:"Direction"`
+}
+type Point struct {
+	X float64 `json:"x"`
+	Y float64 `json:"y"`
+}
+
+func (h *HikCfg) Json() []byte {
+	marshal, err := json.Marshal(h)
+	if err != nil {
+		return nil
+	}
+	return marshal
+}
+
+func (h *HikCfg) GetBallCameraByName(name string) *BallCamera {
+	for i, camera := range h.BallCamera {
+		if camera.Name == name {
+			return &h.BallCamera[i]
+		}
+	}
+	return nil
+}

+ 377 - 377
src/HIKBallCamera.cpp

@@ -1,377 +1,377 @@
-#include "HIKBallCamera.h"
-#include "FormatTrans.h"
-#include <vector>
-#include <sstream>
-
-HIKBallCamera::HIKBallCamera(){
-
-};
-
-struct PTZ{
-    float P;
-    float T;
-    float Z;
-};
-
-PTZ PTZDATA;
-
-std::vector<std::string> velocity = {"0a","14","1e","28","32","3c","ff"};
-
-bool HIKBallCamera::InitBallCamera(std::string ip, std::string port, std::string username, std::string password, std::string BallMachineType)
-{
-    int res = Login(ip, port, username, password);
-    if (res != 0){
-        std::cout << "Incorrect Login" << std::endl;
-        return false;
-    }
-
-    m_Channel = DeviceInfo.byStartChan;
-    this->BallMachineType = BallMachineType;
-
-    //建立透明通道
-    NET_DVR_SERIALSTART_V40 struSerialParam = { 0 };
-    struSerialParam.dwSize = sizeof(struSerialParam);
-    struSerialParam.dwSerialType = 2;//1:232串口;2:485串口
-    struSerialParam.bySerialNum = 1;//串口编号(设备支持多个RS232串口时有效)
-    lTranHandle = NET_DVR_SerialStart_V40(LoginID, &struSerialParam, sizeof(struSerialParam), g_fSerialDataCallBack, NULL);//设置回调函数获取透传数据
-    if (lTranHandle < 0)
-    {
-        printf("NET_DVR_SerialStart error, %d\n", NET_DVR_GetLastError());
-        NET_DVR_Logout(LoginID);
-        NET_DVR_Cleanup();
-        return false;
-    }
-
-    return true;
-}
-
-//回调透传数据函数的外部实现
-void CALLBACK HIKBallCamera::g_fSerialDataCallBack(LONG lSerialHandle,	LONG lChannel, char *pRecvDataBuffer, DWORD dwBufSize, void *pUser)
-{
-    std::string type = charToHex(pRecvDataBuffer[3]);
-    if (type=="59"){
-        PTZDATA.P = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
-    }else if (type == "5B"){
-        PTZDATA.T = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
-    }else if (type == "5D"){
-        PTZDATA.Z = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
-    }
-}
-
-bool HIKBallCamera::PtzControl(int command, int stop, int speed)
-{
-    bool Ret = false;
-    //use HIK SDK to control the ball camera
-    Ret = NET_DVR_PTZControlWithSpeed_Other(LoginID,m_Channel, command, stop, speed);
-
-    //get the error code
-    if(!Ret)
-    {
-        std::cout << "PTZ control failed! Error code: " << NET_DVR_GetLastError() << std::endl;
-        return false;
-    }
-    return true;
-}
-
-bool HIKBallCamera::PtzControlLeft(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 04 "+velocity[speed - 1]+" 00";
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(PAN_LEFT, state, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlRight(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 02 "+velocity[speed - 1]+" 00";
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(PAN_RIGHT, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlUp(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 08 00 "+velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(TILT_UP, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlDown(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 10 00 "+velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(TILT_DOWN, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlZoomIn(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        SerialSend(PrepareHexString("ff 01 00 20 00 00 21"));
-        return true;
-    }else{
-        return PtzControl(ZOOM_IN, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlZoomOut(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        SerialSend(PrepareHexString("ff 01 00 40 00 00 41"));
-        return true;
-    }else{
-        return PtzControl(ZOOM_OUT, 0, speed);
-    }
-}
-
-
-bool HIKBallCamera::PtzControlFocusAdd(int speed,int state){
-    if (BallMachineType=="BuKongQiu") {
-        std::cout << "ff 01 01 00 00 00 02" << std::endl;
-        SerialSend(PrepareHexString("ff 01 01 00 00 00 02"));
-        return true;
-    }else{
-        return PtzControl(ZOOM_OUT, 1, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlFocusSub(int speed,int state){
-    if (BallMachineType=="BuKongQiu") {
-        std::cout << "ff 01 00 80 00 00 81" << std::endl;
-        SerialSend(PrepareHexString("ff 01 00 80 00 00 81"));
-        return true;
-    }else{
-        return PtzControl(ZOOM_OUT, 1, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlStop(){
-    SerialSend(PrepareHexString("ff 01 00 00 00 00 01"));
-    return true;
-}
-
-
-bool HIKBallCamera::PtzControlUpLeft(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 0c "+velocity[speed - 1]+" " + velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(UP_LEFT, state, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlUpRight(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 0a "+velocity[speed - 1]+" " + velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(UP_RIGHT, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlDownLeft(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 14 "+velocity[speed - 1]+" " + velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(DOWN_LEFT, 0, speed);
-    }
-}
-
-bool HIKBallCamera::PtzControlDownRight(int speed,int state)
-{
-    if (BallMachineType=="BuKongQiu") {
-        std::string buf = "ff 01 00 12 "+velocity[speed - 1]+" " + velocity[speed - 1];
-        buf = buf +" "+ verify(buf);
-        SerialSend(PrepareHexString(buf));
-        return true;
-    }else{
-        return PtzControl(DOWN_RIGHT, 0, speed);
-    }
-}
-
-std::string addSpacesEveryTwoWords(const std::string& hex) {
-    std::ostringstream result;
-
-    int len = hex.length();
-    // 如果十六进制字符串的长度是奇数,则在前面添加一个 0
-    std::string paddedHex = (len % 2 == 1) ? "0" + hex : hex;
-    // 遍历字符串,每两个字符分割一次
-    for (size_t i = 0; i < paddedHex.length(); i += 2) {
-        if (i != 0) {
-            result << " ";
-        }
-        result << paddedHex.substr(i, 2);
-    }
-    return result.str();
-}
-std::string padding(const std::string& hex){
-    if (hex.length()==2){
-        return "00 "+hex;
-    } else{
-        return hex;
-    }
-}
-
-
-// PTZ 跳转到指定位置
-bool HIKBallCamera::PtzGotoPut(int Action, float P, float T, float Z)
-{
-    if (BallMachineType=="BuKongQiu"){
-        std::string pHex = decimalToHexadecimal(P * 100);
-        pHex = padding(addSpacesEveryTwoWords(pHex));
-        std::string tHex = decimalToHexadecimal(T * 100);
-        tHex = padding(addSpacesEveryTwoWords(tHex));
-        std::string zHex = decimalToHexadecimal(Z * 100);
-        zHex = padding(addSpacesEveryTwoWords(zHex));
-        std::string pBuf = "ff 01 00 4b "+ pHex;
-        std::string tBuf = "ff 01 00 4d "+ tHex;
-        std::string zBuf = "ff 01 00 4f "+ zHex;
-        pBuf = pBuf+" "+verify(pBuf);
-        tBuf = tBuf+" "+verify(tBuf);
-        zBuf = zBuf+" "+verify(zBuf);
-        switch (Action) {
-            case 1:
-                SerialSend(PrepareHexString(pBuf)); // 设置 P
-                SerialSend(PrepareHexString(tBuf)); // 设置 T
-                SerialSend(PrepareHexString(zBuf)); // 设置 Z
-                break;
-            case 2:
-                SerialSend(PrepareHexString(pBuf)); // 设置 P
-                break;
-            case 3:
-                SerialSend(PrepareHexString(tBuf)); // 设置 T
-                break;
-            case 4:
-                SerialSend(PrepareHexString(zBuf)); // 设置 Z
-                break;
-            case 5:
-                SerialSend(PrepareHexString(pBuf)); // 设置 P
-                SerialSend(PrepareHexString(tBuf)); // 设置 T
-                break;
-            default:
-                break;
-        }
-        return true;
-    }else{
-        NET_DVR_PTZPOS ptzPosCurrent;
-        ptzPosCurrent.wPanPos = DEC2HEX(P);
-        ptzPosCurrent.wTiltPos = DEC2HEX(T);
-        ptzPosCurrent.wAction = 5;
-
-        bool b = NET_DVR_SetDVRConfig(LoginID, NET_DVR_SET_PTZPOS, m_Channel, &ptzPosCurrent, sizeof(NET_DVR_PTZPOS));
-        return b;
-    }
-}
-bool HIKBallCamera::SerialSend(const std::string& hex){
-    char m_DataBuf[50];
-    int m_DataLen;
-    int len = hex.length();
-    m_DataLen = len<1024 ? len : 1024;
-    memcpy(m_DataBuf,hex.c_str(),m_DataLen);
-    return NET_DVR_SerialSend(lTranHandle,1, m_DataBuf, m_DataLen);
-}
-
-bool HIKBallCamera::PtzGet(float* posP, float* posT, float* posZ) {
-    if (BallMachineType=="BuKongQiu"){
-        SerialSend(PrepareHexString("ff 01 00 51 00 00 52"));
-        SerialSend(PrepareHexString("ff 01 00 53 00 00 54"));
-        SerialSend(PrepareHexString("ff 01 00 55 00 00 56"));
-        SLEEP(1);
-        *posP = PTZDATA.P;
-        *posT = PTZDATA.T;
-        *posZ = PTZDATA.Z;
-        return true;
-    }else{
-        NET_DVR_PTZPOS ptzPosCurrent;
-        DWORD dwtmp;
-        bool b = NET_DVR_GetDVRConfig(LoginID, NET_DVR_GET_PTZPOS, m_Channel, &ptzPosCurrent, sizeof(NET_DVR_PTZPOS),&dwtmp);
-        float P = HEX2DEC(ptzPosCurrent.wPanPos);
-        float T = HEX2DEC(ptzPosCurrent.wTiltPos);
-        float Z = HEX2DEC(ptzPosCurrent.wZoomPos);
-        posP = &P;
-        posT = &T;
-        posZ = &Z;
-        return b;
-    }
-}
-
-bool HIKBallCamera::CmdSwitch(int direction,int speed,int state){
-    bool Res = false;
-    switch (direction) {
-        case PTZ_LEFT:
-            Res = PtzControlLeft(speed,state);
-            break;
-        case PTZ_RIGHT:
-            Res = PtzControlRight(speed,state);
-            break;
-        case PTZ_UP:
-            Res = PtzControlUp(speed,state);
-            break;
-        case PTZ_DOWN:
-            Res = PtzControlDown(speed,state);
-            break;
-        case PTZ_UP_LEFT:
-            Res = PtzControlUpLeft(speed,state);
-            break;
-        case PTZ_UP_RIGHT:
-            Res = PtzControlUpRight(speed,state);
-            break;
-        case PTZ_DOWN_LEFT:
-            Res = PtzControlDownLeft(speed,state);
-            break;
-        case PTZ_DOWN_RIGHT:
-            Res = PtzControlDownRight(speed,state);
-            break;
-        case PTZ_ZOOM_IN:
-            Res = PtzControlZoomIn(speed,state);
-            break;
-        case PTZ_ZOOM_OUT:
-            Res = PtzControlZoomOut(speed,state);
-            break;
-        case PTZ_Focus_Far:
-            Res = PtzControlFocusSub(speed,state);
-            break;
-        case PTZ_Focus_Near:
-            Res = PtzControlFocusAdd(speed,state);
-            break;
-    }
-    return Res;
-}
-
-bool HIKBallCamera::StopBus(int direction) {
-    if (BallMachineType=="BuKongQiu"){
-        return PtzControlStop();
-    }
-    return CmdSwitch(direction,0,1);
-}
-
-bool HIKBallCamera::StartBus(int direction, int speed) {
-    return CmdSwitch(direction,speed,0);
-}
+#include "HIKBallCamera.h"
+#include "FormatTrans.h"
+#include <vector>
+#include <sstream>
+
+HIKBallCamera::HIKBallCamera(){
+
+};
+
+struct PTZ{
+    float P;
+    float T;
+    float Z;
+};
+
+PTZ PTZDATA;
+
+std::vector<std::string> velocity = {"0a","14","1e","28","32","3c","ff"};
+
+bool HIKBallCamera::InitBallCamera(std::string ip, std::string port, std::string username, std::string password, std::string BallMachineType)
+{
+    int res = Login(ip, port, username, password);
+    if (res != 0){
+        std::cout << "Incorrect Login error code:" << res << std::endl;
+        return false;
+    }
+
+    m_Channel = DeviceInfo.byStartChan;
+    this->BallMachineType = BallMachineType;
+
+    if (BallMachineType == "BuKongQiu"){
+        NET_DVR_SERIALSTART_V40 struSerialParam = { 0 };
+        struSerialParam.dwSize = sizeof(struSerialParam);
+        struSerialParam.dwSerialType = 2;//1:232串口;2:485串口
+        struSerialParam.bySerialNum = 1;//串口编号(设备支持多个RS232串口时有效)
+        lTranHandle = NET_DVR_SerialStart_V40(LoginID, &struSerialParam, sizeof(struSerialParam), g_fSerialDataCallBack, NULL);//设置回调函数获取透传数据
+        if (lTranHandle < 0)
+        {
+            printf("NET_DVR_SerialStart error, %d\n", NET_DVR_GetLastError());
+            NET_DVR_Logout(LoginID);
+            NET_DVR_Cleanup();
+            return false;
+        }
+    }
+    return true;
+}
+
+//回调透传数据函数的外部实现
+void CALLBACK HIKBallCamera::g_fSerialDataCallBack(LONG lSerialHandle,	LONG lChannel, char *pRecvDataBuffer, DWORD dwBufSize, void *pUser)
+{
+    std::string type = charToHex(pRecvDataBuffer[3]);
+    if (type=="59"){
+        PTZDATA.P = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
+    }else if (type == "5B"){
+        PTZDATA.T = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
+    }else if (type == "5D"){
+        PTZDATA.Z = float(hexadecimalToDecimal(charToHex(pRecvDataBuffer[4])+charToHex(pRecvDataBuffer[5])))/100.0;
+    }
+}
+
+bool HIKBallCamera::PtzControl(int command, int stop, int speed)
+{
+    bool Ret = false;
+    //use HIK SDK to control the ball camera
+    Ret = NET_DVR_PTZControlWithSpeed_Other(LoginID,m_Channel, command, stop, speed);
+
+    //get the error code
+    if(!Ret)
+    {
+        std::cout << "PTZ control failed! Error code: " << NET_DVR_GetLastError() << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool HIKBallCamera::PtzControlLeft(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 04 "+velocity[speed - 1]+" 00";
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(PAN_LEFT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlRight(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 02 "+velocity[speed - 1]+" 00";
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(PAN_RIGHT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlUp(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 08 00 "+velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(TILT_UP, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlDown(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 10 00 "+velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(TILT_DOWN, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlZoomIn(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        SerialSend(PrepareHexString("ff 01 00 20 00 00 21"));
+        return true;
+    }else{
+        return PtzControl(ZOOM_IN, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlZoomOut(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        SerialSend(PrepareHexString("ff 01 00 40 00 00 41"));
+        return true;
+    }else{
+        return PtzControl(ZOOM_OUT, state, speed);
+    }
+}
+
+
+bool HIKBallCamera::PtzControlFocusAdd(int speed,int state){
+    if (BallMachineType=="BuKongQiu") {
+        std::cout << "ff 01 01 00 00 00 02" << std::endl;
+        SerialSend(PrepareHexString("ff 01 01 00 00 00 02"));
+        return true;
+    }else{
+        return PtzControl(ZOOM_OUT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlFocusSub(int speed,int state){
+    if (BallMachineType=="BuKongQiu") {
+        std::cout << "ff 01 00 80 00 00 81" << std::endl;
+        SerialSend(PrepareHexString("ff 01 00 80 00 00 81"));
+        return true;
+    }else{
+        return PtzControl(ZOOM_OUT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlStop(){
+    SerialSend(PrepareHexString("ff 01 00 00 00 00 01"));
+    return true;
+}
+
+
+bool HIKBallCamera::PtzControlUpLeft(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 0c "+velocity[speed - 1]+" " + velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(UP_LEFT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlUpRight(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 0a "+velocity[speed - 1]+" " + velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(UP_RIGHT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlDownLeft(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 14 "+velocity[speed - 1]+" " + velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(DOWN_LEFT, state, speed);
+    }
+}
+
+bool HIKBallCamera::PtzControlDownRight(int speed,int state)
+{
+    if (BallMachineType=="BuKongQiu") {
+        std::string buf = "ff 01 00 12 "+velocity[speed - 1]+" " + velocity[speed - 1];
+        buf = buf +" "+ verify(buf);
+        SerialSend(PrepareHexString(buf));
+        return true;
+    }else{
+        return PtzControl(DOWN_RIGHT, state, speed);
+    }
+}
+
+std::string addSpacesEveryTwoWords(const std::string& hex) {
+    std::ostringstream result;
+
+    int len = hex.length();
+    // 如果十六进制字符串的长度是奇数,则在前面添加一个 0
+    std::string paddedHex = (len % 2 == 1) ? "0" + hex : hex;
+    // 遍历字符串,每两个字符分割一次
+    for (size_t i = 0; i < paddedHex.length(); i += 2) {
+        if (i != 0) {
+            result << " ";
+        }
+        result << paddedHex.substr(i, 2);
+    }
+    return result.str();
+}
+std::string padding(const std::string& hex){
+    if (hex.length()==2){
+        return "00 "+hex;
+    } else{
+        return hex;
+    }
+}
+
+
+// PTZ 跳转到指定位置
+bool HIKBallCamera::PtzGotoPut(int Action, float P, float T, float Z)
+{
+    if (BallMachineType=="BuKongQiu"){
+        std::string pHex = decimalToHexadecimal(P * 100);
+        pHex = padding(addSpacesEveryTwoWords(pHex));
+        std::string tHex = decimalToHexadecimal(T * 100);
+        tHex = padding(addSpacesEveryTwoWords(tHex));
+        std::string zHex = decimalToHexadecimal(Z * 100);
+        zHex = padding(addSpacesEveryTwoWords(zHex));
+        std::string pBuf = "ff 01 00 4b "+ pHex;
+        std::string tBuf = "ff 01 00 4d "+ tHex;
+        std::string zBuf = "ff 01 00 4f "+ zHex;
+        pBuf = pBuf+" "+verify(pBuf);
+        tBuf = tBuf+" "+verify(tBuf);
+        zBuf = zBuf+" "+verify(zBuf);
+        switch (Action) {
+            case 1:
+                SerialSend(PrepareHexString(pBuf)); // 设置 P
+                SerialSend(PrepareHexString(tBuf)); // 设置 T
+                SerialSend(PrepareHexString(zBuf)); // 设置 Z
+                break;
+            case 2:
+                SerialSend(PrepareHexString(pBuf)); // 设置 P
+                break;
+            case 3:
+                SerialSend(PrepareHexString(tBuf)); // 设置 T
+                break;
+            case 4:
+                SerialSend(PrepareHexString(zBuf)); // 设置 Z
+                break;
+            case 5:
+                SerialSend(PrepareHexString(pBuf)); // 设置 P
+                SerialSend(PrepareHexString(tBuf)); // 设置 T
+                break;
+            default:
+                break;
+        }
+        return true;
+    }else{
+        NET_DVR_PTZPOS ptzPosCurrent;
+        ptzPosCurrent.wPanPos = DEC2HEX(P);
+        ptzPosCurrent.wTiltPos = DEC2HEX(T);
+        ptzPosCurrent.wAction = 5;
+
+        bool b = NET_DVR_SetDVRConfig(LoginID, NET_DVR_SET_PTZPOS, m_Channel, &ptzPosCurrent, sizeof(NET_DVR_PTZPOS));
+        return b;
+    }
+}
+bool HIKBallCamera::SerialSend(const std::string& hex){
+    char m_DataBuf[50];
+    int m_DataLen;
+    int len = hex.length();
+    m_DataLen = len<1024 ? len : 1024;
+    memcpy(m_DataBuf,hex.c_str(),m_DataLen);
+    return NET_DVR_SerialSend(lTranHandle,1, m_DataBuf, m_DataLen);
+}
+
+bool HIKBallCamera::PtzGet(float* posP, float* posT, float* posZ) {
+    if (BallMachineType=="BuKongQiu"){
+        SerialSend(PrepareHexString("ff 01 00 51 00 00 52"));
+        SerialSend(PrepareHexString("ff 01 00 53 00 00 54"));
+        SerialSend(PrepareHexString("ff 01 00 55 00 00 56"));
+        SLEEP(1);
+        *posP = PTZDATA.P;
+        *posT = PTZDATA.T;
+        *posZ = PTZDATA.Z;
+        return true;
+    }else{
+        NET_DVR_PTZPOS ptzPosCurrent;
+        DWORD dwtmp;
+        bool b = NET_DVR_GetDVRConfig(LoginID, NET_DVR_GET_PTZPOS, m_Channel, &ptzPosCurrent, sizeof(NET_DVR_PTZPOS),&dwtmp);
+        float P = HEX2DEC(ptzPosCurrent.wPanPos);
+        float T = HEX2DEC(ptzPosCurrent.wTiltPos);
+        float Z = HEX2DEC(ptzPosCurrent.wZoomPos);
+        posP = &P;
+        posT = &T;
+        posZ = &Z;
+        return b;
+    }
+}
+
+bool HIKBallCamera::CmdSwitch(int direction,int speed,int state){
+    bool Res = false;
+    switch (direction) {
+        case PTZ_LEFT:
+            Res = PtzControlLeft(speed,state);
+            break;
+        case PTZ_RIGHT:
+            Res = PtzControlRight(speed,state);
+            break;
+        case PTZ_UP:
+            Res = PtzControlUp(speed,state);
+            break;
+        case PTZ_DOWN:
+            Res = PtzControlDown(speed,state);
+            break;
+        case PTZ_UP_LEFT:
+            Res = PtzControlUpLeft(speed,state);
+            break;
+        case PTZ_UP_RIGHT:
+            Res = PtzControlUpRight(speed,state);
+            break;
+        case PTZ_DOWN_LEFT:
+            Res = PtzControlDownLeft(speed,state);
+            break;
+        case PTZ_DOWN_RIGHT:
+            Res = PtzControlDownRight(speed,state);
+            break;
+        case PTZ_ZOOM_IN:
+            Res = PtzControlZoomIn(speed,state);
+            break;
+        case PTZ_ZOOM_OUT:
+            Res = PtzControlZoomOut(speed,state);
+            break;
+        case PTZ_Focus_Far:
+            Res = PtzControlFocusSub(speed,state);
+            break;
+        case PTZ_Focus_Near:
+            Res = PtzControlFocusAdd(speed,state);
+            break;
+    }
+    return Res;
+}
+
+bool HIKBallCamera::StopBus(int direction) {
+    if (BallMachineType=="BuKongQiu"){
+        return PtzControlStop();
+    }
+    return CmdSwitch(direction,0,1);
+}
+
+bool HIKBallCamera::StartBus(int direction, int speed) {
+    return CmdSwitch(direction,speed,0);
+}

+ 35 - 36
src/HIKBase.cpp

@@ -1,37 +1,36 @@
-#include "HIKBase.h"
-#include <memory>
-#include <cstring>
-#include <chrono>
-
-HIKBase::HIKBase()
-{
-    memset(&DeviceInfo, 0, sizeof(DeviceInfo));
-}
-
-
-HIKBase::~HIKBase() = default;
-
-int HIKBase::Login(std::string ip, std::string port, std::string username, std::string password)
-{
-    Ip = ip;
-    Port = port;
-    Username = username;
-    Password = password;
-
-    LoginID = NET_DVR_Login_V30((char *)Ip.c_str(), atoi(Port.c_str()), (char *)Username.c_str(), (char *)Password.c_str(), &DeviceInfo);
-    std::cout << LoginID <<std::endl;
-    return LoginID;
-}
-
-void HIKBase::Logout()
-{
-    if (LoginID >= 0)
-    {
-        NET_DVR_Logout(LoginID);
-        LoginID = -1;
-    }
-}
-
-bool HK_DVR_Init(){
-    return NET_DVR_Init();
+#include "HIKBase.h"
+#include <memory>
+#include <cstring>
+#include <chrono>
+
+HIKBase::HIKBase()
+{
+    memset(&DeviceInfo, 0, sizeof(DeviceInfo));
+}
+
+
+HIKBase::~HIKBase() = default;
+
+int HIKBase::Login(std::string ip, std::string port, std::string username, std::string password)
+{
+    Ip = ip;
+    Port = port;
+    Username = username;
+    Password = password;
+
+    LoginID = NET_DVR_Login_V30((char *)Ip.c_str(), atoi(Port.c_str()), (char *)Username.c_str(), (char *)Password.c_str(), &DeviceInfo);
+    return NET_DVR_GetLastError();
+}
+
+void HIKBase::Logout()
+{
+    if (LoginID >= 0)
+    {
+        NET_DVR_Logout(LoginID);
+        LoginID = -1;
+    }
+}
+
+bool HK_DVR_Init(){
+    return NET_DVR_Init();
 }