This is an automated email from the ASF dual-hosted git repository.

gongchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new 0b6fb353f1 [feature]add support for Dahua and Uniview devices (#3214)
0b6fb353f1 is described below

commit 0b6fb353f1a858de1fbe6a1e67d8dfafc8b2ae0f
Author: Logic <[email protected]>
AuthorDate: Mon Apr 7 23:05:29 2025 +0800

    [feature]add support for Dahua and Uniview devices (#3214)
---
 .../collector/collect/http/HttpCollectImpl.java    | 148 ++++++++++--
 .../collect/http/HttpCollectImplTest.java          |  28 +--
 .../collector/dispatch/MetricsCollect.java         |   2 +-
 .../collector/dispatch/DispatchConstants.java      |   4 +
 .../hertzbeat/common/entity/job/Metrics.java       |   5 -
 .../src/main/resources/define/app-dahua.yml        | 247 +++++++++++++++++++++
 .../main/resources/define/app-hikvision_isapi.yml  | 100 +++++----
 .../src/main/resources/define/app-uniview.yml      | 154 +++++++++++++
 home/docs/advanced/extend-http-xmlpath.md          | 138 +++++++++---
 home/docs/help/dahua.md                            |  60 +++++
 home/docs/help/uniview.md                          |  47 ++++
 .../current/advanced/extend-http-xmlpath.md        | 138 +++++++++---
 .../current/help/dahua.md                          |  60 +++++
 .../current/help/uniview.md                        |  47 ++++
 home/sidebars.json                                 |   4 +-
 15 files changed, 1035 insertions(+), 147 deletions(-)

diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImpl.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImpl.java
index 20cee1eb57..5866f36cdb 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImpl.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImpl.java
@@ -91,8 +91,12 @@ import org.xml.sax.InputSource;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-import org.apache.hertzbeat.common.entity.job.Metrics.Field;
-import java.util.function.Function;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * http https collect
@@ -161,6 +165,8 @@ public class HttpCollectImpl extends AbstractCollect {
                             parseResponseBySiteMap(resp, 
metrics.getAliasFields(), builder);
                     case DispatchConstants.PARSE_HEADER ->
                             parseResponseByHeader(builder, 
metrics.getAliasFields(), response);
+                    case DispatchConstants.PARSE_CONFIG ->
+                            parseResponseByConfig(resp, 
metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
                     default ->
                             parseResponseByDefault(resp, 
metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
                 }
@@ -382,9 +388,6 @@ public class HttpCollectImpl extends AbstractCollect {
                 return;
             }
 
-            Map<String, Field> fieldMap = metrics.getFields().stream()
-                    .collect(Collectors.toMap(Field::getField, 
Function.identity(), (field1, field2) -> field1));
-
             for (int i = 0; i < nodeList.getLength(); i++) {
                 Node node = nodeList.item(i);
                 CollectRep.ValueRow.Builder valueRowBuilder = 
CollectRep.ValueRow.newBuilder();
@@ -395,19 +398,11 @@ public class HttpCollectImpl extends AbstractCollect {
                     } else if 
(CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
                         
valueRowBuilder.addColumn(Integer.toString(keywordNum));
                     } else {
-                        Field field = fieldMap.get(alias);
-                        if (field == null || 
!StringUtils.hasText(field.getXpath())) {
-                            log.warn("No field definition or xpath found for 
alias '{}' in XML path parsing.", alias);
-                            
valueRowBuilder.addColumn(CommonConstants.NULL_VALUE);
-                            continue;
-                        }
-
-                        String relativeXpath = field.getXpath();
                         try {
-                            String value = (String) 
xpath.evaluate(relativeXpath, node, XPathConstants.STRING);
+                            String value = (String) xpath.evaluate(alias, 
node, XPathConstants.STRING);
                             
valueRowBuilder.addColumn(StringUtils.hasText(value) ? value : 
CommonConstants.NULL_VALUE);
                         } catch (XPathExpressionException e) {
-                            log.warn("Failed to evaluate relative XPath '{}' 
(from field definition) for node [{}]: {}", relativeXpath, node.getNodeName(), 
e.getMessage());
+                            log.warn("Failed to evaluate XPath '{}' for node 
[{}]: {}", alias, node.getNodeName(), e.getMessage());
                             
valueRowBuilder.addColumn(CommonConstants.NULL_VALUE);
                         }
                     }
@@ -422,6 +417,129 @@ public class HttpCollectImpl extends AbstractCollect {
         }
     }
 
+
+
+    /**
+     * Parses the response body in Properties/Config format.
+     * Two modes are supported:
+     * 1. single-object mode: if http.parseScript is null, aliasFields are 
treated as indicator names.
+     * - If there is a locator in the indicator definition, use the locator as 
the key of the Properties.
+     * - Otherwise, use aliasField (metric name) as the key for Properties.
+     * Generate a single row of data.
+     * 2. array mode: if http.parseScript is not empty (e.g. “users”), treat 
it as an array base path.
+     * Treat aliasFields as the attribute name of an array element, and 
generate a single row of data for each array index. locator is invalid in this 
mode.
+     *
+     * @param resp Response body string
+     * @param aliasFields List of metrics aliases (i.e., the list of fields in 
metrics.fields).
+     * @param http http protocol configuration
+     * @param builder The metrics data builder.
+     * @param responseTime response time
+     */
+    private void parseResponseByConfig(String resp, List<String> aliasFields, 
HttpProtocol http,
+                                       CollectRep.MetricsData.Builder builder, 
Long responseTime) {
+        if (!StringUtils.hasText(resp)) {
+            log.warn("Http collect parse type is config, but response body is 
empty.");
+            builder.setCode(CollectRep.Code.FAIL);
+            builder.setMsg("Response body is empty");
+            return;
+        }
+
+        Properties properties = new Properties();
+        try (StringReader reader = new StringReader(resp)) {
+            properties.load(reader);
+        } catch (IOException e) {
+            log.warn("Failed to parse config response: {}", e.getMessage(), e);
+            builder.setCode(CollectRep.Code.FAIL);
+            builder.setMsg("Failed to parse config response: " + 
e.getMessage());
+            return;
+        }
+        String arrayBasePath = http.getParseScript();
+        int keywordNum = CollectUtil.countMatchKeyword(resp, 
http.getKeyword());
+
+        if (!StringUtils.hasText(arrayBasePath)) {
+            CollectRep.ValueRow.Builder valueRowBuilder = 
CollectRep.ValueRow.newBuilder();
+            for (String alias : aliasFields) {
+                if (NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
+                    valueRowBuilder.addColumn(responseTime.toString());
+                } else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) 
{
+                    valueRowBuilder.addColumn(Integer.toString(keywordNum));
+                } else {
+                    String value = properties.getProperty(alias);
+                    valueRowBuilder.addColumn(value != null ? value : 
CommonConstants.NULL_VALUE);
+                }
+            }
+            CollectRep.ValueRow valueRow = valueRowBuilder.build();
+            if (hasMeaningfulDataInRow(valueRow, aliasFields)) {
+                builder.addValueRow(valueRow);
+            } else {
+                log.warn("No meaningful data found in single config object 
response for aliasFields: {}", aliasFields);
+            }
+        } else {
+            Pattern pattern = Pattern.compile("^" + 
Pattern.quote(arrayBasePath) + "\\[(\\d+)]\\.");
+            Set<Integer> existingIndices = new HashSet<>();
+            for (String key : properties.stringPropertyNames()) {
+                Matcher matcher = pattern.matcher(key);
+                if (matcher.find()) {
+                    try {
+                        int index = Integer.parseInt(matcher.group(1));
+                        existingIndices.add(index);
+                    } catch (NumberFormatException e) {
+                        log.error("Could not parse index from key: {}", key);
+                    }
+                }
+            }
+            if (existingIndices.isEmpty()) {
+                log.warn("Could not find any array elements for base path '{}' 
in config response.", arrayBasePath);
+                return;
+            }
+            List<Integer> sortedIndices = new ArrayList<>(existingIndices);
+            Collections.sort(sortedIndices);
+            for (int i : sortedIndices) {
+                CollectRep.ValueRow.Builder valueRowBuilder = 
CollectRep.ValueRow.newBuilder();
+                for (String alias : aliasFields) {
+                    if 
(NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
+                        valueRowBuilder.addColumn(responseTime.toString());
+                    } else if 
(CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
+                        
valueRowBuilder.addColumn(Integer.toString(keywordNum));
+                    } else {
+                        String currentKey = arrayBasePath + "[" + i + "]." + 
alias;
+                        String value = properties.getProperty(currentKey);
+                        valueRowBuilder.addColumn(value != null ? value : 
CommonConstants.NULL_VALUE);
+                    }
+                }
+                CollectRep.ValueRow valueRow = valueRowBuilder.build();
+                if (hasMeaningfulDataInRow(valueRow, aliasFields)) {
+                    builder.addValueRow(valueRowBuilder.build());
+                }
+            }
+        }
+    }
+
+    private boolean hasMeaningfulDataInRow(CollectRep.ValueRow valueRow, 
List<String> aliasFields) {
+        if (valueRow.getColumnsCount() == 0) {
+            return false;
+        }
+        if (valueRow.getColumnsCount() != aliasFields.size()) {
+            log.error("Column count ({}) mismatch with aliasFields size ({}) 
when checking meaningful data.",
+                    valueRow.getColumnsCount(), aliasFields.size());
+            return false;
+        }
+
+        boolean hasMeaningfulData = false;
+        for (int i = 0; i < valueRow.getColumnsCount(); i++) {
+            String columnValue = valueRow.getColumns(i);
+            String alias = aliasFields.get(i);
+            if (!CommonConstants.NULL_VALUE.equals(columnValue) && 
(!NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias) && 
!CollectorConstants.KEYWORD.equalsIgnoreCase(alias))) {
+                hasMeaningfulData = true;
+                break;
+            }
+            if ((NetworkConstants.RESPONSE_TIME.equalsIgnoreCase(alias) || 
CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) && 
!CommonConstants.NULL_VALUE.equals(columnValue)) {
+                hasMeaningfulData = true;
+            }
+        }
+        return hasMeaningfulData;
+    }
+
     private void parseResponseByJsonPath(String resp, List<String> 
aliasFields, HttpProtocol http,
                                          CollectRep.MetricsData.Builder 
builder, Long responseTime) {
         List<Object> results = JsonPathParser.parseContentWithJsonPath(resp, 
http.getParseScript());
diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImplTest.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImplTest.java
index 9f707bddda..9ec23f5b6e 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImplTest.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/http/HttpCollectImplTest.java
@@ -99,26 +99,26 @@ class HttpCollectImplTest {
                     </server>
                 </root>
                 """;
-
+    
         // Set up HttpProtocol with XML path parsing
         HttpProtocol http = HttpProtocol.builder()
                 .parseType(DispatchConstants.PARSE_XML_PATH)
                 .parseScript("//server")  // XPath to select all server nodes
                 .build();
-
+    
         // Set up Metrics with fields that have XPath expressions
         List<Metrics.Field> fields = new ArrayList<>();
-        
fields.add(Metrics.Field.builder().field("name").xpath("name").build());
-        
fields.add(Metrics.Field.builder().field("status").xpath("status").build());
-        
fields.add(Metrics.Field.builder().field("cpu").xpath("metrics/cpu").build());
-        
fields.add(Metrics.Field.builder().field("memory").xpath("metrics/memory").build());
-
+        fields.add(Metrics.Field.builder().field("name").build());
+        fields.add(Metrics.Field.builder().field("status").build());
+        fields.add(Metrics.Field.builder().field("metrics/cpu").build());
+        fields.add(Metrics.Field.builder().field("metrics/memory").build());
+    
         Metrics metrics = Metrics.builder()
                 .http(http)
                 .fields(fields)
-                .aliasFields(Arrays.asList("name", "status", "cpu", "memory"))
+                .aliasFields(Arrays.asList("name", "status", "metrics/cpu", 
"metrics/memory"))
                 .build();
-
+    
         // Create a custom builder that captures added rows
         List<CollectRep.ValueRow> capturedRows = new ArrayList<>();
         CollectRep.MetricsData.Builder builder = new 
CollectRep.MetricsData.Builder() {
@@ -128,7 +128,7 @@ class HttpCollectImplTest {
                 return super.addValueRow(valueRow);
             }
         };
-
+    
         // Use reflection to access the private parseResponseByXmlPath method
         Method parseMethod = HttpCollectImpl.class.getDeclaredMethod(
                 "parseResponseByXmlPath", 
@@ -137,13 +137,13 @@ class HttpCollectImplTest {
                 CollectRep.MetricsData.Builder.class, 
                 Long.class);
         parseMethod.setAccessible(true);
-
+    
         // Call the method
         parseMethod.invoke(httpCollectImpl, xmlResponse, metrics, builder, 
100L);
-
+    
         // Verify the results
         assertEquals(2, capturedRows.size(), "Should have parsed 2 server 
nodes");
-
+    
         // Check first server
         CollectRep.ValueRow firstRow = capturedRows.get(0);
         assertEquals(4, firstRow.getColumnsCount(), "First row should have 4 
columns");
@@ -151,7 +151,7 @@ class HttpCollectImplTest {
         assertEquals("Running", firstRow.getColumns(1), "First server status 
should be Running");
         assertEquals("75.5", firstRow.getColumns(2), "First server CPU should 
be 75.5");
         assertEquals("1024", firstRow.getColumns(3), "First server memory 
should be 1024");
-
+    
         // Check second server
         CollectRep.ValueRow secondRow = capturedRows.get(1);
         assertEquals(4, secondRow.getColumnsCount(), "Second row should have 4 
columns");
diff --git 
a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
 
b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
index 811fbac3f6..254af29710 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
@@ -302,7 +302,7 @@ public class MetricsCollect implements Runnable, 
Comparable<MetricsCollect> {
                             value = String.valueOf(objValue);
                         }
                     } catch (Exception e) {
-                        log.info("[calculates execute warning] {}.", 
e.getMessage());
+                        log.warn("[calculates execute warning, use original 
value.] {}", e.getMessage());
                         value = 
Optional.ofNullable(fieldValueMap.get(expression.getSourceText()))
                                 .map(String::valueOf)
                                 .orElse(null);
diff --git 
a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java
 
b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java
index e2da8d63ac..eea60acebf 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/DispatchConstants.java
@@ -202,6 +202,10 @@ public interface DispatchConstants {
      * Parsing method prometheus exporter data
      */
     String PARSE_PROMETHEUS = "prometheus";
+    /**
+     * Parse response body as config/properties format
+     */
+    String PARSE_CONFIG = "config";
     /**
      * prometheus accept header
      */
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java
index 73c48bee47..e56bbf93b6 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Metrics.java
@@ -377,10 +377,5 @@ public class Metrics {
          * Metric unit
          */
         private String unit;
-
-        /**
-         * when parse type is xmlParse, use it, like 
NetPortStatusList/NetPortStatus[id='1']/workSpeed
-         */
-        private String xpath;
     }
 }
diff --git a/hertzbeat-manager/src/main/resources/define/app-dahua.yml 
b/hertzbeat-manager/src/main/resources/define/app-dahua.yml
new file mode 100644
index 0000000000..dfba23f9cf
--- /dev/null
+++ b/hertzbeat-manager/src/main/resources/define/app-dahua.yml
@@ -0,0 +1,247 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The monitoring type category:service-application service monitoring 
db-database monitoring custom-custom monitoring os-operating system monitoring
+category: server
+# The monitoring type eg: linux windows tomcat mysql aws...
+app: dahua
+# The monitoring i18n name
+name:
+  zh-CN: 大华
+  en-US: Dahua
+# The description and help of this monitoring type
+help:
+  zh-CN: 通过http接口监控大华设备状态,获取设备健康数据。
+  en-US: Monitor Dahua devices through http interface to collect health data.
+
+# Input params define for monitoring(render web ui by the definition)
+params:
+  - field: host
+    name:
+      zh-CN: 主机Host
+      en-US: Host
+    type: host
+    required: true
+  - field: port
+    name:
+      zh-CN: 端口
+      en-US: Port
+    type: number
+    range: '[0,65535]'
+    required: true
+    defaultValue: 80
+  - field: timeout
+    name:
+      zh-CN: 超时时间(ms)
+      en-US: Timeout(ms)
+    type: number
+    range: '[1000,60000]'
+    required: true
+    defaultValue: 5000
+  - field: username
+    name:
+      zh-CN: 用户名
+      en-US: Username
+    type: text
+    required: true
+  - field: password
+    name:
+      zh-CN: 密码
+      en-US: Password
+    type: password
+    required: true
+  - field: ssl
+    name:
+      zh-CN: 启用HTTPS
+      en-US: SSL
+    type: boolean
+    required: false
+    defaultValue: false
+
+# collect metrics config list
+metrics:
+  - name: network_info # 指标集合名称
+    i18n:
+      zh-CN: 网络信息
+      en-US: Network Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /cgi-bin/configManager.cgi?action=getConfig&name=Network
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: config
+    fields:
+      - field: default_interface
+        type: 1
+        i18n:
+          zh-CN: 默认网卡
+          en-US: Default Interface
+      - field: domain_name
+        type: 1
+        i18n:
+          zh-CN: 域名
+          en-US: Domain Name
+      - field: hostname
+        type: 1
+        i18n:
+          zh-CN: 主机名
+          en-US: Hostname
+      - field: eth0_ip_address
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 IP地址
+          en-US: Interface eth0 IP Address
+      - field: eth0_gateway
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 默认网关
+          en-US: Interface eth0 Default Gateway
+      - field: eth0_mac_address
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 物理地址
+          en-US: Interface eth0 Physical Address
+      - field: eth0_subnet_mask
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 子网掩码
+          en-US: Interface eth0 Subnet Mask
+      - field: eth0_mtu
+        type: 0
+        i18n:
+          zh-CN: 网卡 eth0 MTU
+          en-US: Interface eth0 MTU
+      - field: eth0_dns1
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 DNS服务器1
+          en-US: Interface eth0 DNS Server 1
+      - field: eth0_dns2
+        type: 1
+        i18n:
+          zh-CN: 网卡 eth0 DNS服务器2
+          en-US: Interface eth0 DNS Server 2
+    aliasFields:
+      - table.Network.DefaultInterface
+      - table.Network.Domain
+      - table.Network.Hostname
+      - table.Network.eth0.IPAddress
+      - table.Network.eth0.DefaultGateway
+      - table.Network.eth0.PhysicalAddress
+      - table.Network.eth0.SubnetMask
+      - table.Network.eth0.MTU
+      - table.Network.eth0.DnsServers[0]
+      - table.Network.eth0.DnsServers[1]
+    calculates:
+      - default_interface=table.Network.DefaultInterface
+      - domain_name=table.Network.Domain
+      - hostname=table.Network.Hostname
+      - eth0_ip_address=table.Network.eth0.IPAddress
+      - eth0_gateway=table.Network.eth0.DefaultGateway
+      - eth0_mac_address=table.Network.eth0.PhysicalAddress
+      - eth0_subnet_mask=table.Network.eth0.SubnetMask
+      - eth0_mtu=table.Network.eth0.MTU
+      - eth0_dns1=table.Network.eth0.DnsServers[0]
+      - eth0_dns2=table.Network.eth0.DnsServers[1]
+  - name: user_info
+    i18n:
+      zh-CN: 用户信息
+      en-US: User Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /cgi-bin/userManager.cgi?action=getActiveUserInfoAll
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: config
+      parseScript: users
+    fields:
+      - field: ClientAddress
+        type: 1
+        i18n:
+          zh-CN: 客户端地址
+          en-US: ClientAddress
+      - field: Name
+        type: 1
+        i18n:
+          zh-CN: 客户端用户
+          en-US: Name
+      - field: ClientType
+        type: 1
+        i18n:
+          zh-CN: 客户端登录类型
+          en-US: ClientType
+      - field: LoginTime
+        type: 1
+        i18n:
+          zh-CN: 客户端登录时间
+          en-US: LoginTime
+  - name: ntp_info
+    i18n:
+      zh-CN: 校时信息
+      en-US: Ntp Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /cgi-bin/configManager.cgi?action=getConfig&name=NTP
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: config
+    fields:
+      - field: ntp_address
+        type: 1
+        i18n:
+          zh-CN: 校时服务器
+          en-US: Ntp Address
+      - field: ntp_port
+        type: 1
+        i18n:
+          zh-CN: 校时端口
+          en-US: Ntp Port
+      - field: ntp_update_period
+        type: 1
+        i18n:
+          zh-CN: 校时间隔
+          en-US: Ntp Update Period
+    aliasFields:
+      - table.NTP.Address
+      - table.NTP.Port
+      - table.NTP.UpdatePeriod
+    calculates:
+      - ntp_address=table.NTP.Address
+      - ntp_port=table.NTP.Port
+      - ntp_update_period=table.NTP.UpdatePeriod
\ No newline at end of file
diff --git 
a/hertzbeat-manager/src/main/resources/define/app-hikvision_isapi.yml 
b/hertzbeat-manager/src/main/resources/define/app-hikvision_isapi.yml
index b20eaa4da0..76987a3814 100644
--- a/hertzbeat-manager/src/main/resources/define/app-hikvision_isapi.yml
+++ b/hertzbeat-manager/src/main/resources/define/app-hikvision_isapi.yml
@@ -90,39 +90,38 @@ metrics:
         digestAuthUsername: ^_^username^_^
         digestAuthPassword: ^_^password^_^
       parseType: xmlPath
-      parseScript: 'DeviceInfo'
+      parseScript: //DeviceInfo
     fields:
       - field: deviceName
         type: 1
         i18n:
           zh-CN: 设备名称
           en-US: Device Name
-        xpath: deviceName
       - field: deviceID
         type: 1
         i18n:
           zh-CN: 设备ID
           en-US: Device ID
-        xpath: deviceID
       - field: firmwareVersion
         type: 1
         i18n:
           zh-CN: 固件版本
           en-US: Firmware Version
-        xpath: firmwareVersion
       - field: model
         type: 1
         i18n:
           zh-CN: 设备型号
           en-US: Device Model
-        xpath: model
       - field: macAddress
         type: 1
         i18n:
           zh-CN: mac地址
           en-US: Mac Address
-        xpath: macAddress
   - name: status
+    i18n:
+      zh-CN: 设备状态
+      en-US: Status
+    priority: 0
     protocol: http
     http:
       host: ^_^host^_^
@@ -136,115 +135,134 @@ metrics:
         digestAuthUsername: ^_^username^_^
         digestAuthPassword: ^_^password^_^
       parseType: xmlPath
-      parseScript: 'DeviceStatus'
+      parseScript: //DeviceStatus
     fields:
-      - field: cpuUtilization
+      - field: CPU_utilization
         i18n:
           zh-CN: CPU 利用率
           en-US: CPU Utilization
         type: 0
         unit: '%'
-        xpath: CPUList/CPU/cpuUtilization
-      - field: memoryUsage
+      - field: memory_usage
         i18n:
           zh-CN: 内存使用量
           en-US: Memory Usage
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryUsage
-      - field: memoryAvailable
+      - field: memory_available
         i18n:
           zh-CN: 可用内存
           en-US: Memory Available
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryAvailable
-      - field: cacheSize
+      - field: cache_size
         i18n:
           zh-CN: 缓存大小
           en-US: Cache Size
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/cacheSize
-      - field: netPort1Speed
+      - field: net_port_1_speed
         i18n:
           zh-CN: 网口1速度
           en-US: Net Port 1 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='1']/workSpeed
-      - field: netPort2Speed
+      - field: net_port_2_speed
         i18n:
           zh-CN: 网口2速度
           en-US: Net Port 2 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='2']/workSpeed
-      - field: bootTime
+      - field: boot_time
         i18n:
           zh-CN: 启动时间
           en-US: Boot Time
         type: 1
-        xpath: bootTime
-      - field: deviceUpTime
+      - field: device_uptime
         i18n:
           zh-CN: 运行时长
           en-US: Device Uptime
         type: 1
-        xpath: deviceUpTime
-      - field: lastCalibrationTime
+      - field: last_calibration_time
         i18n:
           zh-CN: 上次校时时间
           en-US: Last Calibration Time
         type: 1
-        xpath: lastCalibrationTime
-      - field: lastCalibrationTimeDiff
+      - field: last_calibration_time_diff
         i18n:
           zh-CN: 上次校时时间差
           en-US: Last Calibration Time Diff
         type: 0
         unit: s
-        xpath: lastCalibrationTimeDiff
-      - field: avgUploadTime
+      - field: avg_upload_time
         i18n:
           zh-CN: 平均上传耗时
           en-US: Avg Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/avgTime
-      - field: maxUploadTime
+      - field: max_upload_time
         i18n:
           zh-CN: 最大上传耗时
           en-US: Max Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/maxTime
-      - field: minUploadTime
+      - field: min_upload_time
         i18n:
           zh-CN: 最小上传耗时
           en-US: Min Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/minTime
-      - field: lastCalibrationMode
+      - field: last_calibration_mode
         i18n:
           zh-CN: 上次校时模式
           en-US: Last Calibration Mode
         type: 1
-        xpath: lastCalibrationTimeMode
-      - field: lastCalibrationAddress
+      - field: last_calibration_address
         i18n:
           zh-CN: 上次校时地址
           en-US: Last Calibration Address
         type: 1
-        xpath: lastCalibrationTimeAddress
-      - field: responseTime
+      - field: response_time
         i18n:
           zh-CN: 响应时间
           en-US: Response Time
         type: 0
         unit: ms
+    aliasFields:
+      - CPUList/CPU/cpuUtilization
+      - MemoryList/Memory/memoryUsage
+      - MemoryList/Memory/memoryAvailable
+      - MemoryList/Memory/cacheSize
+      - NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - bootTime
+      - deviceUpTime
+      - lastCalibrationTime
+      - lastCalibrationTimeDiff
+      - uploadTimeConsumingList/avgTime
+      - uploadTimeConsumingList/maxTime
+      - uploadTimeConsumingList/minTime
+      - lastCalibrationTimeMode
+      - lastCalibrationTimeAddress
+      - responseTime
+    calculates:
+      - CPU_utilization=CPUList/CPU/cpuUtilization
+      - memory_usage=MemoryList/Memory/memoryUsage
+      - memory_available=MemoryList/Memory/memoryAvailable
+      - cache_size=MemoryList/Memory/cacheSize
+      - net_port_1_speed=NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - net_port_2_speed=NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - boot_time=bootTime
+      - device_uptime=deviceUpTime
+      - last_calibration_time=lastCalibrationTime
+      - last_calibration_time_diff=lastCalibrationTimeDiff
+      - avg_upload_time=uploadTimeConsumingList/avgTime
+      - max_upload_time=uploadTimeConsumingList/maxTime
+      - min_upload_time=uploadTimeConsumingList/minTime
+      - last_calibration_mode=lastCalibrationTimeMode
+      - last_calibration_address=lastCalibrationTimeAddress
+      - response_time=responseTime
     units:
-      - memoryUsage=KB->MB
-      - memoryAvailable=KB->MB
-      - cacheSize=KB->MB
\ No newline at end of file
+      - memory_usage=KB->MB
+      - memory_available=KB->MB
+      - cache_size=KB->MB
\ No newline at end of file
diff --git a/hertzbeat-manager/src/main/resources/define/app-uniview.yml 
b/hertzbeat-manager/src/main/resources/define/app-uniview.yml
new file mode 100644
index 0000000000..2fb818fe81
--- /dev/null
+++ b/hertzbeat-manager/src/main/resources/define/app-uniview.yml
@@ -0,0 +1,154 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The monitoring type category:service-application service monitoring 
db-database monitoring custom-custom monitoring os-operating system monitoring
+category: server
+# The monitoring type eg: linux windows tomcat mysql aws...
+app: uniview
+# The monitoring i18n name
+name:
+  zh-CN: 宇视
+  en-US: Uniview
+# The description and help of this monitoring type
+help:
+  zh-CN: 通过HTTP接口监控宇视设备状态,获取设备健康数据。
+  en-US: Monitor Uniview devices through HTTP interface to collect health data.
+
+# Input params define for monitoring(render web ui by the definition)
+params:
+  - field: host
+    name:
+      zh-CN: 主机Host
+      en-US: Host
+    type: host
+    required: true
+  - field: port
+    name:
+      zh-CN: 端口
+      en-US: Port
+    type: number
+    range: '[0,65535]'
+    required: true
+    defaultValue: 80
+  - field: timeout
+    name:
+      zh-CN: 超时时间(ms)
+      en-US: Timeout(ms)
+    type: number
+    range: '[1000,60000]'
+    required: true
+    defaultValue: 5000
+  - field: username
+    name:
+      zh-CN: 用户名
+      en-US: Username
+    type: text
+    required: true
+  - field: password
+    name:
+      zh-CN: 密码
+      en-US: Password
+    type: password
+    required: true
+  - field: ssl
+    name:
+      zh-CN: 启用HTTPS
+      en-US: SSL
+    type: boolean
+    required: false
+    defaultValue: false
+
+# collect metrics config list
+metrics:
+  - name: system_info
+    i18n:
+      zh-CN: 系统信息
+      en-US: System Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /LAPI/V1.0/System/DeviceInfo
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: jsonPath
+      parseScript: '$.Response.Data'
+    fields:
+      - field: DeviceName
+        type: 1
+        i18n:
+          zh-CN: 设备名称
+          en-US: Device Name
+      - field: SerialNumber
+        type: 1
+        i18n:
+          zh-CN: 序列号
+          en-US: SerialNumber
+      - field: FirmwareVersion
+        type: 1
+        i18n:
+          zh-CN: 固件版本
+          en-US: Firmware Version
+      - field: DeviceModel
+        type: 1
+        i18n:
+          zh-CN: 设备型号
+          en-US: Device Model
+  - name: ntp_info
+    i18n:
+      zh-CN: 校时信息
+      en-US: NTP Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /LAPI/V1.0/System/Time/NTP
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: jsonPath
+      parseScript: '$.Response.Data.NTPServerInfos[0]'
+    fields:
+      - field: IPAddress
+        type: 1
+        i18n:
+          zh-CN: IP地址
+          en-US: IPAddress
+      - field: Port
+        type: 1
+        i18n:
+          zh-CN: 端口号
+          en-US: Port
+      - field: SynchronizeInterval
+        type: 1
+        i18n:
+          zh-CN: 同步间隔
+          en-US: SynchronizeInterval
+      - field: Enabled
+        type: 1
+        i18n:
+          zh-CN: 是否启用
+          en-US: Enabled
\ No newline at end of file
diff --git a/home/docs/advanced/extend-http-xmlpath.md 
b/home/docs/advanced/extend-http-xmlpath.md
index 2b95061dce..fd1692ec89 100644
--- a/home/docs/advanced/extend-http-xmlpath.md
+++ b/home/docs/advanced/extend-http-xmlpath.md
@@ -130,7 +130,56 @@ params:
 
 # collect metrics config list
 metrics:
+  - name: system_info
+    i18n:
+      zh-CN: 系统信息
+      en-US: System Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /ISAPI/System/deviceInfo
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: xmlPath
+      parseScript: //DeviceInfo
+    fields:
+      - field: deviceName
+        type: 1
+        i18n:
+          zh-CN: 设备名称
+          en-US: Device Name
+      - field: deviceID
+        type: 1
+        i18n:
+          zh-CN: 设备ID
+          en-US: Device ID
+      - field: firmwareVersion
+        type: 1
+        i18n:
+          zh-CN: 固件版本
+          en-US: Firmware Version
+      - field: model
+        type: 1
+        i18n:
+          zh-CN: 设备型号
+          en-US: Device Model
+      - field: macAddress
+        type: 1
+        i18n:
+          zh-CN: mac地址
+          en-US: Mac Address
   - name: status
+    i18n:
+      zh-CN: 设备状态
+      en-US: Status
+    priority: 0
     protocol: http
     http:
       host: ^_^host^_^
@@ -144,115 +193,134 @@ metrics:
         digestAuthUsername: ^_^username^_^
         digestAuthPassword: ^_^password^_^
       parseType: xmlPath
-      parseScript: 'DeviceStatus'
+      parseScript: //DeviceStatus
     fields:
-      - field: cpuUtilization
+      - field: CPU_utilization
         i18n:
           zh-CN: CPU 利用率
           en-US: CPU Utilization
         type: 0
         unit: '%'
-        xpath: CPUList/CPU/cpuUtilization
-      - field: memoryUsage
+      - field: memory_usage
         i18n:
           zh-CN: 内存使用量
           en-US: Memory Usage
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryUsage
-      - field: memoryAvailable
+      - field: memory_available
         i18n:
           zh-CN: 可用内存
           en-US: Memory Available
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryAvailable
-      - field: cacheSize
+      - field: cache_size
         i18n:
           zh-CN: 缓存大小
           en-US: Cache Size
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/cacheSize
-      - field: netPort1Speed
+      - field: net_port_1_speed
         i18n:
           zh-CN: 网口1速度
           en-US: Net Port 1 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='1']/workSpeed
-      - field: netPort2Speed
+      - field: net_port_2_speed
         i18n:
           zh-CN: 网口2速度
           en-US: Net Port 2 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='2']/workSpeed
-      - field: bootTime
+      - field: boot_time
         i18n:
           zh-CN: 启动时间
           en-US: Boot Time
         type: 1
-        xpath: bootTime
-      - field: deviceUpTime
+      - field: device_uptime
         i18n:
           zh-CN: 运行时长
           en-US: Device Uptime
         type: 1
-        xpath: deviceUpTime
-      - field: lastCalibrationTime
+      - field: last_calibration_time
         i18n:
           zh-CN: 上次校时时间
           en-US: Last Calibration Time
         type: 1
-        xpath: lastCalibrationTime
-      - field: lastCalibrationTimeDiff
+      - field: last_calibration_time_diff
         i18n:
           zh-CN: 上次校时时间差
           en-US: Last Calibration Time Diff
         type: 0
         unit: s
-        xpath: lastCalibrationTimeDiff
-      - field: avgUploadTime
+      - field: avg_upload_time
         i18n:
           zh-CN: 平均上传耗时
           en-US: Avg Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/avgTime
-      - field: maxUploadTime
+      - field: max_upload_time
         i18n:
           zh-CN: 最大上传耗时
           en-US: Max Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/maxTime
-      - field: minUploadTime
+      - field: min_upload_time
         i18n:
           zh-CN: 最小上传耗时
           en-US: Min Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/minTime
-      - field: lastCalibrationMode
+      - field: last_calibration_mode
         i18n:
           zh-CN: 上次校时模式
           en-US: Last Calibration Mode
         type: 1
-        xpath: lastCalibrationTimeMode
-      - field: lastCalibrationAddress
+      - field: last_calibration_address
         i18n:
           zh-CN: 上次校时地址
           en-US: Last Calibration Address
         type: 1
-        xpath: lastCalibrationTimeAddress
-      - field: responseTime
+      - field: response_time
         i18n:
           zh-CN: 响应时间
           en-US: Response Time
         type: 0
         unit: ms
+    aliasFields:
+      - CPUList/CPU/cpuUtilization
+      - MemoryList/Memory/memoryUsage
+      - MemoryList/Memory/memoryAvailable
+      - MemoryList/Memory/cacheSize
+      - NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - bootTime
+      - deviceUpTime
+      - lastCalibrationTime
+      - lastCalibrationTimeDiff
+      - uploadTimeConsumingList/avgTime
+      - uploadTimeConsumingList/maxTime
+      - uploadTimeConsumingList/minTime
+      - lastCalibrationTimeMode
+      - lastCalibrationTimeAddress
+      - responseTime
+    calculates:
+      - CPU_utilization=CPUList/CPU/cpuUtilization
+      - memory_usage=MemoryList/Memory/memoryUsage
+      - memory_available=MemoryList/Memory/memoryAvailable
+      - cache_size=MemoryList/Memory/cacheSize
+      - net_port_1_speed=NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - net_port_2_speed=NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - boot_time=bootTime
+      - device_uptime=deviceUpTime
+      - last_calibration_time=lastCalibrationTime
+      - last_calibration_time_diff=lastCalibrationTimeDiff
+      - avg_upload_time=uploadTimeConsumingList/avgTime
+      - max_upload_time=uploadTimeConsumingList/maxTime
+      - min_upload_time=uploadTimeConsumingList/minTime
+      - last_calibration_mode=lastCalibrationTimeMode
+      - last_calibration_address=lastCalibrationTimeAddress
+      - response_time=responseTime
     units:
-      - memoryUsage=KB->MB
-      - memoryAvailable=KB->MB
-      - cacheSize=KB->MB
+      - memory_usage=KB->MB
+      - memory_available=KB->MB
+      - cache_size=KB->MB
diff --git a/home/docs/help/dahua.md b/home/docs/help/dahua.md
new file mode 100644
index 0000000000..82707663a1
--- /dev/null
+++ b/home/docs/help/dahua.md
@@ -0,0 +1,60 @@
+---
+id: dahua
+title: Monitor Dahua Devices
+sidebar_label: Dahua
+keywords: [ monitor, dahua ]
+---
+
+> Monitor Dahua devices through HTTP interface to collect health data.
+
+## Configuration
+
+| Parameter | Description |
+| ----------- | ----------- |
+| Host | Target IP/Domain |
+| Name | Unique monitor name |
+| Port | Network port (default 80) |
+| Timeout | Request timeout in ms |
+| Username | Device username |
+| Password | Device password |
+| SSL | Enable HTTPS |
+| Interval | Collection interval (≥30s) |
+
+## Metrics
+
+### Network Info
+
+- Default Interface
+- Domain Name
+- Hostname
+- eth0 IP Address
+- eth0 Gateway  
+- eth0 MAC
+- eth0 Subnet Mask
+- eth0 MTU
+- DNS Servers
+
+### User Info
+
+- Client Address
+- Username
+- Login Type
+- Login Time
+
+### NTP Info
+
+- NTP Server
+- NTP Port
+- Sync Interval
+
+## Implementation
+
+Access device APIs via:
+
+1. Network: `/cgi-bin/configManager.cgi?action=getConfig&name=Network`
+
+2. Users: `/cgi-bin/userManager.cgi?action=getActiveUserInfoAll`
+
+3. NTP: `/cgi-bin/configManager.cgi?action=getConfig&name=NTP`
+
+Using Digest Auth and parsing config format responses.
diff --git a/home/docs/help/uniview.md b/home/docs/help/uniview.md
new file mode 100644
index 0000000000..70a094db98
--- /dev/null
+++ b/home/docs/help/uniview.md
@@ -0,0 +1,47 @@
+---
+id: uniview
+title: Monitor Uniview Devices
+sidebar_label: Uniview 
+keywords: [ monitor, uniview ]
+---
+
+> Monitor Uniview devices through HTTP interface.
+
+## Configuration
+
+| Parameter | Description |
+| ----------- | ----------- |
+| Host | Device IP/Domain |
+| Name | Unique identifier |
+| Port | Default 80 |
+| Timeout | Milliseconds |
+| Username | Auth username |
+| Password | Auth password |
+| SSL | HTTPS Enable |
+| Interval | ≥30 seconds |
+
+## Metrics
+
+### System Info
+
+- Device Name
+- Serial Number
+- Firmware Version
+- Device Model
+
+### NTP Info
+
+- NTP Server IP
+- NTP Port
+- Sync Interval
+- NTP Status
+
+## Implementation
+
+Access device APIs:
+
+1. System: `/LAPI/V1.0/System/DeviceInfo`
+
+2. NTP: `/LAPI/V1.0/System/Time/NTP`
+
+Using Digest Authentication and parsing JSON responses.
diff --git 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/advanced/extend-http-xmlpath.md
 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/advanced/extend-http-xmlpath.md
index 311cf73d00..f66f6128a5 100644
--- 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/advanced/extend-http-xmlpath.md
+++ 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/advanced/extend-http-xmlpath.md
@@ -130,7 +130,56 @@ params:
 
 # collect metrics config list
 metrics:
+  - name: system_info
+    i18n:
+      zh-CN: 系统信息
+      en-US: System Info
+    priority: 0
+    protocol: http
+    http:
+      host: ^_^host^_^
+      port: ^_^port^_^
+      ssl: ^_^ssl^_^
+      url: /ISAPI/System/deviceInfo
+      method: GET
+      timeout: ^_^timeout^_^
+      authorization:
+        type: Digest Auth
+        digestAuthUsername: ^_^username^_^
+        digestAuthPassword: ^_^password^_^
+      parseType: xmlPath
+      parseScript: //DeviceInfo
+    fields:
+      - field: deviceName
+        type: 1
+        i18n:
+          zh-CN: 设备名称
+          en-US: Device Name
+      - field: deviceID
+        type: 1
+        i18n:
+          zh-CN: 设备ID
+          en-US: Device ID
+      - field: firmwareVersion
+        type: 1
+        i18n:
+          zh-CN: 固件版本
+          en-US: Firmware Version
+      - field: model
+        type: 1
+        i18n:
+          zh-CN: 设备型号
+          en-US: Device Model
+      - field: macAddress
+        type: 1
+        i18n:
+          zh-CN: mac地址
+          en-US: Mac Address
   - name: status
+    i18n:
+      zh-CN: 设备状态
+      en-US: Status
+    priority: 0
     protocol: http
     http:
       host: ^_^host^_^
@@ -144,115 +193,134 @@ metrics:
         digestAuthUsername: ^_^username^_^
         digestAuthPassword: ^_^password^_^
       parseType: xmlPath
-      parseScript: 'DeviceStatus'
+      parseScript: //DeviceStatus
     fields:
-      - field: cpuUtilization
+      - field: CPU_utilization
         i18n:
           zh-CN: CPU 利用率
           en-US: CPU Utilization
         type: 0
         unit: '%'
-        xpath: CPUList/CPU/cpuUtilization
-      - field: memoryUsage
+      - field: memory_usage
         i18n:
           zh-CN: 内存使用量
           en-US: Memory Usage
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryUsage
-      - field: memoryAvailable
+      - field: memory_available
         i18n:
           zh-CN: 可用内存
           en-US: Memory Available
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/memoryAvailable
-      - field: cacheSize
+      - field: cache_size
         i18n:
           zh-CN: 缓存大小
           en-US: Cache Size
         type: 0
         unit: MB
-        xpath: MemoryList/Memory/cacheSize
-      - field: netPort1Speed
+      - field: net_port_1_speed
         i18n:
           zh-CN: 网口1速度
           en-US: Net Port 1 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='1']/workSpeed
-      - field: netPort2Speed
+      - field: net_port_2_speed
         i18n:
           zh-CN: 网口2速度
           en-US: Net Port 2 Speed
         type: 0
         unit: Mbps
-        xpath: NetPortStatusList/NetPortStatus[id='2']/workSpeed
-      - field: bootTime
+      - field: boot_time
         i18n:
           zh-CN: 启动时间
           en-US: Boot Time
         type: 1
-        xpath: bootTime
-      - field: deviceUpTime
+      - field: device_uptime
         i18n:
           zh-CN: 运行时长
           en-US: Device Uptime
         type: 1
-        xpath: deviceUpTime
-      - field: lastCalibrationTime
+      - field: last_calibration_time
         i18n:
           zh-CN: 上次校时时间
           en-US: Last Calibration Time
         type: 1
-        xpath: lastCalibrationTime
-      - field: lastCalibrationTimeDiff
+      - field: last_calibration_time_diff
         i18n:
           zh-CN: 上次校时时间差
           en-US: Last Calibration Time Diff
         type: 0
         unit: s
-        xpath: lastCalibrationTimeDiff
-      - field: avgUploadTime
+      - field: avg_upload_time
         i18n:
           zh-CN: 平均上传耗时
           en-US: Avg Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/avgTime
-      - field: maxUploadTime
+      - field: max_upload_time
         i18n:
           zh-CN: 最大上传耗时
           en-US: Max Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/maxTime
-      - field: minUploadTime
+      - field: min_upload_time
         i18n:
           zh-CN: 最小上传耗时
           en-US: Min Upload Time
         type: 0
         unit: ms
-        xpath: uploadTimeConsumingList/minTime
-      - field: lastCalibrationMode
+      - field: last_calibration_mode
         i18n:
           zh-CN: 上次校时模式
           en-US: Last Calibration Mode
         type: 1
-        xpath: lastCalibrationTimeMode
-      - field: lastCalibrationAddress
+      - field: last_calibration_address
         i18n:
           zh-CN: 上次校时地址
           en-US: Last Calibration Address
         type: 1
-        xpath: lastCalibrationTimeAddress
-      - field: responseTime
+      - field: response_time
         i18n:
           zh-CN: 响应时间
           en-US: Response Time
         type: 0
         unit: ms
+    aliasFields:
+      - CPUList/CPU/cpuUtilization
+      - MemoryList/Memory/memoryUsage
+      - MemoryList/Memory/memoryAvailable
+      - MemoryList/Memory/cacheSize
+      - NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - bootTime
+      - deviceUpTime
+      - lastCalibrationTime
+      - lastCalibrationTimeDiff
+      - uploadTimeConsumingList/avgTime
+      - uploadTimeConsumingList/maxTime
+      - uploadTimeConsumingList/minTime
+      - lastCalibrationTimeMode
+      - lastCalibrationTimeAddress
+      - responseTime
+    calculates:
+      - CPU_utilization=CPUList/CPU/cpuUtilization
+      - memory_usage=MemoryList/Memory/memoryUsage
+      - memory_available=MemoryList/Memory/memoryAvailable
+      - cache_size=MemoryList/Memory/cacheSize
+      - net_port_1_speed=NetPortStatusList/NetPortStatus[id='1']/workSpeed
+      - net_port_2_speed=NetPortStatusList/NetPortStatus[id='2']/workSpeed
+      - boot_time=bootTime
+      - device_uptime=deviceUpTime
+      - last_calibration_time=lastCalibrationTime
+      - last_calibration_time_diff=lastCalibrationTimeDiff
+      - avg_upload_time=uploadTimeConsumingList/avgTime
+      - max_upload_time=uploadTimeConsumingList/maxTime
+      - min_upload_time=uploadTimeConsumingList/minTime
+      - last_calibration_mode=lastCalibrationTimeMode
+      - last_calibration_address=lastCalibrationTimeAddress
+      - response_time=responseTime
     units:
-      - memoryUsage=KB->MB
-      - memoryAvailable=KB->MB
-      - cacheSize=KB->MB
+      - memory_usage=KB->MB
+      - memory_available=KB->MB
+      - cache_size=KB->MB
diff --git 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/dahua.md 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/dahua.md
new file mode 100644
index 0000000000..d9452d3da3
--- /dev/null
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/dahua.md
@@ -0,0 +1,60 @@
+---
+id: dahua
+title: 监控 大华设备
+sidebar_label: 大华
+keywords: [ monitor, dahua, 大华 ]
+---
+
+> 通过HTTP接口监控大华设备状态,获取设备健康数据。
+
+## 监控配置参数
+
+| 参数名称      | 参数帮助描述 |
+| ----------- | ----------- |
+| 监控Host     | 被监控的对端IP或域名 |
+| 监控名称     | 标识此监控的唯一名称 |
+| 端口        | 网络请求端口,默认80 |
+| 超时时间 | 请求超时时间,单位毫秒 |
+| 用户名      | 设备登录用户名 |
+| 密码        | 设备登录密码 |
+| 启用HTTPS   | 是否启用HTTPS协议 |
+| 采集间隔    | 数据采集周期(≥30秒) |
+
+## 采集指标
+
+### 网络信息
+
+- 默认网卡
+- 域名
+- 主机名
+- 网卡 eth0 IP地址
+- 网卡 eth0 默认网关
+- 网卡 eth0 物理地址
+- 网卡 eth0 子网掩码
+- 网卡 eth0 MTU
+- DNS服务器1/2
+
+### 用户信息
+
+- 客户端地址
+- 客户端用户
+- 客户端登录类型
+- 客户端登录时间
+
+### 校时信息
+
+- 校时服务器
+- 校时端口
+- 校时间隔
+
+## 实现原理
+
+通过大华设备HTTP接口获取数据:
+
+1. 网络信息:`/cgi-bin/configManager.cgi?action=getConfig&name=Network`
+
+2. 用户信息:`/cgi-bin/userManager.cgi?action=getActiveUserInfoAll`
+
+3. 校时信息:`/cgi-bin/configManager.cgi?action=getConfig&name=NTP`
+
+使用Digest认证方式,解析设备返回的配置数据格式。
diff --git 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/uniview.md 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/uniview.md
new file mode 100644
index 0000000000..97cf025f29
--- /dev/null
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/uniview.md
@@ -0,0 +1,47 @@
+---
+id: uniview
+title: 监控 宇视设备
+sidebar_label: 宇视
+keywords: [ monitor, uniview, 宇视 ]
+---
+
+> 通过HTTP接口监控宇视设备状态,获取设备健康数据。
+
+## 监控配置参数
+
+| 参数名称      | 参数帮助描述 |
+| ----------- | ----------- |
+| 监控Host     | 设备IP/域名 |
+| 监控名称     | 唯一标识名称 |
+| 端口        | 默认80端口 |
+| 超时时间 | 毫秒级超时设置 |
+| 用户名      | 认证用户名 |
+| 密码        | 认证密码 |
+| 启用HTTPS   | HTTPS开关 |
+| 采集间隔    | ≥30秒采集周期 |
+
+## 采集指标
+
+### 系统信息
+
+- 设备名称
+- 序列号
+- 固件版本
+- 设备型号
+
+### 校时信息
+
+- NTP服务器IP
+- 校时端口
+- 同步间隔
+- 校时启用状态
+
+## 实现原理
+
+通过宇视HTTP API接口:
+
+1. 系统信息:`/LAPI/V1.0/System/DeviceInfo`
+
+2. 校时信息:`/LAPI/V1.0/System/Time/NTP`
+
+使用Digest认证,解析JSON格式响应数据。
diff --git a/home/sidebars.json b/home/sidebars.json
index c5a590a2ee..faa7f18ded 100755
--- a/home/sidebars.json
+++ b/home/sidebars.json
@@ -147,7 +147,9 @@
           "label": "server",
           "items": [
           "help/ipmi",
-          "help/hikvision_isapi"
+          "help/hikvision_isapi",
+          "help/dahua",
+          "help/uniview"
           ]
         },
         {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to