iDS-2CD7A26G0/P-IZHS get captured plate numbers via ISAPI or just API?

shakir

n3wb
Joined
Feb 20, 2023
Messages
2
Reaction score
0
Location
Uzbekistan
I'm using a iDS-2CD7A26G0/P-IZHS ANPR to capture plate-numbers of cars who visited carwash center. What I want now is that, I want to get the captured-plates-result (ex: 'plate-number', 'time-stamp'...) through ISAPI or calling some API and insert it to my MYSQL database.
I followed this: stackoverfow post, but I dont know why, it didnt work. It returns 401 error.
bellow is the python source code that I used to get the latest capture results.

Python:
import requests
from requests.auth import HTTPDigestAuth
import xml.etree.ElementTree as ET

endpoint = "http://192.168.0.64/ISAPI/Traffic/channels/1/vehicleDetect/results"
headers = {'Content-Type': 'application/xml'}
auth1 = ('user', 'q1234!@#$')
auth2 = requests.auth.HTTPDigestAuth('user', 'q1234!@#$')

# Send an HTTP GET request to the endpoint
response1 = requests.get(endpoint, headers=headers, auth=auth1)
print(response1.status_code)
response2 = requests.get(endpoint, headers=headers, auth=auth2)
print(response2.status_code)

# Parse the response XML to retrieve the detected plate number
if response1.status_code == 200:
    root = ET.fromstring(response1.content)
    plate_number = root.find('./PlateResult').get('license')
    confidence = root.find('./PlateResult').get('confidence')
    plate_location = root.find('./PlateResult').get('plateLocation')

# Parse the response XML to retrieve the detected plate number
if response2.status_code == 200:
    root = ET.fromstring(response2.content)
    plate_number = root.find('./PlateResult').get('license')
    confidence = root.find('./PlateResult').get('confidence')
    plate_location = root.find('./PlateResult').get('plateLocation')
 
Last edited:

trempa92

Pulling my weight
Joined
Mar 26, 2020
Messages
724
Reaction score
221
Location
Croatia,Zagreb

shakir

n3wb
Joined
Feb 20, 2023
Messages
2
Reaction score
0
Location
Uzbekistan
Digest Auth POST Body:

<?xml version="1.0" encoding="UTF-8"?>
<AfterTime version="2.0" xmlns="">
<picTime>YYYYMMDDHHMMSS</picTime>
</AfterTime>


This will give you 20 results and that is max and the starting time is set in picTime

As you can see you were doing a GET which would get last 20 always, now you do post with starting time cause it contains more data now.

Cheers

Hi, thanks for your response.
Tried it, butIt didn't work for me. It is returning 401
 

trempa92

Pulling my weight
Joined
Mar 26, 2020
Messages
724
Reaction score
221
Location
Croatia,Zagreb
Probably you are doing something wrong with Digest authorization in your app.

Try with Postman and see if it works
 

trempa92

Pulling my weight
Joined
Mar 26, 2020
Messages
724
Reaction score
221
Location
Croatia,Zagreb
403 - Not authorized, look what you are doing wrong with Digest authorization. Perhaps switch to basic in Security tab if you cant handle Digest for some reason.
 

aqeel

n3wb
Joined
Dec 14, 2023
Messages
4
Reaction score
0
Location
Pakistan
Thanks for swift reply . i changed authorization from digest to basic but still it showing same issue.1706020164003.png
 

trempa92

Pulling my weight
Joined
Mar 26, 2020
Messages
724
Reaction score
221
Location
Croatia,Zagreb
I have noticed your Body formatting is horrible. Its probably copy paste typo. Please format it as xml should look like. That is cause of your problem
 

paulpeter

n3wb
Joined
May 31, 2018
Messages
11
Reaction score
6
Location
china
I'm using a iDS-2CD7A26G0/P-IZHS ANPR to capture plate-numbers of cars who visited carwash center. What I want now is that, I want to get the captured-plates-result (ex: 'plate-number', 'time-stamp'...) through ISAPI or calling some API and insert it to my MYSQL database.
I followed this: stackoverfow post, but I dont know why, it didnt work. It returns 401 error.
bellow is the python source code that I used to get the latest capture results.

Python:
import requests
from requests.auth import HTTPDigestAuth
import xml.etree.ElementTree as ET

endpoint = "http://192.168.0.64/ISAPI/Traffic/channels/1/vehicleDetect/results"
headers = {'Content-Type': 'application/xml'}
auth1 = ('user', 'q1234!@#$')
auth2 = requests.auth.HTTPDigestAuth('user', 'q1234!@#$')

# Send an HTTP GET request to the endpoint
response1 = requests.get(endpoint, headers=headers, auth=auth1)
print(response1.status_code)
response2 = requests.get(endpoint, headers=headers, auth=auth2)
print(response2.status_code)

