kangda/app/crud/event.py

638 lines
21 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import List, Optional, Dict, Any
from sqlalchemy import select, and_, or_, update, bindparam, func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.crud.base import CRUDBase
from app.models.models import Event, Image, RobotInfo, Temperature, Message, Robot, Task
from app.schemas.event import AllMessageDto, EventUpdate, EventQuery, BackStageEvent, BackStageEventDto, BackStageEventDetail, EditTemperatureDto, OcrAlertMessage, OcrAlertMessageDto, GetRobotDto, CommonAlertMessage, GetAllMessageDto, TaskListDto
from pydantic import VERSION as PYDANTIC_VERSION
from datetime import datetime, timedelta, timezone
# from app.util import kangda
class CRUDEvent(CRUDBase[Event, EventUpdate, EventUpdate]):
async def get_by_id(self, db: AsyncSession, *, event_id: str) -> Optional[Event]:
"""根据ID获取事件"""
query = (
select(Event)
.options(
selectinload(Event.images),
selectinload(Event.temperatures)
)
.where(Event.eventId == event_id)
)
result = await db.execute(query)
return result.scalar_one_or_none()
async def get_event_detail(
self,
db: AsyncSession,
*,
eventId: str
) -> Optional[BackStageEventDetail]:
stmt = (select(Event.eventId, Event.number, Event.name,Image.imageUrl, Image.localPath, Temperature.temperature,Temperature.confidence, Temperature.status, Temperature.createTime).
select_from(Event).
outerjoin(Image, Image.eventId == Event.eventId).
outerjoin(Temperature, Event.eventId==Temperature.eventId).
where(Event.eventId==eventId)
)
result = await db.execute(stmt)
result = result.mappings().first()
return result
async def get_ocr_result(
self,
db: AsyncSession,
) -> List[BackStageEvent]:
"""获取所有仪表识别结果"""
stmt = (
select(Event.eventId, Event.number, Event.name, Image.imageUrl, Image.localPath, Temperature.temperature, Temperature.confidence, Temperature.createTime, Temperature.status)
.select_from(Temperature)
.outerjoin(Event, Event.eventId==Temperature.eventId)
.outerjoin(Image, Image.imageId == Temperature.imageId)
.order_by(Temperature.createTime.desc())
)
results = await db.execute(stmt)
results = results.mappings().all()
back = list()
for result in results:
back.append(BackStageEvent(**result))
return back
async def get_multi_backstage_events(
self,
db: AsyncSession,
*,
query: BackStageEventDto
) -> List[BackStageEvent]:
"""后台根据条件获取事件列表"""
conditions = []
if query.eventId is not None and len(query.eventId) > 0:
conditions.append(Event.eventId==query.eventId)
if query.number is not None and len(query.number) > 0:
conditions.append(Event.number == query.number)
if query.name is not None and len(query.name) > 0:
conditions.append(Event.name == query.name)
if query.status is not None and len(query.status) > 0:
conditions.append(Temperature.status == query.status)
if query.start_time is not None:
conditions.append(Temperature.createTime >= query.start_time)
if query.end_time is not None:
conditions.append(Temperature.createTime <= query.end_time)
stmt = (
select(Event.eventId, Event.number, Event.name, Image.imageUrl, Image.localPath, Temperature.temperature, Temperature.confidence, Temperature.createTime, Temperature.status)
.select_from(Temperature)
.outerjoin(Event, Event.eventId==Temperature.eventId)
.outerjoin(Image, Image.imageId == Temperature.imageId)
.where(*conditions)
.order_by(Temperature.createTime.desc())
.offset(query.skip)
.limit(query.limit)
)
results = await db.execute(stmt)
results = results.mappings().all()
back = list()
for result in results:
# if result["temperature"] is not None:
back.append(BackStageEvent(**result))
return back
async def get_multi_with_query(
self,
db: AsyncSession,
*,
query: EventQuery
) -> List[Event]:
"""根据查询条件获取事件列表"""
conditions = []
if query.start_time:
conditions.append(Event.insDate >= query.start_time)
if query.end_time:
conditions.append(Event.insDate <= query.end_time)
if query.etypeName:
conditions.append(Event.etypeName == query.etypeName)
if query.area:
conditions.append(Event.area == query.area)
query_stmt = (
select(Event)
.options(
selectinload(Event.images),
selectinload(Event.temperatures)
)
)
if conditions:
query_stmt = query_stmt.where(and_(*conditions))
query_stmt = query_stmt.offset(query.skip).limit(query.limit)
result = await db.execute(query_stmt)
return result.scalars().all()
async def update_event(
self,
db: AsyncSession,
*,
event_id: str,
obj_in: EditTemperatureDto
) -> Optional[Event]:
"""更新事件信息"""
dict_values = dict()
if PYDANTIC_VERSION.startswith("2."):
field_names = list(EditTemperatureDto.model_fields.keys())
else:
field_names = list(EditTemperatureDto.__fields__.keys())
for key in field_names:
value = getattr(obj_in, key)
if value is not None:
dict_values[key] = value
try:
update_stmt = (
update(Temperature).where(Temperature.eventId == event_id).values(**dict_values)
)
await db.execute(update_stmt)
await db.commit()
return True
except:
return False
# event = await self.get_by_id(db, event_id=event_id)
# if not event:
# return None
# update_data = obj_in.model_dump()
# for field, value in update_data.items():
# setattr(event, field, value)
# # db.add(event)
# await db.commit()
# await db.refresh(event)
# return event
async def delete_event(
self,
db: AsyncSession,
*,
event_id: str
) -> Optional[Event]:
"""删除事件"""
event = await self.get_by_id(db, event_id=event_id)
if not event:
return None
await db.delete(event)
await db.commit()
return event
async def get_messages(
self,
db: AsyncSession,
skip:int,
limit:int,
condition: list = []
) -> Optional[List[OcrAlertMessage]]:
query_stmt = (
select(Message.messageId,Message.eventId ,Message.messageType, Message.eventType, Message.handle, Message.remark, Message.createTime,
Event.number,Event.name,
# Image.imageUrl, Image.localPath,
Temperature.temperature)
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
# .outerjoin(Image, Message.eventId == Image.eventId)
.outerjoin(Temperature, Message.eventId == Temperature.eventId)
.where(*condition)
.order_by(Message.createTime.desc())
.offset(skip)
.limit(limit)
)
messages = await db.execute(query_stmt)
messages = messages.mappings().all()
back = list()
for message in messages:
# 获取图片URL列表
query_image_stmt = (
select(Image.imageUrl)
.where(Image.eventId == message.get("eventId"))
)
images = await db.execute(query_image_stmt)
images = images.mappings().all()
# 将RowMapping转换为字典
message_dict = dict(message)
# 将图片URL列表转换为普通列表
image_urls = [dict(img)["imageUrl"] for img in images]
message_dict["imageUrl"] = image_urls
ocrAlertMessage = OcrAlertMessage(**message_dict)
back.append(ocrAlertMessage)
return back
async def get_messages_front(
self,
db: AsyncSession,
skip:int,
limit:int,
condition: list = []
) -> Optional[List[OcrAlertMessage]]:
query_stmt = (
select(Message.messageId,Message.eventId ,Message.messageType, Message.eventType, Message.handle, Message.remark, Message.createTime,
Event.number,Event.name,
# Image.imageUrl, Image.localPath,
RobotInfo.flvPtz, RobotInfo.flvTherm, RobotInfo.flvThermLight,
Temperature.temperature)
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
# .outerjoin(Image, Message.eventId == Image.eventId)
.outerjoin(RobotInfo, RobotInfo.number == Event.number)
.outerjoin(Temperature, Message.eventId == Temperature.eventId)
.where(*condition)
.order_by(Message.createTime.desc())
.offset(skip)
.limit(limit)
)
messages = await db.execute(query_stmt)
messages = messages.mappings().all()
back = list()
for message in messages:
# 获取图片URL列表
query_image_stmt = (
select(Image.imageUrl)
.where(Image.eventId == message.get("eventId"))
)
images = await db.execute(query_image_stmt)
images = images.mappings().all()
# 将RowMapping转换为字典
message_dict = dict(message)
# 将图片URL列表转换为普通列表
image_urls = [dict(img)["imageUrl"] for img in images]
message_dict["imageUrl"] = image_urls
commonAlertMessage = CommonAlertMessage(**message_dict)
back.append(commonAlertMessage)
return back
async def get_all_alert_message(
self,
db: AsyncSession,
number: str,
offset: int,
limit: int
):
"""
获取机器人所有的告警
"""
query_stmt = (
select(Message.messageId, Message.handle, Message.remark, Message.eventId,Message.createTime,Event.number, Event.name, Event.etypeName)
.select_from(Message)
.outerjoin(Event, Message.eventId==Event.eventId)
.where(Event.number == number)
.order_by(Message.createTime.desc())
.offset(offset)
.limit(limit)
)
results = await db.execute(query_stmt)
results = results.mappings().all()
data = list()
for result in results:
t = AllMessageDto(**result)
query_image_stmt = (
select(Image.imageUrl)
.where(Image.eventId == result.eventId)
)
image_list = await db.execute(query_image_stmt)
image_list = image_list.scalars().all()
t.imageList = image_list
t.imagePreview = image_list[0]
data.append(t)
return data
async def handle_ocr_alerts(
self,
db:AsyncSession,
messageIdList: List[int]
):
"""处理OCR告警消息
Args:
db: 数据库会话
messageIdList: 要处理的messageId列表
Returns:
bool: 更新是否成功
"""
try:
# 获取所有需要更新的消息ID
# 构建更新语句
update_stmt = (
update(Message)
.where(Message.messageId.in_(messageIdList))
.values(
handle="1",
updateTime=datetime.now()
)
)
# 准备更新数据
# 执行更新
await db.execute(
update_stmt,
# update_data,
execution_options={"synchronize_session": False}
)
await db.commit()
return True
except Exception as e:
print(f"更新OCR告警消息失败: {str(e)}")
await db.rollback()
return False
async def handle_ocr_alerts_get(
self,
db: AsyncSession,
number: Optional[str] = None
):
try:
if number and len(number) > 0:
update_stmt = (
update(Message)
.values(
handle="1",
updateTime=datetime.now()
)
.where(Message.eventId == Event.eventId) # JOIN 条件放在 where()
.where(Event.number == number) # 过滤条件
.where(Message.handle == "0") # 过滤条件
)
print(number, "number")
else:
update_stmt = (
update(Message)
.where(Message.handle == "0")
.values(
handle = "1",
updateTime=datetime.now()
)
)
# 执行更新
await db.execute(
update_stmt,
execution_options={"synchronize_session": False}
)
await db.commit()
return True
except Exception as e:
print(f"更新告警消息失败: {str(e)}")
await db.rollback()
return False
async def handle_ocr_alert(
self,
db: AsyncSession,
ocrAlertMessageDto: OcrAlertMessageDto,
):
try:
if ocrAlertMessageDto.number and len(ocrAlertMessageDto.number) > 0:
update_stmt = (
update(Message)
.where(Message.eventId == Event.eventId)
.where(Event.number == ocrAlertMessageDto.number)
.where(Message.messageId == ocrAlertMessageDto.messageId)
.values(
handle = "1",
remark = ocrAlertMessageDto.remark,
updateTime=datetime.now()
)
)
else:
update_stmt = (
update(Message)
.where(Message.messageId == ocrAlertMessageDto.messageId)
.values(
handle = "1",
remark = ocrAlertMessageDto.remark,
updateTime=datetime.now()
)
)
await db.execute(update_stmt)
await db.commit()
return True
except Exception as e:
print(f"处理单个消息失败: {e}")
await db.rollback()
return False
async def get_alert_detail(
self,
db: AsyncSession,
messageId: int
) ->Optional[OcrAlertMessage]:
try:
select_stmt = (
select(Message.messageId,Message.eventId ,Message.messageType, Message.eventType, Message.handle, Message.remark, Message.createTime,
Event.number,Event.name,
Image.imageUrl, Image.localPath,
Temperature.temperature)
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
.outerjoin(Image, Message.eventId == Image.eventId)
.outerjoin(Temperature, Message.eventId == Temperature.eventId)
.where(Message.messageId == messageId)
)
result = await db.execute(select_stmt)
message = result.mappings().first()
if message:
# 获取图片URL列表
query_image_stmt = (
select(Image.imageUrl)
.where(Image.eventId == message.get("eventId"))
)
images = await db.execute(query_image_stmt)
images = images.mappings().all()
# 将RowMapping转换为字典
message_dict = dict(message)
# 添加图片URL列表
message_dict["imageUrl"] = images
return OcrAlertMessage(**message_dict)
return None
except Exception as e:
print(f"获取告警详情失败: {e}")
return None
async def get_alert_count(
self,
db: AsyncSession,
handle: str,
number: Optional[str] = None
):
try:
query_stmt = (
select(func.count(Message.messageId))
.select_from(Message)
.outerjoin(Event, Message.eventId == Event.eventId)
.where(and_(Message.handle == handle, (Event.number==number) if number else True))
)
result = await db.execute(query_stmt)
return result.scalar()
except Exception as e:
print(f"{e}")
async def get_robot_count(
self,
db: AsyncSession,
*, # 关键字参数分隔符,代表后面的参数一定要用关键字指定
status: list
):
try:
query_stmt = (
select(func.count(Robot.robotId))
.where(*status)
)
result = await db.execute(query_stmt)
return result.scalar()
except Exception as e:
print(f"{e}")
async def get_etype_name_list(
self,
db: AsyncSession
):
query_stmt = (
select(Event.etypeName)
.group_by(Event.etypeName)
)
results = await db.execute(query_stmt)
return results.scalars().all()
async def get_robot_task(
self,
db: AsyncSession,
robotId: Optional[str] = None
):
try:
# print("robotId", robotId)
query_stmt = (
select(Task.robotId, Task.taskName, Task.times).where(Task.robotId == robotId)
)
results = await db.execute(query_stmt)
results = results.mappings().all()
data = list()
for result in results:
t = TaskListDto(**result)
t.status = "0"
times = t.times.split(",")
for time in times:
if self.is_current_time_in_interval(time):
t.status = "1"
break
data.append(t)
return data
except Exception as e:
print(f"{e}")
async def get_messages_st(
self,
db: AsyncSession,
day: int
):
try:
now = datetime.now(timezone.utc)
start_time = now - timedelta(days=day)
query_stmt = (
select(
Message.eventType,
func.count(Message.eventType).label("count"))
.where(and_(start_time<=Message.createTime, Message.createTime <= now))
.group_by(Message.eventType)
)
result = await db.execute(query_stmt)
return [
{"eventType": row.eventType, "count": row.count}
for row in result
]
except Exception as e:
print(f"{e}")
def is_current_time_in_interval(self, interval):
"""检查当前时间是否在指定的时间区间内"""
# 获取当前时间字符串(格式 HH:MM
current = datetime.now().strftime('%H:%M')
# 拆分时间区间字符串
start, end = interval.split(' - ')
# 直接比较时间字符串24小时制时间字符串可直接比较
return start <= current <= end
# async def get_robot_list(
# self,
# db: AsyncSession,
# get_robot_dto: GetRobotDto
# ):
# # 前端登录
# d = kangda._login_front()
# duty_list = kangda._get_robot_group(d["tenantInfoId"], d["token"])
event = CRUDEvent(Event)