Onvif Create Element items for rule creation in c#

Viewed 11

I have a HIK camera that is Onvif compliant. I have been able to get the credentials and login to the camera. From there I am able to create simple rules for cell detection.

I want to add line detection which uses a ItemListElementItem.

I have been reading the specification and documentation This specifically mentions line detection: https://www.onvif.org/specs/srv/analytics/ONVIF-Analytics-Service-Spec.pdf

This document gives some additional overview on the rules: https://www.onvif.org/wp-content/uploads/2016/12/Version_Handling-1.pdf

I can get the supported rules from the device. If I then create a rule from the HIK UI, I have been able to modify this rule with some hard coded string values.

The documentation states that the line "type" should be "polyline" and that this is a "IntRange". I am not sure how to generate the required XMLNode from this information.

Here is the code I have that works, with a generated xmlElement from a string.

 public async Task CreateLineDetection()
    {
        try
        {
            var device = await OnvifClientFactory.CreateDeviceClientAsync(_cameraIp, _userName, _password);
            var media = await OnvifClientFactory.CreateMediaClientAsync(_cameraIp, _userName, _password);
            var analyticsEngine = await OnvifClientFactory.CreateAnalyticsEnginePortClientAsync(_cameraIp, _userName, _password);
            var ruleEngine = await OnvifClientFactory.CreateRuleEnginePortClientAsync(_cameraIp, _userName, _password);

            var profiles = await media.GetProfilesAsync();

            var mediaAnalytics = await media.GetVideoAnalyticsConfigurationsAsync();

            var analysticConfigurations = mediaAnalytics.Configurations;
            var analyticsConfigurationEngine = analysticConfigurations[0].AnalyticsEngineConfiguration;

            //get supported rules
            var supportedRules = await ruleEngine.GetSupportedRulesAsync(analysticConfigurations[0].token);
            if (supportedRules != null)
            {
                if (supportedRules.RuleDescription != null)
                {
                    foreach (var ruleItem in supportedRules.RuleDescription)
                    {
                        Console.WriteLine($"Supported rule is {ruleItem.Name}");
                        if (ruleItem.Parameters != null)
                        {
                            if (ruleItem.Parameters.SimpleItemDescription != null)
                            {
                                foreach (var simpleParamItem in ruleItem.Parameters.SimpleItemDescription)
                                {
                                    Console.WriteLine($"Rule {ruleItem.Name} simple item param name: {simpleParamItem.Name}");
                                    Console.WriteLine($"Rule {ruleItem.Name} simple item param type: {simpleParamItem.Type}");
                                }
                            }

                            if (ruleItem.Parameters.ElementItemDescription != null)
                            {
                                foreach (var elementParamItem in ruleItem.Parameters.ElementItemDescription)
                                {
                                    Console.WriteLine($"Rule {ruleItem.Name} element item param name: {elementParamItem.Name}");
                                    Console.WriteLine($"Rule {ruleItem.Name} element item param type: {elementParamItem.Type}");
                                }
                            }

                            
                        }
                    }
                }
            }

            //get rule engine from token
            var ruleEngineRules = await ruleEngine.GetRulesAsync(analysticConfigurations[0].token);


            if (ruleEngineRules != null && ruleEngineRules.Rule != null)
            {
                //modify existing rule called "MyLineDetector1"
                Config[] modifyRule = new Config[1];

                modifyRule[0] = ruleEngineRules.Rule.Where(x => x.Name == "MyLineDetector1").FirstOrDefault();

                //simple type for the direction. This is magic strings not sure if there is a better way to set this.
                Onvif20Analytics.ItemList modifyRuleItems = new Onvif20Analytics.ItemList();
                Onvif20Analytics.ItemListSimpleItem modifyRuleSimpleItem1 = new Onvif20Analytics.ItemListSimpleItem();
                modifyRuleSimpleItem1.Name = "Direction";
                modifyRuleSimpleItem1.Value = "Right";

                ItemListElementItem itemListElementItem1 = new ItemListElementItem();
                itemListElementItem1.Name = "Segments";

                //This is an int range so should be the type for polyline?
                IntRange xRange = new IntRange();
                xRange.Max = 520;
                xRange.Min = 50;

                IntRange yRange = new IntRange();
                yRange.Max = 520;
                yRange.Min = 50;

                //string to test value. 1000 is the edge of the screen. 
                //This is a line from bottom left to top right.
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml("<Polyline>" +
                    "<Point x=\"0.0\" y=\"0.0\"/>" +
                    "<Point x=\"1000.0\" y=\"1000.0\"/>" +
                    "</Polyline>");
                Console.WriteLine(xmlDoc.DocumentElement.Name);

                itemListElementItem1.Any = xmlDoc.DocumentElement;

                //after creating items set to the list                   
                modifyRuleItems.SimpleItem = new Onvif20Analytics.ItemListSimpleItem[] { modifyRuleSimpleItem1 };
                modifyRuleItems.ElementItem = new ItemListElementItem[] { itemListElementItem1 };

                modifyRule[0].Parameters = modifyRuleItems;

                //modify rule.
                Onvif20Analytics.ModifyRulesResponse ruleUpdateReturned = await ruleEngine.ModifyRulesAsync(profiles.Profiles[0].VideoAnalyticsConfiguration.token, modifyRule);

            }

        }
        catch (Exception ex)
        {

        }
    }

I am not sure how the element items work. They take in a name as a string and then a .Any which is an XMLElement. I am not sure how to generate this or if I am generating the rules correctly.

The specific piece of code I am unsure of in the provided block is:

    ItemListElementItem itemListElementItem1 = new ItemListElementItem();
            itemListElementItem1.Name = "Segments";

            //This is an int range so should be the type for polyline?
            IntRange xRange = new IntRange();
            xRange.Max = 520;
            xRange.Min = 50;

            IntRange yRange = new IntRange();
            yRange.Max = 520;
            yRange.Min = 50;

            //string to test value. 1000 is the edge of the screen. 
            //This is a line from bottom left to top right.
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml("<Polyline>" +
                "<Point x=\"0.0\" y=\"0.0\"/>" +
                "<Point x=\"1000.0\" y=\"1000.0\"/>" +
                "</Polyline>");
            Console.WriteLine(xmlDoc.DocumentElement.Name);

            itemListElementItem1.Any = xmlDoc.DocumentElement;

What I have works but it is hard coded and checking the rule after, it looks subtly different with some tags missing from when I do it within the HIK interface.

Any help would be appreciated.

0 Answers
Related