# Parse the response XML to retrieve the detected plate number
if response1.status_code == 200:
    root = ET.fromstring(response1.content)
    plate_number = root.find('./PlateResult').get('license')
    confidence = root.find('./PlateResult').get('confidence')
    plate_location = root.find('./PlateResult').get('plateLocation')

# Parse the response XML to retrieve the detected plate number
if response2.status_code == 200:
    root = ET.fromstring(response2.content)
    plate_number = root.find('./PlateResult').get('license')
    confidence = root.find('./PlateResult').get('confidence')
    plate_location = root.find('./PlateResult').get('plateLocation')
you can check this post:
 

trempa92

Pulling my weight
Joined
Mar 26, 2020
Messages
724
Reaction score
221
Location
Croatia,Zagreb
@paulpeter Thats realtime fetch via Alarm server. And its best possible way to fetch. But i think ISAPI is needed as a backup for the network lost time if the server isn't running 24/7. I don't believe ANR will solve longer network loss

C# equivalent:

Code:
using Microsoft.Extensions.Hosting;
using Microsoft.SqlServer.Server;
using ProxyApi.db_cotroller;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

public class TcpServerService : BackgroundService
{
    private TcpListener _tcpListener;

    private readonly IWebHostEnvironment _env;

    public TcpServerService(IWebHostEnvironment env)
    {
        _env = env;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        string localIP = GetLocalIPAddress();
        _tcpListener = new TcpListener(IPAddress.Parse(localIP), 9091); / Adjust the IP and port
        _tcpListener.Start();

        Console.ForegroundColor = ConsoleColor.Green;

        Console.WriteLine($"HTTP LISTENER started listening on {localIP}:9091.");

        Console.ResetColor();

        while (!stoppingToken.IsCancellationRequested)
        {
            TcpClient client = await _tcpListener.AcceptTcpClientAsync();
            _ = HandleClient(client);
        }
    }

    public static string GetLocalIPAddress()
    {
        var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

        foreach (var networkInterface in networkInterfaces)
        {
            if (networkInterface.NetworkInterfaceType != NetworkInterfaceType.Wireless80211 &&
                networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback)
            {
                var ipProperties = networkInterface.GetIPProperties();
                foreach (var ip in ipProperties.UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        return ip.Address.ToString();
                    }
                }
            }
        }

