SoFunction
Updated on 2025-04-08

Detailed explanation of how to use Hikvision Equipment Network SDK to perform Java secondary development camera license plate recognition

Preface

As the first requirement for interns, although it is very simple, we still need to record the problems encountered in this process and solutions.

Development Process

  • Open Hikvision official website to findDevelopment Documentationand download the correspondingDevice Network SDK, there is also a chm version of the corresponding development document in the compressed package of the device network SDK, which is more convenient to view. In the same way, we can find Java demos. Note that after copying the dll support library to the demo's lib directory, you can try to run it.
  • When the equipment detects the vehicle, the license plate recognition and picture capture are carried out, and the recognition and capture results are uploaded. Identification and capture are implemented by the device, and are uploaded actively by the device and received by the SDK. This means that we only need to new SDK object on the backend, and after establishing a connection with the device, we will upload the information to the SDK, and the SDK will process the information. The commonly understood method of arming means to turn on the recognition function. There are two ways to arming here.

    1) Alarming method refers to the SDK actively connecting the device to establish an alarm upload channel, and sending it to the SDK after an alarm occurs in the device. You need to register and log in to the device first.
    2) Alarm monitoring method refers to the device actively connecting to the SDK and uploading alarm information when the event is triggered, and the SDK monitors and receives it on the set port. It is necessary to first configure the IP and port of the alarm host on the device side, which should be the same as the IP and ports listened to by the SDK.

  • I chose the alarm and defense method here. Since Hikvision's SDK is written based on C++, the JavaSDK in it is also translated based on C++, all of which are counterintuitive, but it's okay, I will explain the problems I encountered clearly. I won't post the demo code, there are all documents, so I'll focus on the problems I encountered.

Problems and solutions

The problem of the dll library not loading

If you run the demo directly, there should be no problem if nothing unexpected happens, unless you fail to log in without using your own device and IP, and the library can also be loaded.

However, when we do secondary development, we always need to integrate these things into the project, which may be single projects or microservice projects. Most of the time, we need to put lib in a fixed folder of the project, such as the lib directory under WEB-INF, for example, my project is, which originally contains a lot of dependencies and has already added as library.

private static boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized () {
                String strDllPath = "";
                try {
                    if (())
                        //Win system loading library path                        strDllPath = ("") + "\\lib\\";
                    else if (())
                        //Linux system loading library path                        strDllPath = ("") + "/lib/";
                    hCNetSDK = (HCNetSDK) (strDllPath, );
                    (strDllPath);
                } catch (Exception ex) {
                    ("loadLibrary: " + strDllPath + " Error: " + ());
                    return false;
                }
            }
        }
        return true;
    }

() This method, the previous parameter is the location of the dll to be loaded, and the latter is the class to be loaded. The first parameter in the demo is filled in the absolute path. When I integrated it into the project, I found that there was always an error here. Later, the debugging found that the path obtained was the path of the tomcat deployment directory, and he did not recognize it in the new lib folder in the root directory of the project. Later, I tried to write it as an absolute path, but it still didn't work. The error turned into a very strange message, showing that xxx (the absolute path of dll) cannot be found in xxx (the directory of lib under WEB-INF), but in fact, I have put the dll in the lib directory under WEB-INF, why can't I find it?

Later, I found that the first parameter of this method only needs to fill in the name supported by the dll, so I changed it to

