feat: 添加多个功能模块和工具脚本

- 新增websocket客户端和服务端实现
- 添加图片压缩工具和快速压缩脚本
- 实现学生信息处理相关API
- 添加MQTT客户端和消息处理功能
- 更新.gitignore忽略更多文件类型
- 添加数据库操作工具和示例
- 实现多个测试脚本和工具类
This commit is contained in:
2026-04-13 14:47:50 +08:00
parent 2cfd7c5a08
commit aac9f5934d
87 changed files with 216279 additions and 6519 deletions
+527
View File
@@ -0,0 +1,527 @@
{
"code": 0,
"msg": null,
"data": [
{
"productId": null,
"children": [
{
"productId": "2019296600419340289",
"productNameEn": "elevator",
"productName": "电梯",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2019296519146311681",
"productNameEn": "vehicle",
"productName": "车辆识别",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018978676756332545",
"productNameEn": "door_lock",
"productName": "门锁",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018978571475107841",
"productNameEn": "air-switch",
"productName": "空气开关",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018976858823344129",
"productNameEn": "wristban",
"productName": "手环",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018976009908797441",
"productNameEn": "recognizer",
"productName": "识别器",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018969974410309633",
"productNameEn": "cabinet-lock",
"productName": "柜锁",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018954460048912385",
"productNameEn": "wigan",
"productName": "韦根",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018937813758013442",
"productNameEn": "reader",
"productName": "读头",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018646961491968002",
"productNameEn": "base-station",
"productName": "基站",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": "2018645932016828417",
"productNameEn": "gateway",
"productName": "网关",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
],
"categoryName": "测试1",
"categoryId": "2018612484376014849",
"typeCode": "111",
},
{
"productId": null,
"children": [
{
"productId": "2019337895955329026",
"productNameEn": "school_bus",
"productName": "校车",
"categoryId": "2018623083457794050",
"typeCode": "777555",
},
{
"productId": "2018940636990173185",
"productNameEn": "circuit-breaker",
"productName": "断路器",
"categoryId": "2018623083457794050",
"typeCode": "777555",
},
],
"categoryName": "测试2",
"categoryId": "2018623083457794050",
"typeCode": "777555",
},
{
"productId": null,
"children": [
{
"productId": "2019302796740136962",
"productNameEn": "tradition_wristban",
"productName": "传统手环",
"categoryId": "2019302407156404226",
"typeCode": "555666",
},
{
"productId": "2019302708227739649",
"productNameEn": "bluetooth_wristban",
"productName": "蓝牙手环",
"categoryId": "2019302407156404226",
"typeCode": "555666",
},
],
"categoryName": "手环",
"categoryId": "2019302407156404226",
"typeCode": "555666",
},
],
"ok": true,
}
# %%
import os
os.add_dll_directory(os.getcwd())
import random
import string
import sys
import importlib.util
from typing import Any, Dict
from pctoken import get_token
from requests import post, get
from faker import Faker
fake = Faker("zh_CN")
# %%
BASE_URL = "http://192.168.0.209:9999"
data = get_token(BASE_URL, "admin", "123456")
TOKEN = data.get("access_token", "")
print(TOKEN)
headers = {
"Authorization": f"Bearer {TOKEN}",
"hx-client": "hongxapp",
}
# %%
# air-switch
DEVICE_AIR_SWITCH_CREATE = "/admin/device/air-switch"
for i in range(20):
air_switch_sn = random.randint(1000000000000000, 9999999999999999)
air_switch_body = {
"productId": "2018978571475107841",
"deviceSn": air_switch_sn,
"deviceName": f"智能空开-{fake.word()}",
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"installLocation": fake.address(),
"switchStatus": random.choice([0, 1]),
"status": 0,
"remark": fake.sentence(nb_words=6),
}
res = post(
BASE_URL + DEVICE_AIR_SWITCH_CREATE, headers=headers, json=air_switch_body
)
print(res.text)
# %%
# base-station
DEVICE_STATION_CREATE = "/admin/device/station"
for i in range(20):
station_sn = random.randint(1000000000000000, 9999999999999999)
station_body = {
"productId": "2018646961491968002",
"deviceSn": station_sn,
"deviceName": f"基站-{fake.word()}",
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"deviceType": "1",
"installLocation": fake.address(),
"deviceKey": random.randint(1000000000000000, 9999999999999999),
"remark": fake.sentence(nb_words=6),
"status": 0,
}
res = post(BASE_URL + DEVICE_STATION_CREATE, headers=headers, json=station_body)
print(res.text)
# %%
# cabinet-lock(依赖 stationId
DEVICE_CABINET_LOCK_CREATE = "/admin/netdevice/device-cabinet-lock"
for i in range(20):
cabinet_lock_no = random.randint(1000000000000000, 9999999999999999)
cabinet_lock_body = {
"productId": "2018969974410309633",
"lockNo": cabinet_lock_no,
"deviceName": f"柜锁-{fake.city()}",
"status": random.choice([0, 1, 2]),
"isBoundToDoor": random.choice([0, 1]),
"type": random.choice(["1", "2"]),
"remark": fake.sentence(),
}
res = post(
BASE_URL + DEVICE_CABINET_LOCK_CREATE, headers=headers, json=cabinet_lock_body
)
print(res.text)
# %%
# gateway
DEVICE_GATEWAY_CREATE = "/admin/device/gateway"
for i in range(20):
gateway_sn = random.randint(1000000000000000, 9999999999999999)
gateway_body = {
"productId": "2018645932016828417",
"deviceSn": gateway_sn,
"deviceName": f"网关-{fake.city()}",
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"deviceType": random.choice(["door_lock_gateway", "other_gateway"]),
"installLocation": fake.address(),
"deviceChannel": str(random.randint(1, 16)),
"remark": fake.sentence(nb_words=6),
"status": 0,
}
res = post(BASE_URL + DEVICE_GATEWAY_CREATE, headers=headers, json=gateway_body)
print(res.text)
# %%
# door_lock(依赖 gatewayId
DEVICE_LOCK_CREATE = "/admin/device/lock"
for i in range(20):
lock_no = random.randint(1000000000000000, 9999999999999999)
door_lock_body = {
"productId": "2018978676756332545",
"lockNo": lock_no,
"deviceName": f"门锁-{fake.city()}",
"gatewayId": random.choice(["9169811239367567", "7754060128201993"]),
"status": random.choice([0, 1, 2]),
"hasExtractFunction": 0,
"hasPassword": 1,
"password": random.randint(100000, 999999),
"isBoundToDoor": random.choice([0, 1]),
"remark": fake.sentence(),
}
res = post(BASE_URL + DEVICE_LOCK_CREATE, headers=headers, json=door_lock_body)
print(res.text)
# %%
# circuit-breaker(依赖 airSwitchId,通常是 air-switch 的 deviceSn
DEVICE_CIRCUIT_BREAKER_CREATE = "/admin/device/circuit-breaker"
for i in range(20):
breaker_no = random.randint(1000000000000000, 9999999999999999)
circuit_breaker_body = {
"productId": "2018940636990173185",
"breakerNo": breaker_no,
"deviceName": f"断路器-{fake.city()}",
"airSwitchId": random.choice(
[
1582072120398342,
1644746172859060,
2574410292808179,
2776742625637816,
3207386695301040,
3674583763875269,
3849211969830226,
]
),
"status": random.choice([0, 1, 2]),
"nodeCount": random.randint(1, 8),
"remark": fake.sentence(),
}
res = post(
BASE_URL + DEVICE_CIRCUIT_BREAKER_CREATE,
headers=headers,
json=circuit_breaker_body,
)
print(res)
# %%
# elevator
DEVICE_LIFT_CREATE = "/admin/device/lift"
for i in range(20):
lift_sn = random.randint(1000000000000000, 9999999999999999)
elevator_body = {
"productId": "2019296600419340289",
"deviceSn": lift_sn,
"deviceName": f"梯控-{fake.city()}",
"deviceIp": fake.ipv4(),
"deviceNo": str(random.randint(1, 9999)),
"connectedRouter": fake.ipv4(),
"installLocation": fake.address(),
"deviceMode": random.choice([0, 1]),
"status": random.choice([0, 1]),
"remark": fake.sentence(),
}
res = post(BASE_URL + DEVICE_LIFT_CREATE, headers=headers, json=elevator_body)
print(res.text)
# %%
# vehicle
DEVICE_VEHICLE_CREATE = "/admin/device/vehicle"
for i in range(20):
vehicle_sn = random.randint(1000000000000000, 9999999999999999)
vehicle_body = {
"productId": "2019296519146311681",
"deviceSn": vehicle_sn,
"deviceName": f"车辆设备-{fake.city()}",
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"deviceNo": str(random.randint(1, 9999)),
"installLocation": fake.address(),
"remark": fake.sentence(nb_words=6),
"status": random.choice([0, 1]),
}
res = post(BASE_URL + DEVICE_VEHICLE_CREATE, headers=headers, json=vehicle_body)
print(res.text)
# %%
# reader
DEVICE_READER_CREATE = "/admin/device/reader"
for i in range(20):
reader_no = random.randint(1000000000000000, 9999999999999999)
reader_body = {
"productId": "2018937813758013442",
"readerNo": reader_no,
"deviceName": f"读头-{fake.city()}",
"deviceSn": random.choice(
[
"4395863208063177",
"4507620338768596",
"4525465159473066",
"5123044738057092",
"5138054588855177",
"5183699874143289",
"5287117187640740",
"5462074601573078",
"6497478658104596",
"6566629050320440",
"6694612533818614",
"6790065482367945",
"7197073294560282",
"7403435624676403",
"7471664598236084",
"7856765426748316",
"8049877407436250",
"8580359496001971",
"8693901920738335",
"8770253509179521",
"8969126999259935",
"8995277348047315",
"9036644215670448",
"9242517627258907",
]
),
"deviceWeigengName": random.choice(
[
"3991174509065581",
"4443732147129234",
"4452687293776438",
"4574669744572919",
"5179325299441845",
"5205102639206670",
"5219766583478496",
"5726539153999514",
"5748607175944076",
"6353723150878385",
"6363184644999826",
"6374957876680257",
"6624601507335739",
"6753190058729790",
"6772927867754962",
"6856769083289203",
"6913876972860350",
"7047373159961839",
"7304404323678071",
"8095618128747104",
"8114941815818391",
"9042734145575960",
"9100122124868847",
]
),
"status": random.choice([0, 1, 2]),
"inOutStatus": random.choice([0, 1]),
"remark": fake.sentence(),
}
res = post(BASE_URL + DEVICE_READER_CREATE, headers=headers, json=reader_body)
print(res.text)
# %%
# recognizer(依赖 deviceSn,通常是基站 deviceSn
DEVICE_RECOGNIZER_CREATE = "/admin/device/recognizer"
for i in range(20):
recognizer_no = random.randint(1000000000000000, 9999999999999999)
recognizer_body = {
"productId": "2018976009908797441",
"recognizerNo": recognizer_no,
"deviceName": f"识别器-{fake.city()}",
"deviceSn": random.choice(
[
"8580359496001971",
"3548057972567292",
"4214139409397043",
"4525465159473066",
"3693107917636902",
"8770253509179521",
"3321970154630762",
"8693901920738335",
"8049877407436250",
"4382530155992156",
"5123044738057092",
"4395863208063177",
"2411282157269000",
"3256701932888562",
"9718641970097762",
"7197073294560282",
"2376641311995328",
"6497478658104596",
"6566629050320440",
"8995277348047315",
"5287117187640740",
"3165966423462843",
]
),
"status": random.choice([0, 1]),
"remark": fake.sentence(),
}
res = post(
BASE_URL + DEVICE_RECOGNIZER_CREATE, headers=headers, json=recognizer_body
)
print(res.text)
# %%
# wristban
DEVICE_WRISTBAND_CREATE = "/admin/device/wristband"
for i in range(200):
wristband_no = random.randint(1000000000, 9999999999)
wristband_mac = fake.mac_address()
wristband_body = {
"productId": random.choice(
[
"2019302796740136962",
"2019302708227739649",
]
),
"wristbandNo": wristband_no,
"wristbandMac": wristband_mac,
"status": str(random.choice([0, 1, 2, 3])),
}
res = post(BASE_URL + DEVICE_WRISTBAND_CREATE, headers=headers, json=wristband_body)
print(res.text)
# %%
# wigan(同 /admin/device/station,可视为另一种 station 数据)
for i in range(20):
wigan_sn = random.randint(1000000000000000, 9999999999999999)
wigan_body = {
"productId": "2018954460048912385",
"deviceSn": wigan_sn,
"deviceName": f"微耕-{fake.city()}",
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"installLocation": fake.address(),
"readerCount": random.randint(1, 8),
"remark": fake.sentence(),
"status": random.choice([0, 1]),
}
res = post(BASE_URL + "/admin/device/weigeng", headers=headers, json=wigan_body)
print(res.text)
# %%
# school-bus
for i in range(20):
shool_bus = {
"productId": "2019337895955329026",
"deviceSn": random.randint(1000000000000000, 9999999999999999),
"deviceName": f'校车-{fake.city()}',
"deviceIp": fake.ipv4(),
"connectedRouter": fake.ipv4(),
"simNo": random.randint(1000000000000000, 9999999999999999),
"simTime": fake.date_time_this_year().strftime("%Y-%m-%d %H:%M:%S"),
"installLocation": fake.address(),
"remark": fake.sentence(),
"status": random.choice([0, 1]),
}
res = post(BASE_URL + "/admin/device/school-bus", headers=headers, json=shool_bus)
print(res.text)
# %%
+78
View File
@@ -0,0 +1,78 @@
import base64
import os
import sys
import requests
def encrypt_password(password: str, key_word: str) -> str:
from Crypto.Cipher import AES
key = key_word.encode('utf-8')
iv = key
cypher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
ciphertext = cypher.encrypt(password.encode('utf-8'))
return base64.b64encode(ciphertext).decode('utf-8')
def build_basic_auth(client: str) -> str:
b64 = base64.b64encode(client.encode('utf-8')).decode('utf-8')
return f'Basic {b64}'
def get_token(base_url: str, username: str, password: str) -> dict:
enc_key = 'hongxyundapp2025'
oauth_client = 'hongxapp:hongxplapp'
enc_password = encrypt_password(password, enc_key)
url = f"{base_url.rstrip('/')}/auth/oauth2/token"
params = {
'username': username,
'randomStr': 'clickWord',
'code': '',
'grant_type': 'password',
'scope': 'server',
}
data = {
'password': enc_password,
}
resp = requests.post(
url,
params=params,
data=data,
headers={
'Authorization': build_basic_auth(oauth_client),
'Content-Type': 'application/x-www-form-urlencoded',
'Enc-Flag': 'false',
},
timeout=30,
)
resp.raise_for_status()
return resp.json()
def main() -> int:
base_url ='http://192.168.0.209:9999'
username ='admin'
password ='123456'
try:
res = get_token(base_url, username, password)
print(res)
access_token = res.get('access_token')
if access_token:
print('\nACCESS_TOKEN=')
print(access_token)
return 0
except Exception as e:
print(str(e), file=sys.stderr)
return 1
if __name__ == '__main__':
raise SystemExit(main())
+81
View File
@@ -0,0 +1,81 @@
import os
import random
from faker import Faker
from requests import post
from pctoken import get_token
BASE_URL = 'http://192.168.0.209:9999'
USERNAME = 'admin'
PASSWORD = '123456'
# TODO: 你自己处理
ORG_ID = ['2019668989619634177','2019669020191916033','2019669694686330882','2019669543792050177','2019669579221336066','2019669610317905922']
# 新增时一般传 "0"
PERSON_ID = '0'
# TODO: 如需绑定角色你自己填(int 列表)
ROLE_IDS = []
# 新增学生
CREATE_PERSON_API = '/admin/person-info'
fake = Faker('zh_CN')
def main() -> None:
data = get_token(BASE_URL, USERNAME, PASSWORD)
token = data.get('access_token', '')
if not token:
raise RuntimeError('No access_token found')
headers = {
'Authorization': f'Bearer {token}',
'hx-client': 'hongxapp',
}
for _ in range(200):
index = random.randint(0, 2)
names = [fake.name(), fake.name_male(), fake.name_female()]
fake_name = names[index]
body = {
'personId':0,
'orgId': random.choice(ORG_ID),
'postId': 0,
'personType': 'hx_stud',
'name': fake_name,
'tel': fake.phone_number(),
'gender':index,
'idcard': fake.ssn(),
'personCode': '',
'status': random.choice(['0', '1']),
'deptId': 0,
'delFlag': '0',
'avatar': '',
'personUserModelList': [
{
'username': fake.user_name(),
'relationType': '',
'phone': fake.phone_number(),
'password': '123456',
'teamUserType': '',
'personType': 'hx_stud',
'personId': '0',
'name': fake.user_name(),
'key': '',
'relId': 0,
'roleIds': ['2015665758143623178'],
},
],
}
resp = post(BASE_URL + CREATE_PERSON_API, headers=headers, json=body, timeout=30)
print(resp.status_code, resp.text)
if __name__ == '__main__':
main()
+125
View File
@@ -0,0 +1,125 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "70c9ccec",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"os.add_dll_directory(os.getcwd())\n",
"from pctoken import get_token\n",
"from requests import get,post"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "379f4db2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"342e75d2-dd64-4d6b-9316-da51fdce642d\n"
]
}
],
"source": [
"BASE_URL = \"http://192.168.0.244:9999\"\n",
"data = get_token(BASE_URL, \"admin\", \"123456\")\n",
"TOKEN = data.get(\"access_token\", \"\")\n",
"print(TOKEN)\n",
"headers = {\n",
" \"Authorization\": f\"Bearer {TOKEN}\",\n",
" \"hx-client\": \"hongxapp\",\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "820f6d23",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"timestamp\":\"2026-02-27 15:36:51\",\"status\":500,\"error\":\"Internal Server Error\",\"path\":\"/videoInfoStream/page\"}'"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"headers = {\n",
" \"Authorization\": f\"Bearer {TOKEN}\",\n",
" \"HX-CLIENT\": \"hongxapp\",\n",
" 'H-SV-CODE':'video',\n",
" 'Host': '192.168.0.111:5173',\n",
" 'Referer': 'http://192.168.0.111:5173/'\n",
"}\n",
"get( \" http://192.168.0.244:9999/video/videoInfoStream/page?current=1&size=10&descs=&ascs=\",headers=headers).text"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2c7227e6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'{\"timestamp\":\"2026-02-27 15:34:24\",\"status\":500,\"error\":\"Internal Server Error\",\"path\":\"/podPhoto/pageInfoBySections\"}'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "1822efb2",
"metadata": {},
"outputs": [],
"source": [
" # \"Accept\": 'application/json, text/plain, */*',\n",
"# 'Connection': 'keep-alive',\n",
"# 'H-SV-CODE':'video',\n",
"# 'HX-CLIENT':'hongxapp',\n",
"# 'Host': '192.168.0.111:5173',\n",
"# 'Referer': 'http://192.168.0.111:5173/'"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+1
View File
@@ -0,0 +1 @@
from schooliot_token import get_token