1.添加简单http服务端模拟海康服务.\n2.添加测试海康接口方法

This commit is contained in:
haotian 2025-09-09 17:21:56 +08:00
parent 234c9d8842
commit b79ef0504b
4 changed files with 763 additions and 140 deletions

View File

@ -1,7 +1,89 @@
# from utils.haikang_util import HaikangUtil
from utils.haikang_util import HaikangUtil
import asyncio
import base64
# 查询门禁点列表
async def get_door_list_service(pageNo: int = 1, pageSize: int = 10):
result = await HaikangUtil.get_door_list_v2(pageNo, pageSize)
print(result)
# 查询门禁状态
async def get_door_status_service(door_index_codes):
result = await HaikangUtil.get_door_status(door_index_codes)
print(result)
# 门禁控制
async def door_do_control_service(door_index_codes, control_type):
result = await HaikangUtil.door_do_control(door_index_codes, control_type)
print(result)
# 查询门禁点事件
async def query_door_events_service(door_index_code,pageNo, pageSize, startTime, endTime):
result = await HaikangUtil.query_door_events_v2(door_index_code, pageNo=pageNo, pageSize=pageSize ,startTime=startTime, endTime=endTime)
print(result)
# 按条件查询人脸分组, 很重要
async def get_face_group_service():
result = await HaikangUtil.get_face_group()
print(result)
# 人脸分组1vN搜索
async def face_group_1vN_search_service(image_path):
with open(image_path, 'rb') as f:
image_data = f.read()
encoded_image = base64.b64encode(image_data).decode('utf-8')
result = await HaikangUtil.face_group_1vN_search(
facePicBinaryData=encoded_image,
pageNo=1,
pageSize=10,
searchNum=99,
minSimilarity=50,
faceGroupIndexCodes=['5dc82633-a4cb-4107-b55e-f21bf952f9']
)
print(result)
# 人脸评分
async def face_picture_check(image_path):
with open(image_path, 'rb') as f:
image_data = f.read()
encoded_image = base64.b64encode(image_data).decode('utf-8')
result = await HaikangUtil.face_picture_check(
facePicBinaryData=encoded_image
)
print(result)
# 查询访客预约记录
async def query_visitor_record():
result = await HaikangUtil.query_visitor_record()
print(result)
if __name__ == '__main__':
# asyncio.run(get_door_list_service())
# print("*"*100)
# asyncio.run(get_door_status_service(['D01']))
# print("*"*100)
# asyncio.run(door_do_control_service(['D01'], 1))
# asyncio.run(query_door_events_service('D01',1,10,1640995200,1640995200))
# asyncio.run(get_face_group_service())
# image_path = "75c03e462769c81b6a8513d90ff2a27d.jpg"
# asyncio.run(face_group_1vN_search_service(image_path))
# asyncio.run(face_picture_check(image_path))
asyncio.run(query_visitor_record())

View File

