py-hikvision 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 郭磊
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: py-hikvision
3
+ Version: 0.1.0
4
+ Summary: 一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。
5
+ License-Expression: MIT
6
+ Project-URL: Home, https://gitee.com/guolei19850528/py_hikvision
7
+ Keywords: isc,hikvision,python,client,api,海康威视,iSecure Center
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: httpx>=0.27.0
14
+ Requires-Dist: pydantic>=2.0.0
15
+ Requires-Dist: jsonpath-ng>=1.2.0
16
+ Requires-Dist: jsonschema>=4.0.0
17
+ Requires-Dist: twine>=6.2.0
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=7.0; extra == "dev"
20
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
21
+ Requires-Dist: build>=0.18.0; extra == "dev"
22
+ Requires-Dist: twine>=4.0.0; extra == "dev"
23
+ Dynamic: license-file
24
+
25
+ # py_hikvision
26
+
27
+ 一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。
28
+
29
+ ## 功能特性
30
+
31
+ - 🔐 **API 认证**: 支持 HMAC-SHA256 签名认证机制
32
+ - 🚀 **同步/异步请求**: 支持同步和异步两种 HTTP 请求方式
33
+ - 📋 **响应模型**: 使用 Pydantic 进行响应数据校验和解析
34
+ - 🔧 **工具函数**: 提供时间戳、UUID、JSONPath 查询等实用工具
35
+
36
+ ## 安装
37
+
38
+ ```bash
39
+ pip install py_hikvision
40
+ ```
41
+
42
+ ## 快速开始
43
+
44
+ ### 基本使用
45
+
46
+ ```python
47
+ from py_hikvision.isc import Isc
48
+
49
+ # 初始化客户端
50
+ isc = Isc(
51
+ host="https://your-isc-server.com",
52
+ ak="your-access-key",
53
+ sk="your-secret-key"
54
+ )
55
+
56
+ # 发送同步请求
57
+ response = isc.request(
58
+ method="POST",
59
+ url="/api/parking/info",
60
+ json={"plateNo": "京A12345"}
61
+ )
62
+ print(response.json())
63
+
64
+ # 发送异步请求
65
+ async def fetch_data():
66
+ response = await isc.async_request(
67
+ method="GET",
68
+ url="/api/parking/list"
69
+ )
70
+ return response.json()
71
+ ```
72
+
73
+ ## API 文档
74
+
75
+ ### Isc 类
76
+
77
+ #### 初始化
78
+
79
+ ```python
80
+ isc = Isc(
81
+ host: Optional[str] = None, # ISC 服务器地址
82
+ ak: Optional[str] = None, # Access Key
83
+ sk: Optional[str] = None, # Secret Key
84
+ client_kwargs: Optional[dict] = None # httpx 客户端配置
85
+ )
86
+ ```
87
+
88
+ #### 方法
89
+
90
+ | 方法 | 说明 |
91
+ |------|------|
92
+ | `client()` | 创建同步 HTTP 客户端 |
93
+ | `async_client()` | 创建异步 HTTP 客户端 |
94
+ | `signature(string)` | 生成 HMAC-SHA256 签名 |
95
+ | `headers(method, path, headers)` | 生成请求头(包含签名) |
96
+ | `request(**kwargs)` | 发送同步请求 |
97
+ | `async_request(**kwargs)` | 发送异步请求 |
98
+
99
+ ### 工具函数
100
+
101
+ ```python
102
+ from py_hikvision.isc.utils import (
103
+ timestamp, # 生成毫秒时间戳
104
+ nonce, # 生成 UUID
105
+ json_find_first, # JSONPath 查询
106
+ json_is_valid, # JSON Schema 校验
107
+ url_add_artemis_prefix, # 添加 Artemis 前缀
108
+ image_to_base64_and_md5, # 图片编码
109
+ convert_to_normal # 转换为 Normal 模型
110
+ )
111
+ ```
112
+
113
+ ## 响应模型
114
+
115
+ ```python
116
+ from py_hikvision.isc.responses import Normal
117
+
118
+ # 响应结构
119
+ normal = Normal(
120
+ code=0, # 错误码,0 表示成功
121
+ msg="success", # 错误信息
122
+ data={...} # 响应数据
123
+ )
124
+ ```
125
+
126
+ ## 安全说明
127
+
128
+ 1. **签名机制**: 使用 HMAC-SHA256 算法确保请求完整性
129
+ 2. **防止重放攻击**: 通过 nonce(随机 UUID)和 timestamp(时间戳)实现
130
+ 3. **密钥管理**: Access Key 和 Secret Key 应妥善保管,避免泄露
131
+
132
+ ## 依赖
133
+
134
+ - `httpx`: HTTP 客户端
135
+ - `pydantic`: 数据验证
136
+ - `jsonpath-ng`: JSONPath 查询
137
+ - `jsonschema`: JSON Schema 校验
138
+
139
+ ## 主页
140
+
141
+ [https://gitee.com/guolei19850528/py_hikvision](https://gitee.com/guolei19850528/py_hikvision)
142
+
143
+ ## 许可证
144
+
145
+ MIT License
146
+
147
+ ## 贡献
148
+
149
+ 欢迎提交 Issue 和 Pull Request!
@@ -0,0 +1,125 @@
1
+ # py_hikvision
2
+
3
+ 一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。
4
+
5
+ ## 功能特性
6
+
7
+ - 🔐 **API 认证**: 支持 HMAC-SHA256 签名认证机制
8
+ - 🚀 **同步/异步请求**: 支持同步和异步两种 HTTP 请求方式
9
+ - 📋 **响应模型**: 使用 Pydantic 进行响应数据校验和解析
10
+ - 🔧 **工具函数**: 提供时间戳、UUID、JSONPath 查询等实用工具
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ pip install py_hikvision
16
+ ```
17
+
18
+ ## 快速开始
19
+
20
+ ### 基本使用
21
+
22
+ ```python
23
+ from py_hikvision.isc import Isc
24
+
25
+ # 初始化客户端
26
+ isc = Isc(
27
+ host="https://your-isc-server.com",
28
+ ak="your-access-key",
29
+ sk="your-secret-key"
30
+ )
31
+
32
+ # 发送同步请求
33
+ response = isc.request(
34
+ method="POST",
35
+ url="/api/parking/info",
36
+ json={"plateNo": "京A12345"}
37
+ )
38
+ print(response.json())
39
+
40
+ # 发送异步请求
41
+ async def fetch_data():
42
+ response = await isc.async_request(
43
+ method="GET",
44
+ url="/api/parking/list"
45
+ )
46
+ return response.json()
47
+ ```
48
+
49
+ ## API 文档
50
+
51
+ ### Isc 类
52
+
53
+ #### 初始化
54
+
55
+ ```python
56
+ isc = Isc(
57
+ host: Optional[str] = None, # ISC 服务器地址
58
+ ak: Optional[str] = None, # Access Key
59
+ sk: Optional[str] = None, # Secret Key
60
+ client_kwargs: Optional[dict] = None # httpx 客户端配置
61
+ )
62
+ ```
63
+
64
+ #### 方法
65
+
66
+ | 方法 | 说明 |
67
+ |------|------|
68
+ | `client()` | 创建同步 HTTP 客户端 |
69
+ | `async_client()` | 创建异步 HTTP 客户端 |
70
+ | `signature(string)` | 生成 HMAC-SHA256 签名 |
71
+ | `headers(method, path, headers)` | 生成请求头(包含签名) |
72
+ | `request(**kwargs)` | 发送同步请求 |
73
+ | `async_request(**kwargs)` | 发送异步请求 |
74
+
75
+ ### 工具函数
76
+
77
+ ```python
78
+ from py_hikvision.isc.utils import (
79
+ timestamp, # 生成毫秒时间戳
80
+ nonce, # 生成 UUID
81
+ json_find_first, # JSONPath 查询
82
+ json_is_valid, # JSON Schema 校验
83
+ url_add_artemis_prefix, # 添加 Artemis 前缀
84
+ image_to_base64_and_md5, # 图片编码
85
+ convert_to_normal # 转换为 Normal 模型
86
+ )
87
+ ```
88
+
89
+ ## 响应模型
90
+
91
+ ```python
92
+ from py_hikvision.isc.responses import Normal
93
+
94
+ # 响应结构
95
+ normal = Normal(
96
+ code=0, # 错误码,0 表示成功
97
+ msg="success", # 错误信息
98
+ data={...} # 响应数据
99
+ )
100
+ ```
101
+
102
+ ## 安全说明
103
+
104
+ 1. **签名机制**: 使用 HMAC-SHA256 算法确保请求完整性
105
+ 2. **防止重放攻击**: 通过 nonce(随机 UUID)和 timestamp(时间戳)实现
106
+ 3. **密钥管理**: Access Key 和 Secret Key 应妥善保管,避免泄露
107
+
108
+ ## 依赖
109
+
110
+ - `httpx`: HTTP 客户端
111
+ - `pydantic`: 数据验证
112
+ - `jsonpath-ng`: JSONPath 查询
113
+ - `jsonschema`: JSON Schema 校验
114
+
115
+ ## 主页
116
+
117
+ [https://gitee.com/guolei19850528/py_hikvision](https://gitee.com/guolei19850528/py_hikvision)
118
+
119
+ ## 许可证
120
+
121
+ MIT License
122
+
123
+ ## 贡献
124
+
125
+ 欢迎提交 Issue 和 Pull Request!
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+ [project]
5
+ name = "py-hikvision"
6
+ version = "0.1.0"
7
+ requires-python = ">=3.13"
8
+ description = "一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。"
9
+ keywords = ["isc", "hikvision", "python", "client", "api", "海康威视", "iSecure Center"]
10
+ readme = "README.md"
11
+ license = "MIT"
12
+ license-files = ["LICEN[CS]E*"]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+ dependencies = [
18
+ "httpx>=0.27.0",
19
+ "pydantic>=2.0.0",
20
+ "jsonpath-ng>=1.2.0",
21
+ "jsonschema>=4.0.0",
22
+ "twine>=6.2.0",
23
+ ]
24
+ [project.optional-dependencies]
25
+ dev = [
26
+ "pytest>=7.0",
27
+ "pytest-asyncio>=0.21",
28
+ "build>=0.18.0",
29
+ "twine>=4.0.0"
30
+ ]
31
+
32
+ [tool.setuptools.packages.find]
33
+ where = ["src"]
34
+ [project.urls]
35
+ "Home" = "https://gitee.com/guolei19850528/py_hikvision"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: UTF-8 -*-
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: UTF-8 -*-
3
+ import base64
4
+ import hashlib
5
+ import hmac
6
+ from typing import Optional, Tuple
7
+
8
+ import httpx
9
+ from pydantic import HttpUrl
10
+
11
+ from .responses import Normal
12
+ from .utils import timestamp, nonce
13
+
14
+
15
+ class Isc:
16
+ """
17
+ Isc类,用于与iSecure Center进行交互
18
+ """
19
+
20
+ def __init__(
21
+ self,
22
+ host: Optional[HttpUrl] = None,
23
+ ak: Optional[str] = None,
24
+ sk: Optional[str] = None,
25
+ client_kwargs: Optional[dict] = None,
26
+ ):
27
+ """
28
+ 初始化 Isc 客户端
29
+
30
+ 创建与 iSecure Center 交互的客户端实例,配置连接参数和认证密钥。
31
+
32
+ 参数:
33
+ host (Optional[HttpUrl]): iSecure Center 服务器地址,如 "https://isc.example.com"
34
+ ak (Optional[str]): Access Key,用于 API 认证
35
+ sk (Optional[str]): Secret Key,用于生成请求签名
36
+ client_kwargs (Optional[dict]): 传递给 httpx.Client 的额外配置参数
37
+
38
+ 配置说明:
39
+ - host 会自动去除末尾的斜杠
40
+ - 默认配置: base_url=host, verify=False, timeout=60
41
+ - client_kwargs 中的参数会覆盖默认配置
42
+ """
43
+ self.host = host or ""
44
+ self.host = self.host[:-1] if self.host.endswith("/") else self.host
45
+ self.ak = ak or ""
46
+ self.sk = sk or ""
47
+ self.client_kwargs = client_kwargs or {}
48
+ self.client_kwargs = {
49
+ **{
50
+ "base_url": self.host,
51
+ "verify": False,
52
+ "timeout": 60,
53
+ },
54
+ **self.client_kwargs,
55
+ }
56
+
57
+ def client(self) -> httpx.Client:
58
+ """
59
+ 创建并返回同步HTTP客户端
60
+
61
+ Returns:
62
+ httpx.Client: 配置好的同步HTTP客户端实例
63
+ """
64
+ return httpx.Client(**self.client_kwargs)
65
+
66
+ def async_client(self) -> httpx.AsyncClient:
67
+ """
68
+ 创建并返回异步HTTP客户端
69
+
70
+ Returns:
71
+ httpx.AsyncClient: 配置好的异步HTTP客户端实例
72
+ """
73
+ return httpx.AsyncClient(**self.client_kwargs)
74
+
75
+ def signature(self, string: str = "") -> str:
76
+ """
77
+ 生成请求签名
78
+
79
+ 使用 HMAC-SHA256 算法对输入字符串进行签名,确保请求的完整性和真实性。
80
+
81
+ 参数:
82
+ string (str): 需要签名的字符串,由请求方法、Accept、Content-Type、
83
+ x-ca-key、x-ca-nonce、x-ca-timestamp 和请求路径组成
84
+
85
+ 返回:
86
+ str: 生成的签名(Base64 编码的 HMAC-SHA256 哈希值)
87
+
88
+ 签名算法流程:
89
+ 1. 将 Secret Key 编码为字节串作为 HMAC 密钥
90
+ 2. 将待签名字符串编码为字节串
91
+ 3. 使用 HMAC-SHA256 算法计算哈希值
92
+ 4. 对哈希结果进行 Base64 编码并转换为字符串
93
+
94
+ 安全说明:
95
+ - 签名机制防止请求被篡改
96
+ - 配合 nonce 和 timestamp 防止请求重放攻击
97
+ """
98
+ return base64.b64encode(
99
+ hmac.new(
100
+ self.sk.encode(),
101
+ string.encode(),
102
+ digestmod=hashlib.sha256
103
+ ).digest()
104
+ ).decode()
105
+
106
+ def headers(
107
+ self,
108
+ method: str = "POST",
109
+ path: str = "",
110
+ headers: dict = None
111
+ ) -> dict:
112
+ """
113
+ 生成符合 ISecureCenter API 规范的请求头
114
+
115
+ 根据 ISC API 规范生成包含认证信息的请求头,包括签名、密钥、随机数和时间戳。
116
+
117
+ 参数:
118
+ method (str): HTTP 请求方法,支持 GET、POST、PUT、DELETE 等,默认 POST
119
+ path (str): 请求路径,例如 "/api/parking/info"
120
+ headers (dict): 额外的请求头,会覆盖默认请求头中的同名项
121
+
122
+ 返回:
123
+ dict: 完整的请求头字典,包含所有必要的认证信息
124
+
125
+ 请求头字段说明:
126
+ - accept: 接受所有响应类型
127
+ - content-type: 内容类型,固定为 application/json
128
+ - x-ca-key: 访问密钥 Access Key,用于标识请求来源
129
+ - x-ca-nonce: 随机 UUID,防止请求被重放攻击
130
+ - x-ca-timestamp: 当前时间戳(毫秒),用于请求时效性验证
131
+ - x-ca-signature: 请求签名,使用 HMAC-SHA256 算法生成
132
+ - x-ca-signature-headers: 参与签名计算的请求头列表
133
+
134
+ 签名字符串格式:
135
+ 按顺序拼接以下字段,使用换行符分隔:
136
+ 1. HTTP 请求方法
137
+ 2. Accept 头值
138
+ 3. Content-Type 头值
139
+ 4. x-ca-key:{value}
140
+ 5. x-ca-nonce:{value}
141
+ 6. x-ca-timestamp:{value}
142
+ 7. 请求路径
143
+
144
+ 示例:
145
+ >>> headers = isc_client.headers(method="POST", path="/api/parking/info")
146
+ >>> print(headers)
147
+ {
148
+ 'accept': '*/*',
149
+ 'content-type': 'application/json',
150
+ 'x-ca-signature-headers': 'x-ca-key,x-ca-nonce,x-ca-timestamp',
151
+ 'x-ca-key': 'your_access_key',
152
+ 'x-ca-nonce': 'uuid-string',
153
+ 'x-ca-timestamp': '1234567890123',
154
+ 'x-ca-signature': 'base64-encoded-signature'
155
+ }
156
+ """
157
+ method = method or "POST"
158
+ path = path or ""
159
+ headers = headers or {}
160
+
161
+ headers = {
162
+ "accept": "*/*",
163
+ "content-type": "application/json",
164
+ "x-ca-signature-headers": "x-ca-key,x-ca-nonce,x-ca-timestamp",
165
+ "x-ca-key": self.ak,
166
+ "x-ca-nonce": nonce(),
167
+ "x-ca-timestamp": str(timestamp()),
168
+ **headers
169
+ }
170
+
171
+ string = "\n".join([
172
+ method,
173
+ headers["accept"],
174
+ headers["content-type"],
175
+ f"x-ca-key:{headers['x-ca-key']}",
176
+ f"x-ca-nonce:{headers['x-ca-nonce']}",
177
+ f"x-ca-timestamp:{headers['x-ca-timestamp']}",
178
+ path,
179
+ ])
180
+
181
+ headers["x-ca-signature"] = self.signature(string=string)
182
+ return headers
183
+
184
+ def request(self, client: Optional[httpx.Client] = None, **kwargs) -> httpx.Response:
185
+ """
186
+ 发送同步 HTTP 请求
187
+
188
+ 自动添加 ISC API 认证签名,支持传入自定义客户端或使用内置客户端。
189
+
190
+ 参数:
191
+ client (Optional[httpx.Client]): 自定义的 httpx.Client 实例,若为 None 则自动创建
192
+ **kwargs: 传递给 httpx.Client.request 的参数,包括 method、url、headers、data、json 等
193
+
194
+ 返回:
195
+ httpx.Response: HTTP 响应对象
196
+
197
+ 使用示例:
198
+ >>> isc = Isc(host="https://isc.example.com", ak="your_ak", sk="your_sk")
199
+ >>> response = isc.request(method="GET", url="/api/parking/info")
200
+ >>> print(response.json())
201
+ """
202
+ kwargs = kwargs or {}
203
+ kwargs = {
204
+ **{
205
+ "method": "POST",
206
+ "headers": {
207
+ **self.headers(
208
+ method=kwargs.get("method", "POST"),
209
+ path=kwargs.get("url", ""),
210
+ headers=kwargs.get("headers", {})
211
+ )
212
+ },
213
+ },
214
+ **kwargs
215
+ }
216
+ if isinstance(client, httpx.Client):
217
+ response = client.request(**kwargs)
218
+ else:
219
+ with self.client() as _client:
220
+ response = _client.request(**kwargs)
221
+ return response
222
+
223
+ async def async_request(self, client: Optional[httpx.AsyncClient] = None, **kwargs) -> httpx.Response:
224
+ """
225
+ 发送异步 HTTP 请求
226
+
227
+ 自动添加 ISC API 认证签名,支持传入自定义异步客户端或使用内置客户端。
228
+
229
+ 参数:
230
+ client (Optional[httpx.AsyncClient]): 自定义的 httpx.AsyncClient 实例,若为 None 则自动创建
231
+ **kwargs: 传递给 httpx.AsyncClient.request 的参数,包括 method、url、headers、data、json 等
232
+
233
+ 返回:
234
+ httpx.Response: HTTP 响应对象
235
+
236
+ 使用示例:
237
+ >>> isc = Isc(host="https://isc.example.com", ak="your_ak", sk="your_sk")
238
+ >>> response = await isc.async_request(method="POST", url="/api/parking/info", json={"key": "value"})
239
+ >>> print(response.json())
240
+ """
241
+ kwargs = kwargs or {}
242
+ kwargs = {
243
+ **{
244
+ "method": "POST",
245
+ "headers": {
246
+ **self.headers(
247
+ method=kwargs.get("method", "POST"),
248
+ path=kwargs.get("url", ""),
249
+ headers=kwargs.get("headers", {})
250
+ )
251
+ },
252
+ },
253
+ **kwargs
254
+ }
255
+ if isinstance(client, httpx.AsyncClient):
256
+ response = await client.request(**kwargs)
257
+ else:
258
+ async with self.async_client() as _client:
259
+ response = await _client.request(**kwargs)
260
+ return response
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: UTF-8 -*-
3
+ from pydantic import BaseModel
4
+ from pydantic import Field
5
+ from typing import Literal, Union, Any
6
+
7
+ class Base(BaseModel):
8
+ """
9
+ iSecure Center响应基类
10
+
11
+ 所有API响应都包含错误码和错误信息字段
12
+ """
13
+ code: Union[int, str] = Field(..., title="错误码", description="错误码,0表示成功,非0表示失败")
14
+ msg: str = Field(..., title="错误信息", description="错误信息描述")
15
+
16
+
17
+ class Normal(Base):
18
+ """
19
+ 正常响应模型
20
+
21
+ 继承自Base,用于正常接口的响应
22
+ """
23
+ code: Literal[0, "0"] = Field(..., title="错误码", description="成功,值为0")
24
+ data: Any = Field(title="数据", description="正常响应数据")
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: UTF-8 -*-
3
+ import base64
4
+ import hashlib
5
+ import uuid
6
+ from datetime import datetime
7
+ from typing import Any, Optional, Tuple, Union
8
+
9
+ import httpx
10
+ from jsonpath_ng import parse
11
+ from jsonschema.validators import Draft202012Validator
12
+
13
+ from py_hikvision.isc import Normal
14
+
15
+
16
+ class ValidatorSchema:
17
+ """
18
+ JSON Schema 校验器定义类
19
+
20
+ 使用 JSON Schema Draft 2020-12 规范进行数据校验。
21
+
22
+ Attributes:
23
+ success: 通用成功响应 Schema,校验 code 是否为 0
24
+ """
25
+
26
+ success = {
27
+ "type": "object",
28
+ "properties": {
29
+ "code": {
30
+ "oneOf": [
31
+ {"type": "integer", "const": 0},
32
+ {"type": "string", "const": "0"}
33
+ ]
34
+ },
35
+ },
36
+ "required": ["code"]
37
+ }
38
+
39
+
40
+ def json_find_first(expression: str, data: Any) -> Any:
41
+ """
42
+ 使用 JSONPath 表达式从数据中查找第一个匹配项
43
+
44
+ Args:
45
+ expression: JSONPath 表达式,用于指定要查找的数据路径
46
+ data: 待查询的 JSON 数据
47
+
48
+ Returns:
49
+ Any: 第一个匹配的值,如果没有匹配项则返回 None
50
+ """
51
+ results = [i.value for i in parse(expression).find(data)]
52
+ if isinstance(results, list) and len(results) > 0:
53
+ return results[0]
54
+ return None
55
+
56
+
57
+ def json_is_valid(schema: Optional[dict], data: Any) -> bool:
58
+ """
59
+ 校验 JSON 数据是否符合指定的 JSON Schema
60
+
61
+ Args:
62
+ schema: JSON Schema 字典
63
+ data: 待校验的 JSON 数据
64
+
65
+ Returns:
66
+ bool: 校验是否成功
67
+ """
68
+ return Draft202012Validator(schema).is_valid(data)
69
+
70
+
71
+ def timestamp() -> int:
72
+ """
73
+ 生成当前时间戳(毫秒)
74
+
75
+ 返回:
76
+ int: 当前时间戳(毫秒),用于请求的时效性验证
77
+
78
+ 示例:
79
+ >>> ts = utils.timestamp()
80
+ >>> print(ts) # 输出示例: 1630000000000
81
+ """
82
+ return int((datetime.now().timestamp() * 1000))
83
+
84
+
85
+ def nonce() -> str:
86
+ """
87
+ 生成随机的 UUID 字符串
88
+
89
+ 返回:
90
+ str: 随机的 UUID 字符串(无连字符),用于防止请求重放攻击
91
+
92
+ 示例:
93
+ >>> random_nonce = utils.nonce()
94
+ >>> print(random_nonce) # 输出示例: "a1b2c3d4e5f6g7h8i9j0..."
95
+ """
96
+ return uuid.uuid4().hex
97
+
98
+
99
+ def url_add_artemis_prefix(url: Optional[str]) -> str:
100
+ """
101
+ 在URL前添加/artemis/前缀
102
+
103
+ :param url: 输入的URL字符串
104
+ :return: 包含/artemis/前缀的URL字符串
105
+ """
106
+ url = url or ""
107
+ if url.startswith("/"):
108
+ if not url.startswith("/artemis"):
109
+ return "/artemis" + url
110
+ return url
111
+ else:
112
+ return "/artemis/" + url
113
+
114
+
115
+ def image_to_base64_and_md5(image_path: Optional[str] = None) -> Tuple[str, str]:
116
+ """
117
+ 将图片文件转换为 Base64 编码和 MD5 校验值
118
+
119
+ 企业微信 Webhook 图片消息要求同时提供 base64 编码和 md5 值。
120
+
121
+ Args:
122
+ image_path: 图片文件的绝对路径或相对路径,默认值为 None
123
+
124
+ Returns:
125
+ Tuple[str, str]: 包含两个元素的元组
126
+ - 第一个元素: 图片的 Base64 编码字符串
127
+ - 第二个元素: 图片内容的 MD5 哈希值(小写十六进制)
128
+
129
+ Raises:
130
+ FileNotFoundError: 当指定的图片路径不存在时抛出
131
+ IOError: 当读取图片文件失败时抛出
132
+ """
133
+ image_path = image_path or ""
134
+ with open(image_path, 'rb') as f:
135
+ image_data = f.read()
136
+
137
+ base64_str = base64.b64encode(image_data).decode('utf-8')
138
+ md5_str = hashlib.md5(image_data).hexdigest()
139
+
140
+ return base64_str, md5_str
141
+
142
+
143
+ def convert_to_normal(response: Union[httpx.Response, dict]) -> Normal:
144
+ """
145
+ 将 HTTP 响应或字典转换为 Normal 模型对象
146
+
147
+ 统一处理 httpx.Response 对象和字典,将其转换为标准化的 Normal 响应模型。
148
+
149
+ 参数:
150
+ response (Union[httpx.Response, dict]): HTTP 响应对象或字典数据
151
+
152
+ 返回:
153
+ Normal: 标准化的响应模型对象,包含 code、msg 和 data 字段
154
+
155
+ 处理逻辑:
156
+ - 如果输入是 httpx.Response 对象,先调用 json() 方法解析响应体
157
+ - 如果输入是字典,直接传入 Normal 构造函数
158
+ """
159
+ if isinstance(response, httpx.Response):
160
+ return Normal(**response.json())
161
+ return Normal(**response)
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: py-hikvision
3
+ Version: 0.1.0
4
+ Summary: 一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。
5
+ License-Expression: MIT
6
+ Project-URL: Home, https://gitee.com/guolei19850528/py_hikvision
7
+ Keywords: isc,hikvision,python,client,api,海康威视,iSecure Center
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: httpx>=0.27.0
14
+ Requires-Dist: pydantic>=2.0.0
15
+ Requires-Dist: jsonpath-ng>=1.2.0
16
+ Requires-Dist: jsonschema>=4.0.0
17
+ Requires-Dist: twine>=6.2.0
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=7.0; extra == "dev"
20
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
21
+ Requires-Dist: build>=0.18.0; extra == "dev"
22
+ Requires-Dist: twine>=4.0.0; extra == "dev"
23
+ Dynamic: license-file
24
+
25
+ # py_hikvision
26
+
27
+ 一个用于与海康威视 iSecure Center (ISC) API 交互的 Python 客户端库。
28
+
29
+ ## 功能特性
30
+
31
+ - 🔐 **API 认证**: 支持 HMAC-SHA256 签名认证机制
32
+ - 🚀 **同步/异步请求**: 支持同步和异步两种 HTTP 请求方式
33
+ - 📋 **响应模型**: 使用 Pydantic 进行响应数据校验和解析
34
+ - 🔧 **工具函数**: 提供时间戳、UUID、JSONPath 查询等实用工具
35
+
36
+ ## 安装
37
+
38
+ ```bash
39
+ pip install py_hikvision
40
+ ```
41
+
42
+ ## 快速开始
43
+
44
+ ### 基本使用
45
+
46
+ ```python
47
+ from py_hikvision.isc import Isc
48
+
49
+ # 初始化客户端
50
+ isc = Isc(
51
+ host="https://your-isc-server.com",
52
+ ak="your-access-key",
53
+ sk="your-secret-key"
54
+ )
55
+
56
+ # 发送同步请求
57
+ response = isc.request(
58
+ method="POST",
59
+ url="/api/parking/info",
60
+ json={"plateNo": "京A12345"}
61
+ )
62
+ print(response.json())
63
+
64
+ # 发送异步请求
65
+ async def fetch_data():
66
+ response = await isc.async_request(
67
+ method="GET",
68
+ url="/api/parking/list"
69
+ )
70
+ return response.json()
71
+ ```
72
+
73
+ ## API 文档
74
+
75
+ ### Isc 类
76
+
77
+ #### 初始化
78
+
79
+ ```python
80
+ isc = Isc(
81
+ host: Optional[str] = None, # ISC 服务器地址
82
+ ak: Optional[str] = None, # Access Key
83
+ sk: Optional[str] = None, # Secret Key
84
+ client_kwargs: Optional[dict] = None # httpx 客户端配置
85
+ )
86
+ ```
87
+
88
+ #### 方法
89
+
90
+ | 方法 | 说明 |
91
+ |------|------|
92
+ | `client()` | 创建同步 HTTP 客户端 |
93
+ | `async_client()` | 创建异步 HTTP 客户端 |
94
+ | `signature(string)` | 生成 HMAC-SHA256 签名 |
95
+ | `headers(method, path, headers)` | 生成请求头(包含签名) |
96
+ | `request(**kwargs)` | 发送同步请求 |
97
+ | `async_request(**kwargs)` | 发送异步请求 |
98
+
99
+ ### 工具函数
100
+
101
+ ```python
102
+ from py_hikvision.isc.utils import (
103
+ timestamp, # 生成毫秒时间戳
104
+ nonce, # 生成 UUID
105
+ json_find_first, # JSONPath 查询
106
+ json_is_valid, # JSON Schema 校验
107
+ url_add_artemis_prefix, # 添加 Artemis 前缀
108
+ image_to_base64_and_md5, # 图片编码
109
+ convert_to_normal # 转换为 Normal 模型
110
+ )
111
+ ```
112
+
113
+ ## 响应模型
114
+
115
+ ```python
116
+ from py_hikvision.isc.responses import Normal
117
+
118
+ # 响应结构
119
+ normal = Normal(
120
+ code=0, # 错误码,0 表示成功
121
+ msg="success", # 错误信息
122
+ data={...} # 响应数据
123
+ )
124
+ ```
125
+
126
+ ## 安全说明
127
+
128
+ 1. **签名机制**: 使用 HMAC-SHA256 算法确保请求完整性
129
+ 2. **防止重放攻击**: 通过 nonce(随机 UUID)和 timestamp(时间戳)实现
130
+ 3. **密钥管理**: Access Key 和 Secret Key 应妥善保管,避免泄露
131
+
132
+ ## 依赖
133
+
134
+ - `httpx`: HTTP 客户端
135
+ - `pydantic`: 数据验证
136
+ - `jsonpath-ng`: JSONPath 查询
137
+ - `jsonschema`: JSON Schema 校验
138
+
139
+ ## 主页
140
+
141
+ [https://gitee.com/guolei19850528/py_hikvision](https://gitee.com/guolei19850528/py_hikvision)
142
+
143
+ ## 许可证
144
+
145
+ MIT License
146
+
147
+ ## 贡献
148
+
149
+ 欢迎提交 Issue 和 Pull Request!
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/py_hikvision/__init__.py
5
+ src/py_hikvision.egg-info/PKG-INFO
6
+ src/py_hikvision.egg-info/SOURCES.txt
7
+ src/py_hikvision.egg-info/dependency_links.txt
8
+ src/py_hikvision.egg-info/requires.txt
9
+ src/py_hikvision.egg-info/top_level.txt
10
+ src/py_hikvision/isc/__init__.py
11
+ src/py_hikvision/isc/responses.py
12
+ src/py_hikvision/isc/utils.py
@@ -0,0 +1,11 @@
1
+ httpx>=0.27.0
2
+ pydantic>=2.0.0
3
+ jsonpath-ng>=1.2.0
4
+ jsonschema>=4.0.0
5
+ twine>=6.2.0
6
+
7
+ [dev]
8
+ pytest>=7.0
9
+ pytest-asyncio>=0.21
10
+ build>=0.18.0
11
+ twine>=4.0.0
@@ -0,0 +1 @@
1
+ py_hikvision