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.
- py_hikvision-0.1.0/LICENSE +21 -0
- py_hikvision-0.1.0/PKG-INFO +149 -0
- py_hikvision-0.1.0/README.md +125 -0
- py_hikvision-0.1.0/pyproject.toml +35 -0
- py_hikvision-0.1.0/setup.cfg +4 -0
- py_hikvision-0.1.0/src/py_hikvision/__init__.py +2 -0
- py_hikvision-0.1.0/src/py_hikvision/isc/__init__.py +260 -0
- py_hikvision-0.1.0/src/py_hikvision/isc/responses.py +24 -0
- py_hikvision-0.1.0/src/py_hikvision/isc/utils.py +161 -0
- py_hikvision-0.1.0/src/py_hikvision.egg-info/PKG-INFO +149 -0
- py_hikvision-0.1.0/src/py_hikvision.egg-info/SOURCES.txt +12 -0
- py_hikvision-0.1.0/src/py_hikvision.egg-info/dependency_links.txt +1 -0
- py_hikvision-0.1.0/src/py_hikvision.egg-info/requires.txt +11 -0
- py_hikvision-0.1.0/src/py_hikvision.egg-info/top_level.txt +1 -0
|
@@ -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,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 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
py_hikvision
|