@ -0,0 +1,507 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import urllib.parse
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class CustomHTTPRequestHandler(BaseHTTPRequestHandler):
"""自定义HTTP请求处理器"""
def do_GET(self):
"""处理GET请求"""
# 解析URL和查询参数
parsed_path = urllib.parse.urlparse(self.path)
query_params = urllib.parse.parse_qs(parsed_path.query)
logger.info(f"GET 请求: {self.path}")
# 根据路径返回不同的响应
if parsed_path.path == "/":
self._send_response(200, "text/html", self._get_home_page())
elif parsed_path.path == "/api/user":
self._handle_user_api(query_params)
elif parsed_path.path == "/api/status":
self._send_json_response(200, {"status": "ok", "message": "服务运行正常"})
elif parsed_path.path == "/api/time":
import datetime
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self._send_json_response(200, {"time": current_time})
else:
self._send_json_response(404, {"error": "页面未找到"})
def do_POST(self):
"""处理POST请求"""
content_length = int(self.headers.get("Content-Length", 0))
post_data = self.rfile.read(content_length)
logger.info(f"POST 请求: {self.path}")
try:
# 尝试解析JSON数据
if content_length == 0:
logger.info("POST 请求数据为空")
elif self.headers.get("Content-Type") == "application/json":
data = json.loads(post_data.decode("utf-8"))
# logger.info(f"接收到JSON数据: {data}")
else:
# 解析表单数据
data = urllib.parse.parse_qs(post_data.decode("utf-8"))
logger.info(f"接收到表单数据: {data}")
# print("x"*100)
# 根据路径处理不同的POST请求
# if self.path == '/api/login':
# self._handle_login(data)
# elif self.path == '/api/echo':
# self._send_json_response(200, {'echo': data, 'message': '数据已接收'})
# else:
# self._send_json_response(404, {'error': '接口未找到'})
if self.path == "/api/resource/v2/door/search":
self._send_json_response(
200,
{
"code": "0",
"msg": "SUCCESS",
"data": {
"total": 3,
"pageNo": 1,
"pageSize": 1,
"list": [
{
"indexCode": "df8w8cr800283c24c",
"resourceType": "door",
"name": "资源 1",
"doorNo": "123",
"channelNo": "1",
"parentIndexCode": "80d9099q9e991231",
"controlOneId": "11111111",
"controlTwoId": "2222222222",
"readerInId": "ac789y2c0019c",
"readerOutId": "arcew78c710",
"doorSerial": 1,
"treatyType": "hiksdk_net",
"regionIndexCode": "d8a5476e-25c0-4aa2-b7e3-db3788ba1f77",
"regionPath": "@root000000@",
"createTime": "2018-11-28T16:47:27:358+08:00",
"updateTime": "2018-11-28T16:48:34:011+08:00",
"description": "Test",
"channelType": "door",
"regionName": "acs_setUp_42054",
"regionPathName": "@root000000@9ca1eef0-4579-4e7e-a601-caf486442d54@",
"installLocation": "位置 1",
}
],
},
},
)
elif self.path == "/api/v1/door/states":
self._send_json_response(
200,
{
"code": "0",
"msg": "success",
"data": {
"authDoorList": [
{
"doorIndexCode": "e8e3ef5c149243abb4341124ab38fcfc",
"doorState": 0,
}
],
"noAuthDoorIndexCodeList": [
"e8e3ef5c149243abb4341124ab38fcfc"
],
},
},
)
elif self.path == "/api/acs/v1/door/doControl":
self._send_json_response(
200,
{
"code": "0",
"msg": "success",
"data": [
{
"doorIndexCode": "2c95c028a809448f962a969e3ab34f",
"controlResultCode": 0, # 0表示反控成功, 其他表示失败
"controlResultDesc": "success",
}
],
},
)
elif self.path == "/api/acs/v2/door/events":
self._send_json_response(
200,
{
"code": "0",
"msg": "success",
"data": {
"total": 1,
"totalPage": 1,
"pageNo": 1,
"pageSize": 100,
"list": [
{
"eventId": "207dd3b1-37a7-4d6c-8e4d-c8bfd343051b",
"eventName": "acs.acs.eventType.successCard",
"eventTime": "2019-11-16T15:44:33+08:00",
"personId": "216e2ba145824269a1cbb423cdc85cb1",
"cardNo": "3891192334",
"personName": "sdk 人员 1zzzcb",
"orgIndexCode": "root000000",
"orgName": "默认组织",
"doorName": "10.40.239.69new_test2_门_1",
"doorIndexCode": "f0b50050d3434f15b4e34f885d5dacfe",
"doorRegionIndexCode": "fd2df06b-1afb-4c9b-b058-5740c2c00076",
"picUri": "no-pcnvr",
"svrIndexCode": "/pic?=d62i7f6e*6a7i125-c838b9--a8c67dea96e65icb1*=sd*=5dpi*=1dpi*m2i1t=4ed35444bb4s=-39",
"eventType": 198914,
"inAndOutType": 1,
"readerDevIndexCode": "378e563bf3e84d5ba6ef5742bbaa8933",
"readerDevName": "读卡器_1",
"devIndexCode": "dcff422aad9c4d60a47b8b2fe2757b71",
"devName": "10.40.239.69new_test2",
"identityCardUri": "/pic?=d62i7f6e*6a7i125-c838b9--a8c67dea96e65icb1*=sd*=5dpi*=1dpi*m2i1t=4ed35444bb4s=-39z422d3",
"receiveTime": "2019-11-16T15:45:13.525+08:00",
"jobNo": "23333",
"studentId": "201900001",
"certNo": "320826199012110005",
}
],
},
},
)
elif self.path == "/api/frs/v1/face/group":
self._send_json_response(
200,
{
"code": "0",
"msg": "Success",
"data": [
{
"indexCode": "5dc82633-a4cb-4107-b55e-f21bf952f9",
"name": "仓库值守人员",
"description": "仓库值守人员是指守着仓库的人",
}
],
},
)
elif self.path == "/api/frs/v1/application/oneToMany":
self._send_json_response(
200,
{
"code": "0",
"msg": "Success.",
"data": {
"total": 500,
"pageNo": 1,
"pageSize": 10,
"list": [
{
"similarity": 80,
"indexCode": "7cc0adb2-a3c3-48fd-b432-718103e85c28",
"faceInfo": {
"name": "张三",
"sex": "1",
"certificateType": "111",
"certificateNum": "420204199605121656",
},
"facePic": {
"faceUrl": "http://10.166.165.121:8080/frs/facepicturetemp/test.jpg"
},
}
],
},
},
)
elif self.path == "/api/frs/v1/face/picture/check":
self._send_json_response(
200,
{
"code": "0",
"msg": "Success",
"data": {
"checkResult": True,
"faceScore": 90,
"facePicAnalysisResult": {
"id": 5566,
"age": 16,
"ageRange": 1,
"ageGroup": "TEENAGER",
"": "male",
"glasses": "NO",
"smile": "NO",
"facePose": {
"pitch": 45,
"yaw": 25,
"roll": 10,
"clearityScore": 0.5,
"colorConfidence": 0.5,
"eyeDistance": 300,
"grayMean": 120,
"visibleScore": 0.5,
},
"targetModelData": "DD",
"faceRect": {
"height": 12.1,
"width": 16,
"x": 15,
"y": 3,
},
"recommendFaceRect": {
"height": 4,
"width": 6,
"x": 2,
"y": 1,
},
"faceMark": {
"leftEye": {"x": 33, "y": 22},
"rightEye": {"x": 44, "y": 33},
"noseTip": {"x": 43, "y": 12},
"leftMouth": {"x": 32, "y": 54},
"rightMouth": {"x": 67, "y": 12},
},
"mask": "NO",
"faceScore": 90,
},
},
},
)
elif self.path == "/api/visitor/v2/appointment/records":
self._send_json_response(
200,
{
"code": "0",
"msg": "success",
"data": {
"total": 1,
"pageNo": 1,
"pageSize": 20,
"list": [
{
"appointRecordId": "321654987",
"receptionistId": "3124126241412",
"receptionistName": "王五",
"receptionistCode": "323JH234KJH23",
"visitStartTime": "2018-07-26T15:00:00 + 08:00",
"visitEndTime": "2018-07-26T19:00:00 + 08:00",
"visitPurpose": "参考",
"visitorName": "张三",
"visitorId": "ASDF454SDAF565613JHU7712332",
"verificationCode": "1234",
"QRCode": "2015468421",
"": 1,
"phoneNo": "13576361254",
"plateNo": "浙 A12345",
"certificateType": 111,
"certificateNo": "311256196602145692",
"picUri": "/pic?adsdqwe21-asafdd-12sfsdfsdf",
"svrIndexCode": "sadsa123-asd21edsfhgsd-23rfdvsr",
"visitorStatus": 1,
"certAddr": "杭州滨江",
"certIssuer": "滨江分局",
"nation": 1,
"birthplace": "杭州",
"visitorWorkUnit": "中国工商银行",
"visitorAddress": "杭州滨江",
"orderId": "d089ady8a0dud87018d0y90ay9d901",
"designatedResources": {
"paramKey": "1",
"paramValues": ["52v72v35762587n75b26"],
},
"privilegeGroupNames": ["one"],
"identityUri": "/pic?123-scccdf334-3216516516516",
"identitySvrCode": "12ddf53ggg56sss6554",
}
],
},
},
)
except json.JSONDecodeError:
self._send_json_response(400, {"error": "无效的JSON数据"})
except Exception as e:
self._send_json_response(500, {"code": 0, "error": f"服务器错误: {str(e)}"})
def do_PUT(self):
"""处理PUT请求"""
content_length = int(self.headers.get("Content-Length", 0))
put_data = self.rfile.read(content_length)
logger.info(f"PUT 请求: {self.path}")
try:
data = json.loads(put_data.decode("utf-8"))
self._send_json_response(200, {"message": "数据已更新", "data": data})
except json.JSONDecodeError:
self._send_json_response(400, {"error": "无效的JSON数据"})
def do_DELETE(self):
"""处理DELETE请求"""
logger.info(f"DELETE 请求: {self.path}")
self._send_json_response(200, {"message": "删除成功", "path": self.path})
def _handle_user_api(self, query_params):
"""处理用户API请求"""
user_id = query_params.get("id", [""])[0]
if user_id:
user_data = {
"id": user_id,
"name": f"用户{user_id}",
"email": f"user{user_id}@example.com",
"status": "active",
}
self._send_json_response(200, user_data)
else:
# 返回用户列表
users = [
{"id": "1", "name": "张三", "email": "zhangsan@example.com"},
{"id": "2", "name": "李四", "email": "lisi@example.com"},
{"id": "3", "name": "王五", "email": "wangwu@example.com"},
]
self._send_json_response(200, {"users": users})
def _handle_login(self, data):
"""处理登录请求"""
username = (
data.get("username", [""])[0]
if isinstance(data, dict)
else data.get("username", "")
)
password = (
data.get("password", [""])[0]
if isinstance(data, dict)
else data.get("password", "")
)
# 简单的用户验证(仅做演示)
if username == "admin" and password == "123456":
response_data = {
"success": True,
"message": "登录成功",
"token": "fake_jwt_token_here",
"user": {"username": username, "role": "admin"},
}
self._send_json_response(200, response_data)
else:
self._send_json_response(
401, {"success": False, "message": "用户名或密码错误"}
)
def _send_response(self, status_code, content_type, content):
"""发送HTTP响应"""
self.send_response(status_code)
self.send_header("Content-Type", f"{content_type}; charset=utf-8")
self.send_header("Access-Control-Allow-Origin", "*") # 允许跨域
self.send_header(
"Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"
)
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers()
self.wfile.write(content.encode("utf-8"))
def _send_json_response(self, status_code, data):
"""发送JSON响应"""
json_data = json.dumps(data, ensure_ascii=False, indent=2)
self._send_response(status_code, "application/json", json_data)
def _get_home_page(self):
"""获取首页HTML"""
return """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python HTTP 服务端</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.api-list { background: #f5f5f5; padding: 20px; border-radius: 5px; }
.api-item { margin: 10px 0; padding: 10px; background: white; border-radius: 3px; }
.method { font-weight: bold; color: #007cba; }
</style>
</head>
<body>
<h1>🚀 Python HTTP 服务端</h1>
<p>服务运行成功以下是可用的API接口</p>
<div class="api-list">
<div class="api-item">
<span class="method">GET</span> /api/status - 获取服务状态
</div>
<div class="api-item">
<span class="method">GET</span> /api/time - 获取当前时间
</div>
<div class="api-item">
<span class="method">GET</span> /api/user - 获取用户列表
</div>
<div class="api-item">
<span class="method">GET</span> /api/user?id=1 - 获取指定用户
</div>
<div class="api-item">
<span class="method">POST</span> /api/login - 用户登录 (username: admin, password: 123456)
</div>
<div class="api-item">
<span class="method">POST</span> /api/echo - 回显接收到的数据
</div>
</div>
<h3>测试示例</h3>
<pre>
# 获取状态
curl http://localhost:8080/api/status
# 用户登录
curl -X POST -H "Content-Type: application/json" \\
-d '{"username":"admin","password":"123456"}' \\
http://localhost:8080/api/login
# 获取用户信息
curl http://localhost:8080/api/user?id=1
</pre>
</body>
</html>
"""
def do_OPTIONS(self):
"""处理预检请求CORS"""
self.send_response(200)
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header(
"Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"
)
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers()
def log_message(self, format, *args):
"""自定义日志格式"""
logger.info(f"{self.address_string()} - {format % args}")
def run_server(host="localhost", port=8080):
"""启动HTTP服务器"""
server_address = (host, port)
httpd = HTTPServer(server_address, CustomHTTPRequestHandler)
print(f"🌟 HTTP服务器启动成功!")
print(f"📍 地址: http://{host}:{port}")
print(f"🔗 在浏览器中访问: http://{host}:{port}")
print(f"⏹️ 按 Ctrl+C 停止服务器\n")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\n🛑 服务器已停止")
httpd.server_close()
if __name__ == "__main__":
# 启动服务器
run_server(host="10.0.0.202", port=9909)