        throw new Exception("No Ethernet network adapters with an IPv4 address in the system!");
    }


    private async Task HandleClient(TcpClient client)
    {
        string clientIP = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"HTTP LISTENER: {clientIP} sending data.");
        Console.ResetColor();

        try
        {
            using (NetworkStream stream = client.GetStream())
            {
                MemoryStream memoryStream = new MemoryStream();
                byte[] buffer = new byte[client.ReceiveBufferSize];
                int bytesRead;

                while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                {
                    memoryStream.Write(buffer, 0, bytesRead);
                }

                byte[] requestData = memoryStream.ToArray();

                string boundaryString = GetBoundary(requestData);

                if (boundaryString == null)
                {
                    Console.WriteLine("Boundary string not found in the request.");
                    return;
                }

                List<MultipartFormData> formDataList = ExtractFormData(requestData, boundaryString);

                foreach (var formData in formDataList)
                {

                    if (formData.IsImage)
                    {
                        string webRootPath = _env.WebRootPath;
                        string folderPath = Path.Combine(webRootPath, "images", "lpr_images");

                        Directory.CreateDirectory(folderPath);
                        string filePath = Path.Combine(folderPath, formData.Filename);
                        File.WriteAllBytes(filePath, formData.Content);
                        Console.WriteLine($"IMAGE: Saved {formData.Filename}");
                    }
                    else if (formData.ContentType.Equals("text/xml", StringComparison.OrdinalIgnoreCase))
                    {
                        string xmlContent = Encoding.UTF8.GetString(formData.Content);

                        XNamespace ns = "http://www.hikvision.com/ver20/XMLSchema";
                        XDocument xmlDoc = XDocument.Parse(xmlContent);

                        string eventType = xmlDoc.Root.Element(ns + "eventType")?.Value;
                        if (!string.Equals(eventType, "ANPR", StringComparison.OrdinalIgnoreCase))
                        {
                            Console.WriteLine("Skipping non-ANPR event.");
                            continue;
                        }

                        string ipAddress = xmlDoc.Root.Element(ns + "ipAddress")?.Value;
                        string dateTime = xmlDoc.Root.Element(ns + "dateTime")?.Value;
                        XElement anprElement = xmlDoc.Root.Element(ns + "ANPR");
                        string licensePlate = anprElement?.Element(ns + "licensePlate")?.Value;
                        string vehicleListName = anprElement?.Element(ns + "vehicleListName")?.Value;
                        string secondPIdValue = "";

                        if (anprElement != null)
                        {
                            XElement pictureInfoListElement = anprElement.Element(ns + "pictureInfoList");

                            if (pictureInfoListElement != null)
                            {
                                / Select the second pId element by index (index 1) within the ANPR element
                                XElement secondPictureInfoElement = pictureInfoListElement.Elements(ns + "pictureInfo").ElementAtOrDefault(1);

                                if (secondPictureInfoElement != null)
                                {
                                    XElement secondPIdElement = secondPictureInfoElement.Element(ns + "pId");

                                    if (secondPIdElement != null)
                                    {
                                        secondPIdValue = secondPIdElement.Value + ".jpg";
                                    }
                                }
                            }

                            / Now you have the secondPIdValue                          
                        }

                        if (ipAddress == null || dateTime == null || licensePlate == null || vehicleListName == null || secondPIdValue == null)
                        {
                            Console.WriteLine("One or more required XML elements are missing.");
                            continue;
                        }                    
                        SaveLPRlogstoDB.SaveLprLogs(ipAddress, dateTime, licensePlate, vehicleListName, secondPIdValue);
                    }
                }

                byte[] responseBytes = Encoding.ASCII.GetBytes("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
                await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("HTTP LISTENER: Data processed and response sent.");
                Console.ResetColor();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred while handling the client: {ex}");
        }
    }

    static string GetBoundary(byte[] requestData)
    {
        string header = Encoding.UTF8.GetString(requestData);
        Match match = Regex.Match(header, "boundary=(?<boundary>.+?)\r\n");
        if (match.Success)
        {
            return "--" + match.Groups["boundary"].Value.Trim();
        }
        return null;
    }

    static List<MultipartFormData> ExtractFormData(byte[] requestData, string boundaryString)
    {
        List<MultipartFormData> formDataList = new List<MultipartFormData>();
        byte[] boundaryBytes = Encoding.ASCII.GetBytes(boundaryString);

        int currentIndex = 0;
        while (currentIndex < requestData.Length)
        {
            int headerStartIndex = FindIndex(requestData, Encoding.ASCII.GetBytes("Content-Disposition: form-data;"), currentIndex);
            if (headerStartIndex == -1) break;

            int headerEndIndex = FindIndex(requestData, Encoding.ASCII.GetBytes("\r\n\r\n"), headerStartIndex);
            if (headerEndIndex == -1) break;

            string header = Encoding.ASCII.GetString(requestData, headerStartIndex, headerEndIndex - headerStartIndex);
            var filenameMatch = Regex.Match(header, "filename=\"(?<filename>[^\"]+)\"");
            var contentTypeMatch = Regex.Match(header, "Content-Type: (?<contentType>[^\r\n]+)");

            string filename = filenameMatch.Groups["filename"].Value;
            string contentType = contentTypeMatch.Success ? contentTypeMatch.Groups["contentType"].Value : "application/octet-stream"; / Default content type if none specified

            int contentStartIndex = headerEndIndex + 4; / The start index of the content data
            int boundaryIndex = FindIndex(requestData, boundaryBytes, contentStartIndex);
            if (boundaryIndex == -1) boundaryIndex = requestData.Length;

            int contentLength = boundaryIndex - contentStartIndex;
            byte[] contentData = new byte[contentLength];
            Array.Copy(requestData, contentStartIndex, contentData, 0, contentLength);

            formDataList.Add(new MultipartFormData
            {
                ContentType = contentType,
                Filename = filename,
                Content = contentData
                / IsImage is a computed property based on ContentType; no need to set it explicitly
            });

            currentIndex = boundaryIndex + boundaryBytes.Length; / Set currentIndex to after the boundary for the next loop iteration
        }

        return formDataList;
    }

    static int FindIndex(byte[] data, byte[] pattern, int startIndex = 0)
    {
        for (int i = startIndex; i < data.Length - pattern.Length + 1; i++)
        {
            bool isMatch = true;
            for (int j = 0; j < pattern.Length; j++)
            {
                if (data[i + j] != pattern[j])
                {
                    isMatch = false;
                    break;
                }
            }
            if (isMatch) return i;
        }
        return -1;
    }



    class MultipartFormData
    {
        public string ContentType { get; set; }
        public string Filename { get; set; }
        public byte[] Content { get; set; }
        public bool IsImage => ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase);
    }



    public override Task StopAsync(CancellationToken cancellationToken)
    {
        _tcpListener?.Stop();
        return base.StopAsync(cancellationToken);
    }
}
 
Top