kangda/app/api/v1/endpoints/events.py

582 lines
22 KiB
Python

from operator import and_, ge
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Body
# from paddle import normal
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.crud.event import event
from app.models.models import Robot, Message, RobotInfo,Group, GroupRobot, Event
from app.schemas.event import EventList, EventDetail, EventUpdate, EventQuery, BackStageEvent, BackStageEventDto, BackStageEventDetail, EditTemperatureDto, OcrAlertMessage, OcrAlertMessageDto, GetRobotDto, CommonAlertMessage, GetAllMessageDto
from app.util.httpResponse import BaseResponse
from app.util.status import EventType, etypeNameDict
from sqlalchemy import func, select
from app.services.robot_sync_service import robot_sync_service
# import datetime
router = APIRouter()
# @router.get("/events", response_model=List[EventList])
# async def get_events(
# db: AsyncSession = Depends(get_db),
# start_time: Optional[str] = None,
# end_time: Optional[str] = None,
# etypeName: Optional[str] = None,
# area: Optional[str] = None,
# skip: int = Query(0, ge=0),
# limit: int = Query(100, ge=1, le=1000)
# ):
# """
# 获取事件列表
# - 支持时间范围查询
# - 支持事件类型和区域筛选
# - 支持分页
# """
# query = EventQuery(
# start_time=start_time,
# end_time=end_time,
# etypeName=etypeName,
# area=area,
# skip=skip,
# limit=limit
# )
# events = await event.get_multi_with_query(db, query=query)
# return [EventList.model_validate(event) for event in events]
# 后台获取事件列表
# @router.post("/backstageEventlist", response_model=List[BackStageEvent])
@router.post("/backstageEventlist", response_model=BaseResponse[List[BackStageEvent]])
async def get_events_backstage(
db: AsyncSession = Depends(get_db),
query: BackStageEventDto = Body(...)
):
events = await event.get_multi_backstage_events(db, query=query)
return BaseResponse(code=200, msg="success", data=events)
# 后台获取事件详情
@router.get("/backstageEventDetail/{eventId}", response_model=BaseResponse[BackStageEventDetail])
async def get_event_detail(
eventId: str,
db: AsyncSession = Depends(get_db)
):
back = await event.get_event_detail(db=db, eventId=eventId)
return BaseResponse(code = 200, msg="success", data=back)
# @router.get("/events/{event_id}", response_model=EventDetail)
# async def get_event(
# event_id: str,
# db: AsyncSession = Depends(get_db)
# ):
# """
# 获取事件详情
# """
# event_obj = await event.get_by_id(db, event_id=event_id)
# if not event_obj:
# raise HTTPException(status_code=404, detail="事件不存在")
# return EventDetail.model_validate(event_obj)
@router.put("/events/{event_id}", response_model=BaseResponse)
async def update_event(
event_id: str,
event_in: EditTemperatureDto,
db: AsyncSession = Depends(get_db)
):
"""
更新事件信息
"""
event_obj = await event.update_event(
db,
event_id=event_id,
obj_in=event_in
)
if not event_obj:
raise BaseResponse(code=404, msg="事件不存在")
return BaseResponse(code=200, msg="success")
@router.delete("/events/{event_id}", response_model=BaseResponse[EventDetail])
async def delete_event(
event_id: str,
db: AsyncSession = Depends(get_db)
):
"""
删除事件
"""
event_obj = await event.delete_event(db, event_id=event_id)
if not event_obj:
return BaseResponse(code=404,msg="事件不存在")
return BaseResponse(code=200, msg="success", data=EventDetail.model_validate(event_obj))
@router.post("/event/getRobotList", response_model=BaseResponse)
async def get_robot_list(
get_robot_dto: Optional[GetRobotDto] = Body(...),
db: AsyncSession = Depends(get_db)
):
"""
获取机器人列表
"""
try:
# 查询所有分组
conditions = []
if get_robot_dto.tenantInfoId and len(get_robot_dto.tenantInfoId) > 0:
conditions.append(Group.tenantInfoId == get_robot_dto.tenantInfoId)
group_query = (
select(Group.name)
.where(*conditions)
)
group_list = await db.execute(group_query)
group_list = group_list.scalars().all()
result_dict = dict()
# 分组查询
for group_name in group_list:
# 构建查询条件
conditions = []
conditions.append(Group.name == group_name)
if get_robot_dto.number and len(get_robot_dto.number) > 0:
conditions.append(Robot.number.like(f"%{get_robot_dto.number}%"))
if get_robot_dto.status and len(get_robot_dto.status) > 0:
conditions.append(Robot.status == get_robot_dto.status)
if get_robot_dto.onlineStatus and len(get_robot_dto.onlineStatus) > 0:
conditions.append(Robot.onlineStatus == get_robot_dto.onlineStatus)
# if get_robot_dto.name and len(get_robot_dto.name) > 0:
# conditions.append(Group.name == get_robot_dto.name)
# 查询机器人列表
query = (
select(Robot, RobotInfo, Group)
.outerjoin(RobotInfo, Robot.robotId == RobotInfo.robotId)
.outerjoin(GroupRobot, Robot.robotId == GroupRobot.robotId)
.outerjoin(Group, GroupRobot.groupingId == Group.groupingId)
)
if conditions:
query = query.where(*conditions)
result = await db.execute(query)
robots = result.all()
# 格式化返回数据
robot_list = []
for robot, robot_info, group in robots:
# 查询告警数量, 高温感知报警为一级报警, 其余为二级报警.
count_1 = 0
query_1 = (
select(func.count())
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
.where(Message.handle=="0", Message.eventType=="1", Event.number == robot.number)
)
count_1 = await db.execute(query_1)
count_1 = count_1.scalar_one_or_none()
count_o = 0
if count_1 == 0:
query_o = (
select(func.count())
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
.where(Message.handle=="0", Message.eventType!="1", Event.number == robot.number)
)
count_o = await db.execute(query_o)
count_o = count_o.scalar_one_or_none()
if count_1 > 0:
tag = 1
elif count_o > 0:
tag = 2
else:
tag = 0
robot_dict = {
"robotId": robot.robotId,
"number": robot.number,
"groupingId": robot.groupingId,
"onlineStatus": robot.onlineStatus,
"status": robot.status,
"groupName": group.name if group else None,
"robotInfo": {
"temperature": robot_info.temperature if robot_info else None,
"humidity": robot_info.humidity if robot_info else None,
"power": robot_info.power if robot_info else None,
"mileage": robot_info.mileage if robot_info else None,
"area": robot_info.area if robot_info else None,
"floor": robot_info.floor if robot_info else None,
"map": robot_info.map if robot_info else None,
"positon": robot_info.positon if robot_info else None,
"status": robot_info.status if robot_info else None,
"ststusName": robot_info.ststusName if robot_info else None,
"updateTime": robot_info.updateTime if robot_info else None,
"tag": tag
}
}
robot_list.append(robot_dict)
result_dict[group_name] = robot_list
return BaseResponse(code=200, msg="success", data=result_dict)
except Exception as e:
print(f"获取机器人列表失败: {str(e)}")
return BaseResponse(code=500, msg="获取机器人列表失败")
@router.post("/event/refreshRobotList", response_model=BaseResponse)
async def refresh_robot_list(
db: AsyncSession = Depends(get_db)
):
"""
刷新机器人列表
"""
try:
# 手动触发数据同步
success = await robot_sync_service.sync_robot_data(db)
if success:
return BaseResponse(code=200, msg="刷新成功")
return BaseResponse(code=500, msg="刷新失败")
except Exception as e:
print(f"刷新机器人列表失败: {str(e)}")
return BaseResponse(code=500, msg="刷新失败")
# 获取未处理告警消息列表
@router.get("/events/messagesUnhandled",
# response_model=BaseResponse[dict]
)
async def get_messages_unhandle(
number: Optional[str]=None,
etypeName: Optional[str] = None,
db: AsyncSession = Depends(get_db),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000)
):
"""_summary_
获取告警消息列表
"""
data = await get_message_by_event_type(db, "0", skip, limit, number, etypeName)
return BaseResponse(code=200, msg="success", data=data)
# 获取已处理告警消息列表
@router.get("/events/messagesHandled",
# response_model=BaseResponse[dict]
)
async def get_messages_handle_robot(
number: Optional[str]=None,
etypeName: Optional[str] = None,
db: AsyncSession = Depends(get_db),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000)
):
data = await get_message_by_event_type(db, "1", skip, limit, number, etypeName)
return BaseResponse(code=200, msg="success", data=data)
# 批量处理告警数据--传递messageId List
@router.post("/events/handleOcrAlerts", response_model=BaseResponse)
async def handle_ocr_alerts(
number:Optional[str] = None,
db: AsyncSession = Depends(get_db),
messageIdList: List[int] = Body(...)
):
"""_summary_
一建处理告警
"""
flag = await event.handle_ocr_alerts(db, messageIdList=messageIdList)
if flag:
return BaseResponse(code=200, msg="success")
return BaseResponse(code=500, msg="fail to update data")
# 批量处理告警数据--直接将 handle=0的置为1
@router.get("/events/handleOcrAlerts", response_model=BaseResponse)
async def handle_ocr_alerts_get(
number:Optional[str] = None,
db: AsyncSession = Depends(get_db)
):
"""_summary_
一键处理告警
Args:
db (AsyncSession, optional): _description_. Defaults to Depends(get_db).
Returns:
_type_: _description_
"""
flag = await event.handle_ocr_alerts_get(db, number)
if flag:
return BaseResponse(code=200, msg="success")
return BaseResponse(code=500, msg="fail to update data")
# 处理单个告警数据
@router.post("/events/handleOcrAlert", response_model=BaseResponse)
async def handle_ocr_alert(
db: AsyncSession = Depends(get_db),
ocrAlertMessageDto: OcrAlertMessageDto = Body(...)
):
"""
处理单个警告
"""
flag = await event.handle_ocr_alert(db, ocrAlertMessageDto=ocrAlertMessageDto)
if flag:
return BaseResponse(code=200, msg="success")
return BaseResponse(code=500, msg="fail to update data")
# 获取消息的统计数据
@router.get("/events/stMessages/{day}", )
async def get_messages_st(
day: int,
db: AsyncSession = Depends(get_db),
):
data = await event.get_messages_st(db, day)
return BaseResponse(code=200, msg="success", data=data)
# 查看告警详情
@router.get("/events/alert/{messageId}", response_model=BaseResponse[OcrAlertMessage])
async def get_alert_detail(
messageId:int,
db: AsyncSession = Depends(get_db),
):
# alert_message = await event.get_alert_detail(db, messageId=messageId)
alert_message = await event.get_messages(db, skip=0, limit=1, condition=[Message.messageId==messageId])
return BaseResponse(code=200, msg="success", data=alert_message[0])
# 前端查看告警详情
@router.get("/events/alertFront/{messageId}", response_model=BaseResponse[OcrAlertMessage])
async def get_alert_front_detail(
messageId:int,
# number: Optional[str] = None,
db: AsyncSession = Depends(get_db),
):
# alert_message = await event.get_alert_detail(db, messageId=messageId)
alert_message = await event.get_messages_front(db, skip=0, limit=1, condition=[Message.messageId==messageId])
return BaseResponse(code=200, msg="success", data=alert_message[0])
# 查看全部告警事件详情--属于该机器人的
@router.get("/events/getAllAlertMessage/{number}")
async def get_all_alert_message(
number: str,
db: AsyncSession = Depends(get_db),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000)
):
data = await event.get_all_alert_message(db, number, skip, limit)
return BaseResponse(
code = 200,
msg = "success",
data = data
)
# 获取未处理告警消息数量
@router.get("/events/alertCount", response_model=BaseResponse)
async def get_alert_count(
number: Optional[str] = None,
db: AsyncSession = Depends(get_db)
):
# 未处理告警数量
alert_count = await event.get_alert_count(db, handle="0", number=number)
# 已处理告警数量
processed_count = await event.get_alert_count(db, handle="1", number=number)
# 所有告警数量
all_count = alert_count + processed_count
return BaseResponse(code=200, msg="success", data={
"alert_count": alert_count,
"processed_count": processed_count,
"all_count": all_count
})
# 获取厂区及机器人实时监控
@router.get("/events/getMonitor")
async def get_monitor():
t = {
"厂区监控1":{
"A区厂区监控":[
"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
],
"B区厂区监控":[
"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
""
],
"C区厂区监控":[
"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
]
},
"厂区监控2":{
"D区厂区监控":[
"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
],
"E区厂区监控":[
"",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
]
},
"厂区监控3":{
"F区厂区监控":[
"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
],
"G区厂区监控":[
"",
"https://play.livejinan.cn/21ZoxrLa/45ee42a7b9d64400963d6bacc9a75867.m3u8?auth_key=1893340800-0-0-3522915cd5471437682295596e73cac2"
]
},
"室外巡检":{
"robot1":[
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041301_34020000001320000001",
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041302_34020000001320000002",
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041302_34020000001320000001"
],
"robot2":[
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041301_34020000001320000001",
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041302_34020000001320000002",
"webrtc://qvs-live.thirdmonitor.concoai.com:447/2xenzwqy2ppcl/31011500991180041302_34020000001320000001"
]
},
}
return BaseResponse(code=200, msg="success",data=t)
# 获取机器人统计信息
@router.get("/events/robotST", response_model=BaseResponse[dict])
async def get_robot_st(
db: AsyncSession = Depends(get_db)
):
# 机器人总数
t_count = await event.get_robot_count(db, status=[])
# 在线总数
online_count = await event.get_robot_count(db, status=[Robot.onlineStatus=="1", Robot.status=="0"])
# 离线总数
offline_count = await event.get_robot_count(db, status=[Robot.onlineStatus=="2", Robot.status=="0"])
# 故障总数
disable_count = await event.get_robot_count(db, status=[Robot.status=="1"])
return BaseResponse(code=200, msg="success",
data = {
"t_count": t_count,
"online_count": online_count,
"offline_count": offline_count,
"disable_count": disable_count
})
# 获取事件类型下拉列表
@router.get("/events/getEtypeNameList")
async def get_etype_name_list(
db: AsyncSession = Depends(get_db)
):
etype_name_list = await event.get_etype_name_list(db)
return BaseResponse(code=200, msg="success", data=etype_name_list)
# 获取仪表识别结果
@router.get("/events/getOcrResult")
async def get_ocr_result(
db: AsyncSession = Depends(get_db)
):
ocr_result = await event.get_ocr_result(db)
return BaseResponse(code=200, msg="success", data=ocr_result)
# 获取机器人任务列表
@router.get("/events/robotTask")
async def get_robot_task(
db: AsyncSession=Depends(get_db),
robotId: Optional[str]=None
):
# print("robotId: ", robotId)
task_list = await event.get_robot_task(db, robotId)
return BaseResponse(code="200", msg="success", data = task_list)
async def get_message_by_event_type(
db:AsyncSession ,
handle: str ,
skip: int ,
limit: int,
number: Optional[str]=None,
etypeName: Optional[str] = None
):
condition_robotId = []
if number and len(number) > 0:
condition_robotId.append( Event.number== number)
if etypeName and len(etypeName) > 0:
if etypeName in etypeNameDict:
print(etypeName, etypeNameDict[etypeName])
query_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==etypeNameDict[etypeName]] + condition_robotId)
return {
"query_message": query_message
}
else:
return {}
# 高温报警消息
high_temperature_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.HightTemperature.value] + condition_robotId)
smoke_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.SMOKE.value]+ condition_robotId)
long_stay_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.LONGSTAY.value]+ condition_robotId)
air_quality_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.AIRQUALITY.value]+ condition_robotId)
stop_emergency_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.STOPEMERGENCY.value]+ condition_robotId)
voice_connect_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.VOICENOTCONNECT.value]+ condition_robotId)
daily_inspect_message = await event.get_messages(db,
skip=skip,
limit=limit,
condition=[Message.handle==handle, Message.eventType==EventType.DAILYINSPECT.value]+ condition_robotId)
return {
"high_temperature_message": high_temperature_message,
"smoke_message": smoke_message,
"long_stay_message": long_stay_message,
"air_quality_message": air_quality_message,
"stop_emergency_message": stop_emergency_message,
"voice_connect_message": voice_connect_message,
"daily_inspect_message": daily_inspect_message,
}