View File

@ -154,8 +154,9 @@ class HaiKangSettings:
"""
海康平台配置
"""
HAIKANG_URL = ''
HAIKANG_PORT = 443
HAIKANG_URL = 'http://10.0.0.202'
# HAIKANG_PORT = 443
HAIKANG_PORT = 9909
HAIKANG_AK = ''
HAIKANG_SK = ''
HAIKANG_ACCESS_TOKEN_URL = '/api/v1/oauth/token'

View File

@ -1,16 +1,16 @@
import hashlib
import hmac
import json
import json
import base64
import requests
import httpx
import httpx
from fastapi import HTTPException
from datetime import datetime, timezone
from email.utils import format_datetime
from urllib.parse import urlparse
from dateutil.relativedelta import relativedelta
from config.env import HaiKangConfig
from config.env import HaiKangConfig
from utils.log_util import logger
@ -23,7 +23,7 @@ class HaikangUtil:
# self.HAIKANG_URL = HaiKangConfig.HAIKANG_URL
# self.HAIKANG_PORT = HaiKangConfig.HAIKANG_PORT
# self.HAIKANG_AK = HaiKangConfig.HAIKANG_AK
# self.HAIKANG_SK = HaiKangConfig.HAIKANG_SK
# self.HAIKANG_SK = HaiKangConfig.HAIKANG_SK
# 通用请求头
@classmethod
def build_signed_headers(cls, method, url, body, app_key, app_secret):
@ -40,28 +40,23 @@ class HaikangUtil:
# 1. 基本 headers
accept = "*/*"
content_type = "application/json"
# 2. 计算 MD5可选如果 body 存在)
content_md5 = ""
if body:
# .digest()返回原始二进制md5
md5_digest = hashlib.md5(body.encode('utf-8')).digest()
content_md5 = base64.b64encode(md5_digest).decode('utf-8')
md5_digest = hashlib.md5(body.encode("utf-8")).digest()
content_md5 = base64.b64encode(md5_digest).decode("utf-8")
# 3. 生成 Date headerHTTP 规范格式)
now = datetime.now(timezone.utc)
date = format_datetime(now, usegmt=True)
# 4. 构造 httpHeaders 部分
http_headers_str = "\n".join([
method.upper(),
accept,
content_md5,
content_type,
date,
""
])
http_headers_str = "\n".join(
[method.upper(), accept, content_md5, content_type, date, ""]
)
# 5. 自定义 headers 部分
custom_headers_str = f"x-ca-key:{app_key}\n"
@ -76,10 +71,10 @@ class HaikangUtil:
string_to_sign = http_headers_str + custom_headers_str + path_and_query
# 8. 使用 HmacSHA256 + Base64 签名
h = hmac.new(app_secret.encode('utf-8'),
string_to_sign.encode('utf-8'),
hashlib.sha256)
signature = base64.b64encode(h.digest()).decode('utf-8')
h = hmac.new(
app_secret.encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha256
)
signature = base64.b64encode(h.digest()).decode("utf-8")
# 9. 返回完整 headers
headers = {
@ -89,20 +84,23 @@ class HaikangUtil:
"Date": date,
"X-Ca-Key": app_key,
"X-Ca-Signature": signature,
"X-Ca-Signature-Headers": "x-ca-key"
"X-Ca-Signature-Headers": "x-ca-key",
}
return headers
# 发送请求
@classmethod
async def send_request(method: str, url: str, headers: dict, body: str | None):
async def send_request(cls, method: str, url: str, headers: dict, body: str | None):
async with httpx.AsyncClient() as client:
response = await client.request(method, url, headers=headers, content=body, timeout=60)
response = await client.request(
method, url, headers=headers, content=body, timeout=60
)
response.raise_for_status()
# if response.status_code >= 400:
# logger.error(f"发送请求失败: {url} , {response.status_code} {response.text}")
# raise HTTPException(status_code=response.status_code, detail=response.text)
return response.json()
# 获取access_token
@classmethod
async def get_access_token(cls):
@ -111,11 +109,13 @@ class HaikangUtil:
Returns:
_type_: json
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_ACCESS_TOKEN_URL}"
headers = cls.build_signed_headers('POST', url, None, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, None)
headers = cls.build_signed_headers(
"POST", url, None, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, None)
if back["code"] == "0":
logger.info("获取access_token成功")
return [True, back]
@ -123,8 +123,7 @@ class HaikangUtil:
else:
logger.error("获取access_token失败", back["code"], back["msg"])
return [False, back]
# 查询门禁点列表v2
@classmethod
async def get_door_list_v2(cls, pageNo: int = 1, pageSize: int = 10):
@ -137,51 +136,59 @@ class HaikangUtil:
Returns:
_type_: _description_
"""
url = f'{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_DOOR_SEARCH}'
body_dict ={
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_DOOR_SEARCH}"
body_dict = {
"pageNo": max(pageNo, 1),
"pageSize": min(pageSize, 999),
}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info("查询门禁点列表成功")
return [True, back["data"]]
else:
logger.error("查询门禁点列表失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 查询门禁状态
@classmethod
async def get_door_status(cls, door_index_codes:list):
async def get_door_status(cls, door_index_codes: list):
"""查询门禁状态
Args:
door_index_codes (list): 门禁点唯一标识
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_DOOR_STATES_URL}"
body_dict = {"doorIndexCodes": door_index_codes}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info("查询门禁状态成功")
return [True, back["data"]["authDoorList"], back["data"]["noAuthDoorIndexCodeList"]]
return [
True,
back["data"]["authDoorList"],
back["data"]["noAuthDoorIndexCodeList"],
]
else:
logger.error("查询门禁状态失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 门禁点反控
@classmethod
async def door_do_control(cls, door_index_code: list, control_type: int):
async def door_do_control(cls, door_index_code: list, control_type: int):
"""门禁点反控
Args:
@ -191,82 +198,101 @@ class HaikangUtil:
if control_type not in [0, 1, 2]:
logger.error("control_type参数错误 ", control_type)
return [False, 400, "control_type参数错误"]
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_DOOR_DOCONTROL_URL}"
body_dict = {
"doorIndexCodes": door_index_code,
"controlType": control_type
}
body_dict = {"doorIndexCodes": door_index_code, "controlType": control_type}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
"""
{
"code": "0",
"msg": "success",
"data": [
{
"doorIndexCode": "2c95c028a809448f962a969e3ab34f",
"controlResultCode": 0, # 0表示反控成功, 其他表示失败, 门禁控制是否成功主要看这个值
"controlResultDesc": "success",
}
],
},
"""
if back["code"] == "0":
logger.info(f'执行门禁控制成功 door_index_code:{door_index_code} control_type:{control_type} ')
logger.info(
f"执行门禁控制接口成功 door_index_code:{door_index_code} control_type:{control_type} "
)
return [True, back["data"]]
else:
logger.error(f'执行门禁控制失败 ', back["code"], back["msg"])
logger.error(f"执行门禁控制失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
@classmethod
# 查询门禁点事件v2
async def query_door_events_v2(cls, door_index_code: str, **args):
""" 查询门禁点事件v2
"""查询门禁点事件v2
Args:
door_index_code (str): 门禁唯一标识
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_DOOR_ENVENTS_URL}"
# current_time = datetime.now(timezone.utc)
# three_months_ago = current_time - relativedelta(months=3)
# # ISO8601 时间格式
# current_time_iso = current_time.isoformat()
# three_months_ago_iso = three_months_ago.isoformat()
body_dict ={
body_dict = {
"pageNo": max(args.get("pageNo", 1), 1),
"pageSize": min(args.get("pageSize", 10), 999),
"doorIndexCode": door_index_code,
# 排序字段
"sort": "eventTime",
# 倒序返回
"order": "desc",
}
if args.get("startTime"):
body_dict["startTime"] = args.get("startTime")
if args.get("endTime"):
body_dict["endTime"] = args.get("endTime")
if args.get("eventType"):
body_dict["eventType"] = args.get("eventType")
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info(f'获取门禁事件成功')
logger.info(f"获取门禁事件成功")
return [True, back["data"]]
else:
logger.error(f'获取门禁事件失败 ', back["code"], back["msg"] )
logger.error(f"获取门禁事件失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 人脸分组1vN检索
@classmethod
async def face_group_1vN_search(cls,
facePicBinaryData: str, # base64编码后的字符串
pageNo: int=1, pageSize:int=20, searchNum: int =99,
minSimilarity: int = 50,
faceGroupIndexCodes: list[str] = None,
):
async def face_group_1vN_search(
cls,
facePicBinaryData: str, # base64编码后的字符串
pageNo: int = 1,
pageSize: int = 20,
searchNum: int = 99,
minSimilarity: int = 50,
faceGroupIndexCodes: list[str] = None,
):
"""人脸分组1vN检索
Args:
@ -280,8 +306,8 @@ class HaikangUtil:
_type_: _description_
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_APPLICATION_ONETOMANY_URL}"
body_dict ={
body_dict = {
"facePicBinaryData": facePicBinaryData,
"pageNo": pageNo,
"pageSize": pageSize,
@ -289,24 +315,28 @@ class HaikangUtil:
"minSimilarity": minSimilarity,
"faceGroupIndexCodes": faceGroupIndexCodes,
}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info(f'获取人脸分组检索成功')
logger.info(f"获取人脸分组检索成功")
return [True, back["data"]]
else:
logger.error(f'获取人脸分组检索失败 ', back["code"], back["msg"] )
logger.error(f"获取人脸分组检索失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 人脸评分
async def face_picture_check(cls,
facePicBinaryData: str , #
):
@classmethod
async def face_picture_check(
cls,
facePicBinaryData: str, #
):
"""人脸评分
Args:
@ -316,30 +346,27 @@ class HaikangUtil:
_type_: _description_
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_PICTURE_CHECK_URL}"
body_dict ={
"facePicBinaryData": facePicBinaryData
}
body_dict = {"facePicBinaryData": facePicBinaryData}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info(f'获取人脸评分成功')
logger.info(f"获取人脸评分成功")
return [True, back["data"]]
else:
logger.error(f'获取人脸评分失败 ', back["code"], back["msg"] )
logger.error(f"获取人脸评分失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 按条件查询人员识别事件
@classmethod
async def get_face_capture_list_event(cls,
startTime,
endTime
):
async def get_face_capture_list_event(cls, startTime, endTime):
"""按条件查询人员识别事件, 暂无实现.
Args:
@ -347,26 +374,30 @@ class HaikangUtil:
endTime (_type_): _description_
"""
pass
# 按条件查询人脸分组
# 按条件查询人脸分组
@classmethod
async def get_face_group(cls):
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_FACE_GROUP_URL}"
headers = cls.build_signed_headers('POST', url, None, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, None)
headers = cls.build_signed_headers(
"POST", url, None, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, None)
if back["code"] == "0":
logger.info(f'按条件查询人脸成功')
logger.info(f"按条件查询人脸成功")
return [True, back["data"]]
else:
logger.error(f'按条件查询人脸失败 ', back["code"], back["msg"] )
logger.error(f"按条件查询人脸失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]
# 查询访客预约记录, visitorStatus: 0 待审核, 1 正常, 2 迟到, 3 失效, 4 审核退回, 9 审核失效, 10 邀约中, 11 邀约失效
@classmethod
async def query_visitor_record(cls, pageNo: int = 1, pageSize: int = 10, visitorStatus:int = 1):
async def query_visitor_record(
cls, pageNo: int = 1, pageSize: int = 10, visitorStatus: int = 1
):
"""查询访客预约记录
Args:
@ -378,21 +409,23 @@ class HaikangUtil:
_type_: _description_
"""
url = f"{HaiKangConfig.HAIKANG_URL}:{HaiKangConfig.HAIKANG_PORT}{HaiKangConfig.HAIKANG_VISITOR_RECORD_SEARCH}"
body_dict ={
body_dict = {
"pageNo": pageNo,
"pageSize": pageSize,
"visitorStatus": visitorStatus
"visitorStatus": visitorStatus,
}
body_json = json.dumps(body_dict, separators=(",", ":"))
headers = cls.build_signed_headers('POST', url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK)
back = await cls.send_request('POST', url, headers, body_json)
headers = cls.build_signed_headers(
"POST", url, body_json, HaiKangConfig.HAIKANG_AK, HaiKangConfig.HAIKANG_SK
)
back = await cls.send_request("POST", url, headers, body_json)
if back["code"] == "0":
logger.info(f'查询访客预约记录成功')
logger.info(f"查询访客预约记录成功")
return [True, back["data"]]
else:
logger.error(f'查询访客预约记录失败 ', back["code"], back["msg"] )
return [False, back["code"], back["msg"]]
logger.error(f"查询访客预约记录失败 ", back["code"], back["msg"])
return [False, back["code"], back["msg"]]