牧安云哨-后端
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
|
||||
from config.redis import RedisClient
|
||||
from db.postgres.iot import *
|
||||
from models.BaseResponse import BaseResponse
|
||||
from models.EMQXWebhook import EMQXWebhook
|
||||
from routers.WS import ws_manager
|
||||
|
||||
iot_router = APIRouter()
|
||||
redis_client = RedisClient()
|
||||
|
||||
from config.security import get_user_id_from_token
|
||||
|
||||
# -------------------- 设备接口 --------------------
|
||||
|
||||
|
||||
@iot_router.post("/common/webhook")
|
||||
async def emqx_webhook(data: EMQXWebhook):
|
||||
device_id = data.clientid
|
||||
event = data.event
|
||||
|
||||
if event == "client.connected":
|
||||
redis_client.set_online(device_id)
|
||||
|
||||
await ws_manager.broadcast({"deviceId": device_id, "online": True})
|
||||
|
||||
print(f"[ONLINE] {device_id}")
|
||||
|
||||
elif event == "client.disconnected":
|
||||
redis_client.set_offline(device_id)
|
||||
|
||||
await ws_manager.broadcast({"deviceId": device_id, "online": False})
|
||||
|
||||
print(f"[OFFLINE] {device_id}")
|
||||
|
||||
else:
|
||||
# 其他事件直接忽略
|
||||
print(f"[IGNORE] {event}")
|
||||
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@iot_router.get("/common/device/list")
|
||||
async def get_device_list(
|
||||
page: int = 1,
|
||||
pageSize: int = 10,
|
||||
id: str | None = None,
|
||||
name: str | None = None,
|
||||
status: int | None = None,
|
||||
is_superuser: int | None = None,
|
||||
dept_id: str | None = None,
|
||||
startTime: str | None = None,
|
||||
endTime: str | None = None,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
devices, total = get_device_list_db_page(
|
||||
page, pageSize, id, name, status, is_superuser, dept_id, startTime, endTime
|
||||
)
|
||||
|
||||
# ===== 👇 核心:补在线状态 =====
|
||||
for d in devices:
|
||||
device_id = d["name"] # 账号
|
||||
d["online"] = redis_client.is_device_online(device_id) == 1
|
||||
|
||||
return BaseResponse(data={"list": devices, "total": total})
|
||||
|
||||
|
||||
@iot_router.post("/common/device")
|
||||
async def create_device(data: dict, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
new_id = insert_device(data)
|
||||
return BaseResponse(data={"id": new_id})
|
||||
|
||||
|
||||
@iot_router.put("/common/device/{id}")
|
||||
async def update_device(
|
||||
id: str,
|
||||
data: dict,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
count = update_device_db(id, data)
|
||||
if count == 0:
|
||||
return BaseResponse(status=False, message="设备不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@iot_router.patch("/common/device/{id}")
|
||||
async def patch_device(
|
||||
id: str,
|
||||
data: dict,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
count = patch_device_db(id, data)
|
||||
if count == 0:
|
||||
return BaseResponse(status=False, message="设备不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@iot_router.delete("/common/device/{id}")
|
||||
async def delete_device(
|
||||
id: str,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
deleted = delete_device_db(id)
|
||||
if deleted == 0:
|
||||
return BaseResponse(status=False, message="设备不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
@@ -0,0 +1,98 @@
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import Depends, APIRouter
|
||||
|
||||
from config.security import get_user_id_from_token
|
||||
from db.postgres import get_dept_ids_by_user_id, get_dept_id_by_user_id
|
||||
from db.postgres.sentinel import *
|
||||
from models.BaseResponse import BaseResponse
|
||||
|
||||
# -------------------- 设备接口 --------------------
|
||||
|
||||
sentinel_router = APIRouter()
|
||||
|
||||
|
||||
@sentinel_router.get("/record/list")
|
||||
async def get_sentinel_record_list(
|
||||
page: int = 1,
|
||||
page_size: int = 10,
|
||||
id: str | None = None,
|
||||
license_plate: str | None = None,
|
||||
vehicle_type: str | None = None,
|
||||
is_inspected: int | None = None,
|
||||
livestock_type: str = None,
|
||||
livestock_source: str | None = None,
|
||||
start_time: str | None = None,
|
||||
end_time: str | None = None,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
dept_ids = get_dept_ids_by_user_id(user_id)
|
||||
print(dept_ids) # 输出所有部门的 dept_id 列表
|
||||
|
||||
records, total = get_sentinel_record_list_db_page(
|
||||
page,
|
||||
page_size,
|
||||
id,
|
||||
license_plate,
|
||||
vehicle_type,
|
||||
is_inspected,
|
||||
livestock_source,
|
||||
livestock_type,
|
||||
dept_ids,
|
||||
start_time,
|
||||
end_time,
|
||||
)
|
||||
|
||||
return BaseResponse(data={"list": records, "total": total})
|
||||
|
||||
|
||||
@sentinel_router.post("/record")
|
||||
async def create_sentinel_record(
|
||||
data: dict, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
dept_id = get_dept_id_by_user_id(user_id)
|
||||
new_id = insert_sentinel_record(data, dept_id)
|
||||
return BaseResponse(data={"id": new_id})
|
||||
|
||||
|
||||
@sentinel_router.put("/record/{id}")
|
||||
async def update_sentinel_record(
|
||||
id: str, data: dict, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
count = update_sentinel_record_db(id, data)
|
||||
if count == 0:
|
||||
return BaseResponse(status=False, message="记录不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@sentinel_router.patch("/record/{id}")
|
||||
async def patch_sentinel_record(
|
||||
id: str, data: dict, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
count = patch_sentinel_record_db(id, data)
|
||||
if count == 0:
|
||||
return BaseResponse(status=False, message="记录不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@sentinel_router.delete("/record/{id}")
|
||||
async def delete_sentinel_record(
|
||||
id: str, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
deleted = delete_sentinel_record_db(id)
|
||||
if deleted == 0:
|
||||
return BaseResponse(status=False, message="记录不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
+118
-19
@@ -1,4 +1,4 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
|
||||
from config.security import get_user_id_from_token
|
||||
from db.postgres.system import *
|
||||
@@ -60,7 +60,7 @@ async def dept_update(
|
||||
|
||||
parent_id = data.get("pid")
|
||||
name = data.get("name")
|
||||
comment = data.get("comment")
|
||||
comment = data.get("remark")
|
||||
|
||||
rowcount = update_dept(id, parent_id, name, comment)
|
||||
if rowcount == 0:
|
||||
@@ -294,12 +294,11 @@ async def delete_role(
|
||||
@systemRouter.get("/user/name-exists")
|
||||
async def user_name_exists(
|
||||
username: str,
|
||||
id: str | None = None,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
exists = db_user_name_exists(username, id)
|
||||
exists = db_user_name_exists(username)
|
||||
return BaseResponse(data=exists)
|
||||
|
||||
|
||||
@@ -333,21 +332,6 @@ async def create_user(data: dict, user_id: UUID = Depends(get_user_id_from_token
|
||||
return BaseResponse(data={"id": new_id})
|
||||
|
||||
|
||||
@systemRouter.put("/user/{id}")
|
||||
async def update_user(
|
||||
id: str,
|
||||
data: dict,
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
count = update_user_db(id, data)
|
||||
if count == 0:
|
||||
return BaseResponse(status=False, message="用户不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@systemRouter.patch("/user/{id}")
|
||||
async def patch_user(
|
||||
id: str,
|
||||
@@ -375,3 +359,118 @@ async def delete_user(
|
||||
if deleted == 0:
|
||||
return BaseResponse(status=False, message="用户不存在", data=None)
|
||||
return BaseResponse(data=True)
|
||||
|
||||
|
||||
@systemRouter.get("/dict/list")
|
||||
def getScVideoList(
|
||||
user_id: UUID = Depends(get_user_id_from_token),
|
||||
name: str = "",
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(10, ge=1, le=100),
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
total, items = get_dict_list(name, page=page, page_size=page_size)
|
||||
return BaseResponse(
|
||||
data={
|
||||
"total": total,
|
||||
"items": items,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@systemRouter.post("/dict")
|
||||
def create_dict_api(data: dict, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
"""
|
||||
创建字典接口
|
||||
data = { "key": str, "name": str, "remark": str }
|
||||
"""
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
new_id = db_create_dict(data.get("key"), data.get("name"), data.get("remark"))
|
||||
return BaseResponse(data={"id": new_id})
|
||||
|
||||
|
||||
@systemRouter.put("/dict/{id}")
|
||||
def update_dict_api(
|
||||
id: str, data: dict, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
"""
|
||||
更新字典接口
|
||||
"""
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
db_update_dict(id, data.get("key"), data.get("name"), data.get("remark"))
|
||||
return BaseResponse(data={"id": id})
|
||||
|
||||
|
||||
@systemRouter.delete("/dict/{id}")
|
||||
def delete_dict_api(id: str, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
"""
|
||||
删除字典接口
|
||||
"""
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
|
||||
db_delete_dict(id)
|
||||
return BaseResponse(data={"id": id})
|
||||
|
||||
|
||||
@systemRouter.get("/dict/detail/list")
|
||||
def get_dict_detail_api(dictId: str, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
items = db_get_dict_detail(dictId)
|
||||
return BaseResponse(data={"list": items})
|
||||
|
||||
|
||||
@systemRouter.post("/dict/detail")
|
||||
def create_dict_detail_api(data: dict, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
new_id = db_create_dict_detail(
|
||||
value=data.get("value"),
|
||||
dict_id=data.get("dict_id"),
|
||||
sort=data.get("sort", 0),
|
||||
pid=data.get("pid"),
|
||||
remark=data.get("remark"),
|
||||
)
|
||||
return BaseResponse(data={"id": new_id})
|
||||
|
||||
|
||||
@systemRouter.put("/dict/detail/{id}")
|
||||
def update_dict_detail_api(
|
||||
id: str, data: dict, user_id: UUID = Depends(get_user_id_from_token)
|
||||
):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
db_update_dict_detail(
|
||||
id=id,
|
||||
value=data.get("value"),
|
||||
sort=data.get("sort"),
|
||||
pid=data.get("pid"),
|
||||
remark=data.get("remark"),
|
||||
)
|
||||
return BaseResponse(data={"id": id})
|
||||
|
||||
|
||||
@systemRouter.delete("/dict/detail/{id}")
|
||||
def delete_dict_detail_api(id: str, user_id: UUID = Depends(get_user_id_from_token)):
|
||||
if not user_id:
|
||||
return {"error": "userId is required"}
|
||||
db_delete_dict_detail(id)
|
||||
return BaseResponse(data={"id": id})
|
||||
|
||||
|
||||
@systemRouter.get("/dict/getValue")
|
||||
def get_dict_detail_by_key(
|
||||
key: str = Query(..., min_length=1),
|
||||
):
|
||||
if not key:
|
||||
return {"error": "key is required"}
|
||||
|
||||
items = get_dict_detail_list_by_key(key)
|
||||
|
||||
return BaseResponse(data=items)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
from fastapi import APIRouter
|
||||
from starlette.websockets import WebSocket, WebSocketDisconnect
|
||||
|
||||
from db.postgres.ws_manager import ConnectionManager
|
||||
|
||||
ws_manager = ConnectionManager()
|
||||
|
||||
|
||||
iot_ws_router = APIRouter()
|
||||
|
||||
|
||||
@iot_ws_router.websocket("/device-status")
|
||||
async def websocket_device_status(websocket: WebSocket):
|
||||
await ws_manager.connect(websocket)
|
||||
print("[WS] client connected")
|
||||
|
||||
try:
|
||||
while True:
|
||||
# 这里不需要接收任何消息
|
||||
await websocket.receive_text()
|
||||
except WebSocketDisconnect:
|
||||
await ws_manager.disconnect(websocket)
|
||||
print("[WS] client disconnected")
|
||||
Reference in New Issue
Block a user