if (hcNetSDK == null) {
            synchronized () {
                String strDllPath = "";
                try {
                
                    // Load the library                    hcNetSDK = (HCNetSDK) ("HCNetSDK", );
                } catch (Exception ex) {
                    ("loadLibrary: " + strDllPath + " Error: " + ());
                    return false;
                }
            }

It can be loaded now. The reason for analysis may be that () method will go to the lib directory specified by the project to find the corresponding dll. If the project does not specify the lib directory, then you need to specify the absolute path. If it is specified, then you only need the name. Maybe there is something wrong with my understanding, and if you have a better understanding, please point it out.

Issues of incompatibility of old versions of SDK

If you are using the newly downloaded SDK, then the following problem should not be encountered

In the demo, you can see that all classes inherit a Structure. This is because there is no structure in Java. As we mentioned earlier, the sdk is translated from C++, so he customized a structure. However, there is a problem. In the old version of sdk, there is a getFiledName() method in this Structure that needs to be implemented by itself. We have to customize a BaseStructure. After writing this method, replace all the places where Structure is integrated in sdk with our custom BaseStructure. The code is as follows.

public class BaseStructure extends Structure
{
	@Override
	protected List<String> getFieldOrder()
	{
		return getFiledName(this);
	}

	public static List<String> getFiledName(Object o)
	{
		Field[] fields = ().getDeclaredFields();
		String[] fieldNames = new String[];
		for (int i = 0; i < ; i++)
		{
			fieldNames[i] = fields[i].getName();
		}
		return (fieldNames);
	}
}

However, in the new version of SDK, this method no longer needs to be rewrited.

I have used the old version of SDK to write some old modules in my project, so I encountered the above problem. In addition, when I replaced the old version of SDK, I found that many methods in the old version of SDK use the nativelong type as the return value or variable type, while in the new version of SDK, these become int, so if the SDK you are using has problems with conflicts between new and old versions, you can try to replace the nativelong type with int.

Key implementation process

Create an SDK instance;

if (hCNetSDK == null) {
            if (!createSDKInstance()) {
                ("Load SDK fail");
                return;
            }
        }

Initialize and load the log

        /**initialization*/
        hCNetSDK.NET_DVR_Init();
        /**Loading log*/
        hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog1", false);
        

Write and set up a callback function (the callback function is a function that processes license plate information. COMM_ITS_PLATE_RESULT is the situation where we need license plate information. You can write your own logic in it). There are different types of license plate photos. You can save the photos yourself as needed. There are different numbers in the document corresponding to different scene pictures.

public class FMSGCallBack implements HCNetSDK.FMSGCallBack_V31 {
    //Alarm information callback function    public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {

        ("Alarm event type: lCommand:" + (lCommand));
        String MonitoringSiteID;
        switch (lCommand) {
            case 0x3058:
                ("Alarm event type: 0x3058 The vehicle black and white list data needs to be uploaded simultaneously");
                break;

            case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:
                ("Alarm event type: COMM_UPLOAD_PLATE_RESULT");
                break;

            case HCNetSDK.COMM_ITS_PLATE_RESULT:  // Traffic capture results (new alarm information)                HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
                //You can handle your own logic here                break;

            default:
                ("Alarm Type:" + (lCommand));
                break;
        }
        return true;
    }

}
if (fMSFCallBack_V31 == null) {
            fMSFCallBack_V31 = new FMSGCallBack_V31();
            Pointer pUser = null;
            if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
                ("Setting the callback function failed!");
                return;
            } else {
                ("Set the callback function successfully!");
            }
        }

Set the result separation parameters

/** The alarm information uploaded by the device is COMM_VCA_ALARM(0x4993),
          After SDK initialization, add call to NET_DVR_SetSDKLocalCfg (enumType is NET_DVR_LOCAL_CFG_TYPE_GENERAL) to set the byAlarmJsonPictureSeparate of the general parameter NET_DVR_LOCAL_GENERAL_CFG to 1,
          Separately upload Json data and picture data. After setting this way, the alarm information received in the alarm protection callback function is COMM_ISAPI_ALARM(0x6009).
          The alarm information structure is NET_DVR_ALARM_ISAPI_INFO (the data structure that is unrelated to the device, encapsulated by SDK), which is easier to parse.  */

        HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
        struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1;   //Set the separation of JSON transit alarm data and pictures        struNET_DVR_LOCAL_GENERAL_CFG.write();
        Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();
        hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);

Then log in to the device and arm it

lUserID=( "10.9.137.17", (short) 8000, "admin", "hik12345");  //Login the device
lAlarmHandle=(lUserID);//Add to alarm and monitor

One thing to note is that the license plate recognition cannot directly identify still pictures. For example, we used the method of putting a tablet (placing a license plate photo on the tablet), and the camera did not capture it. It was moved several times before it was identified. You can pay attention when testing. Although it did not capture the license plate at this time, there was still some alarm information.

Alarm event type: 0x3058 The vehicle black and white list data needs to be uploaded simultaneously

This information will appear every once in a while. When asked the customer service, it is said that this information does not need to be parsed. You can also use this information as debugging information on whether your camera is properly armed. If there is this type of alarm, it means that the armed operation has been successfully armed.

Summarize

This is the article about how to use Hikvision Device Network SDK to perform Java secondary development camera license plate recognition. For more related contents of Hikvision Device Network SDK camera license plate recognition, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!