Compare commits
15 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e95d009982 | 3 months ago |
|
|
662d683813 | 3 months ago |
|
|
94e5cd482b | 3 months ago |
|
|
7c144a33be | 3 months ago |
|
|
6a82e1fa8b | 3 months ago |
|
|
191ef60413 | 3 months ago |
|
|
675d2fad8f | 3 months ago |
|
|
5d58002118 | 3 months ago |
|
|
194dfcf2a3 | 3 months ago |
|
|
f98775a493 | 3 months ago |
|
|
8a15f1990f | 3 months ago |
|
|
60bf0ffaf1 | 3 months ago |
|
|
e181e42c44 | 3 months ago |
|
|
4647d9faa7 | 3 months ago |
|
|
6753312961 | 3 months ago |
@ -0,0 +1,40 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested
|
||||||
|
|
||||||
|
|
||||||
|
class IotAlertLog(db.Model, TimeModelMixin):
|
||||||
|
"""
|
||||||
|
告警日志表
|
||||||
|
"""
|
||||||
|
__tablename__ = "iot_alert_log"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
alert_tag = db.Column(db.String(255), nullable=False, comment="告警标签")
|
||||||
|
alert_target_name = db.Column(db.String(255), nullable=False, comment="告警对象名称")
|
||||||
|
alert_content = db.Column(db.String(2048), nullable=False, comment="告警文本")
|
||||||
|
alert_level = db.Column(db.Integer, nullable=False, comment="告警级别 0-预警,1-一般,2-紧急,3-严重")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=1, comment="状态 1-告警中,0-已恢复")
|
||||||
|
trigger_count = db.Column(db.Integer, nullable=False, default=0, comment="触发次数")
|
||||||
|
|
||||||
|
class IotAlertLogSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警日志表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotAlertLog"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
alert_tag = String()
|
||||||
|
alert_target_name = String()
|
||||||
|
alert_content = String()
|
||||||
|
alert_level = Integer()
|
||||||
|
status = Integer()
|
||||||
|
trigger_count = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
from ast import List
|
||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested, List
|
||||||
|
|
||||||
|
class IotAlertPush(TimeModelMixin, db.Model):
|
||||||
|
"""
|
||||||
|
告警推送表
|
||||||
|
"""
|
||||||
|
__tablename__ = "iot_alert_push"
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment="标识")
|
||||||
|
target_name = db.Column(db.String(255), nullable=False, comment="接收对象名称")
|
||||||
|
push_url = db.Column(db.String(2048), nullable=False, comment="告警推送URL")
|
||||||
|
alert_level = db.Column(db.String(255), nullable=False, comment="告警等级")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=1, comment="状态 1-启用,0-禁用")
|
||||||
|
|
||||||
|
|
||||||
|
class IotAlertPushSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警推送表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotAlertPush"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
target_name = String()
|
||||||
|
push_url = String()
|
||||||
|
alert_level = List(Integer())
|
||||||
|
status = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested
|
||||||
|
|
||||||
|
|
||||||
|
class IotAlertRule(db.Model, TimeModelMixin):
|
||||||
|
"""
|
||||||
|
告警规则表
|
||||||
|
"""
|
||||||
|
__tablename__ = "iot_alert_rule"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
rule_name = db.Column(db.String(255), nullable=False, comment="告警规则名称")
|
||||||
|
node_id = db.Column(db.Integer, nullable=False, comment="采集节点ID")
|
||||||
|
trigger_count = db.Column(db.Integer, nullable=False, comment="阈值触发次数,超过次数后告警")
|
||||||
|
alert_rule = db.Column(db.String(255), nullable=False, comment="告警触发表达式")
|
||||||
|
alert_text = db.Column(db.String(2048), nullable=False, comment="告警文本")
|
||||||
|
alert_level = db.Column(db.Integer, nullable=False, comment="告警级别 0-预警,1-一般,2-紧急,3-严重")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=1, comment="状态 1-启用,0-禁用")
|
||||||
|
|
||||||
|
class IotAlertRuleSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警规则表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotAlertRule"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
rule_name = String()
|
||||||
|
node_id = Integer()
|
||||||
|
trigger_count = Integer()
|
||||||
|
alert_rule = String()
|
||||||
|
alert_text = String()
|
||||||
|
alert_level = Integer()
|
||||||
|
status = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested
|
||||||
|
|
||||||
|
class IotDevice(db.Model, TimeModelMixin):
|
||||||
|
"""
|
||||||
|
设备信息表
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "iot_device"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
workshop_id = db.Column(db.Integer, nullable=False, default=0, unique=True, comment="车间ID")
|
||||||
|
device_name = db.Column(db.String(255), nullable=False, unique=True, comment="设备名称")
|
||||||
|
device_number = db.Column(db.String(20), nullable=False, comment="设备编号")
|
||||||
|
description = db.Column(db.Text, nullable=False, comment="设备描述")
|
||||||
|
brand_name = db.Column(db.String(255), nullable=False, comment="品牌名称")
|
||||||
|
specification_model = db.Column(db.String(255), nullable=False, comment="规格型号")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=0, comment="状态 0:已停机 1:生产中 2:维修中")
|
||||||
|
#关系
|
||||||
|
workshop = db.relationship(
|
||||||
|
"IotWorkshop",
|
||||||
|
primaryjoin="foreign(IotDevice.workshop_id) == IotWorkshop.id",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class IotDeviceSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
设备信息表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotDevice"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
workshop_id = Integer()
|
||||||
|
device_name = String()
|
||||||
|
device_number = String()
|
||||||
|
description = String()
|
||||||
|
brand_name = String()
|
||||||
|
specification_model = String()
|
||||||
|
status = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
#关系
|
||||||
|
workshop = Nested("IotWorkshopSimpleSchema")
|
||||||
|
|
||||||
|
class IotDeviceSimpleSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
设备信息表联合查询响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotDevice"
|
||||||
|
|
||||||
|
device_name = String()
|
||||||
|
device_number = String()
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested
|
||||||
|
|
||||||
|
|
||||||
|
class IotEndpoint(db.Model, TimeModelMixin):
|
||||||
|
"""
|
||||||
|
采集端信息表
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "iot_endpoint"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
endpoint_name = db.Column(db.String(255), nullable=False, unique=True, comment="采集端名称")
|
||||||
|
endpoint_number = db.Column(db.String(20), nullable=False, comment="采集端编号")
|
||||||
|
description = db.Column(db.Text, nullable=False, comment="采集端描述")
|
||||||
|
ip = db.Column(db.String(255), nullable=False, comment="采集端IP")
|
||||||
|
port = db.Column(db.String(255), nullable=False, comment="采集端端口")
|
||||||
|
opc_url_temp = db.Column(db.String(1024), nullable=False, comment="OPC URL模板")
|
||||||
|
brand_name = db.Column(db.String(255), nullable=False, comment="品牌名称")
|
||||||
|
specification_model = db.Column(db.String(255), nullable=False, comment="规格型号")
|
||||||
|
is_online = db.Column(db.Integer, nullable=False, default=0, comment="在线状态 0:离线 1:在线")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=0, comment="状态 0:停用 1:运行中 2:维修中")
|
||||||
|
|
||||||
|
|
||||||
|
class IotEndpointSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
采集端信息表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotEndpoint"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
endpoint_name = String()
|
||||||
|
endpoint_number = String()
|
||||||
|
description = String()
|
||||||
|
ip = String()
|
||||||
|
port = String()
|
||||||
|
opc_url_temp = String()
|
||||||
|
brand_name = String()
|
||||||
|
specification_model = String()
|
||||||
|
is_online = Integer()
|
||||||
|
status = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
|
||||||
|
class IotEndpointSimpleSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
采集端信息表联合查询响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotEndpoint"
|
||||||
|
|
||||||
|
endpoint_name = String()
|
||||||
|
endpoint_number = String()
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime, Nested
|
||||||
|
|
||||||
|
|
||||||
|
class IotNode(db.Model, TimeModelMixin):
|
||||||
|
"""
|
||||||
|
节点信息表
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "iot_node"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
workshop_id = db.Column(db.Integer, nullable=False, default=0, unique=True, comment="车间ID")
|
||||||
|
device_id = db.Column(db.Integer, nullable=False, default=0, unique=True, comment="设备ID")
|
||||||
|
endpoint_id = db.Column(db.Integer, nullable=False, default=0, unique=True, comment="采集端ID")
|
||||||
|
node_number = db.Column(db.String(20), nullable=False, unique=True, comment="节点编号")
|
||||||
|
title = db.Column(db.String(255), nullable=False, unique=True, comment="节点ID")
|
||||||
|
mark = db.Column(db.String(255), nullable=False, comment="采集标识")
|
||||||
|
mark_type = db.Column(db.Integer, nullable=False, comment="采集类型 1:只读 2:只写 3:读写")
|
||||||
|
tag_label = db.Column(db.String(255), nullable=False, comment="变量别名,用于数据存储标记")
|
||||||
|
data_type = db.Column(db.String(255), nullable=False, comment="值类型 text: 文本 int: 整型 float: 浮点型 boolean:布尔型")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=0, comment="状态 0:禁用 1:启用")
|
||||||
|
#关系
|
||||||
|
workshop = db.relationship(
|
||||||
|
"IotWorkshop",
|
||||||
|
primaryjoin="foreign(IotNode.workshop_id) == IotWorkshop.id",
|
||||||
|
)
|
||||||
|
device = db.relationship(
|
||||||
|
"IotDevice",
|
||||||
|
primaryjoin="foreign(IotNode.device_id) == IotDevice.id",
|
||||||
|
)
|
||||||
|
endpoint = db.relationship(
|
||||||
|
"IotEndpoint",
|
||||||
|
primaryjoin="foreign(IotNode.endpoint_id) == IotEndpoint.id",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class IotNodeSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
节点信息表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotNode"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
workshop_id = Integer()
|
||||||
|
device_id = Integer()
|
||||||
|
endpoint_id = Integer()
|
||||||
|
node_number = String()
|
||||||
|
title = String()
|
||||||
|
mark = String()
|
||||||
|
mark_type = Integer()
|
||||||
|
tag_label = String()
|
||||||
|
data_type = String()
|
||||||
|
status = Integer()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
#关系
|
||||||
|
workshop = Nested("IotWorkshopSimpleSchema")
|
||||||
|
device = Nested("IotDeviceSimpleSchema")
|
||||||
|
endpoint = Nested("IotEndpointSimpleSchema")
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.crud import TimeModelMixin, RemarkModelMixin
|
||||||
|
from iti.applications.common.utils import BaseSchema
|
||||||
|
from apiflask.fields import String, Integer, DateTime
|
||||||
|
|
||||||
|
class IotWorkshop(db.Model, TimeModelMixin, RemarkModelMixin):
|
||||||
|
"""
|
||||||
|
车间信息表
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "iot_workshop"
|
||||||
|
id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
comment="标识",
|
||||||
|
)
|
||||||
|
workshop_name = db.Column(db.String(255), nullable=False, unique=True, comment="车间名称")
|
||||||
|
workshop_number = db.Column(db.String(50), nullable=False, comment="车间编号")
|
||||||
|
total_area = db.Column(db.String(50), nullable=False, comment="总面积(单位:平方米)")
|
||||||
|
director_name = db.Column(db.String(30), nullable=False, comment="负责人姓名")
|
||||||
|
director_phone = db.Column(db.String(15), nullable=False, comment="负责人电话")
|
||||||
|
status = db.Column(db.Integer, nullable=False, default=0, comment="状态 0:已停用 1:生产中")
|
||||||
|
|
||||||
|
class IotWorkshopSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
车间信息表响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotWorkshop"
|
||||||
|
|
||||||
|
id = Integer()
|
||||||
|
workshop_name = String()
|
||||||
|
workshop_number = String()
|
||||||
|
total_area = String()
|
||||||
|
director_name = String()
|
||||||
|
director_phone = String()
|
||||||
|
status = Integer()
|
||||||
|
remark = String()
|
||||||
|
created_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
updated_at = DateTime(format="%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
class IotWorkshopSimpleSchema(BaseSchema):
|
||||||
|
"""
|
||||||
|
车间信息表联合查询响应结构
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
name = "IotWorkshop"
|
||||||
|
|
||||||
|
workshop_name = String()
|
||||||
|
workshop_number = String()
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from .workshop_ctl import bp as workshop_bp
|
||||||
|
from .device_ctl import bp as device_bp
|
||||||
|
from .endpoint_ctl import bp as endpoint_bp
|
||||||
|
from .node_ctl import bp as node_bp
|
||||||
|
from .alert_rule_ctl import bp as alert_rule_bp
|
||||||
|
from .alert_log_ctl import bp as alert_log_bp
|
||||||
|
from .alert_push_ctl import bp as alert_push_bp
|
||||||
|
|
||||||
|
iot_bp = APIBlueprint("iot", __name__, url_prefix="/iot")
|
||||||
|
|
||||||
|
|
||||||
|
def register_iot_bp(app):
|
||||||
|
iot_bp.register_blueprint(workshop_bp)
|
||||||
|
iot_bp.register_blueprint(device_bp)
|
||||||
|
iot_bp.register_blueprint(endpoint_bp)
|
||||||
|
iot_bp.register_blueprint(node_bp)
|
||||||
|
iot_bp.register_blueprint(alert_rule_bp)
|
||||||
|
iot_bp.register_blueprint(alert_log_bp)
|
||||||
|
iot_bp.register_blueprint(alert_push_bp)
|
||||||
|
|
||||||
|
app.register_blueprint(iot_bp)
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.service.iot.alert import (
|
||||||
|
add_endpoint_alert_log,
|
||||||
|
add_node_alert_log
|
||||||
|
)
|
||||||
|
from iti.applications.extensions import db
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotAlertLog,
|
||||||
|
IotAlertLogSchema,
|
||||||
|
)
|
||||||
|
from .schemas.alert_log import (
|
||||||
|
AlertLogQuery,
|
||||||
|
AlertLogAddRequest,
|
||||||
|
AlertLogUpdateRequest,
|
||||||
|
NodeAlertLogAddRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_alert_log", __name__, url_prefix="/alertLog", tag="告警中心")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertLog:list")
|
||||||
|
@bp.input(AlertLogQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotAlertLogSchema(many=True))
|
||||||
|
def list_alert_log(query_data: AlertLogQuery):
|
||||||
|
"""
|
||||||
|
获取告警日志列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertLog:list")
|
||||||
|
@bp.input(AlertLogQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotAlertLogSchema))
|
||||||
|
def page_alert_log(query_data: AlertLogQuery):
|
||||||
|
"""
|
||||||
|
获取告警日志分页列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/add/<int:endpoint_id>")
|
||||||
|
# @jwt_required()
|
||||||
|
# @bp.doc(security="JWT")
|
||||||
|
# @permission("iot:alertLog:add")
|
||||||
|
def add_alert_log(endpoint_id: int):
|
||||||
|
"""
|
||||||
|
添加采集端网络不可达告警日志
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = add_endpoint_alert_log(endpoint_id)
|
||||||
|
if len(result) > 0:
|
||||||
|
raise BizException(result)
|
||||||
|
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.post("/addNodeValue")
|
||||||
|
# @jwt_required()
|
||||||
|
# @bp.doc(security="JWT")
|
||||||
|
# @permission("iot:alertLog:add")
|
||||||
|
@bp.input(NodeAlertLogAddRequest, location="json")
|
||||||
|
def add_node_alert(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加节点值异常告警日志
|
||||||
|
"""
|
||||||
|
for node_data in json_data["node_data_list"]:
|
||||||
|
node_id = node_data["node_id"]
|
||||||
|
alert_value = node_data["alert_value"]
|
||||||
|
result = add_node_alert_log(node_id, alert_value)
|
||||||
|
if len(result) > 0:
|
||||||
|
raise BizException(result)
|
||||||
|
|
||||||
|
return success();
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/recover/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertLog:update")
|
||||||
|
def recover_alert_log(id: int):
|
||||||
|
"""
|
||||||
|
恢复告警日志
|
||||||
|
"""
|
||||||
|
|
||||||
|
alert_log = db.session.scalar(select(IotAlertLog).filter_by(id=id))
|
||||||
|
if not alert_log:
|
||||||
|
raise BizException("告警日志不存在")
|
||||||
|
|
||||||
|
alert_log.trigger_count =0
|
||||||
|
alert_log.status = 0
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
def get_list_or_page(query_data: AlertLogQuery):
|
||||||
|
"""
|
||||||
|
获取告警日志列表
|
||||||
|
"""
|
||||||
|
query = select(IotAlertLog).order_by(IotAlertLog.created_at.desc())
|
||||||
|
if query_data.alert_tag is not None:
|
||||||
|
query = query.filter(IotAlertLog.alert_tag == query_data.alert_tag)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotAlertLog.status == query_data.status)
|
||||||
|
if query_data.page and query_data.size:
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
else:
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotAlertPush,
|
||||||
|
IotAlertPushSchema,
|
||||||
|
)
|
||||||
|
from .schemas.alert_push import (
|
||||||
|
AlertPushQuery,
|
||||||
|
AlertPushAddRequest,
|
||||||
|
AlertPushUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_alert_push", __name__, url_prefix="/alertPush", tag="消息通知")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertPush:list")
|
||||||
|
@bp.input(AlertPushQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotAlertPushSchema(many=True))
|
||||||
|
def list_alert_push(query_data: AlertPushQuery):
|
||||||
|
"""
|
||||||
|
获取消息通知列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
r = get_list_or_page(query_data)
|
||||||
|
for item in r.items:
|
||||||
|
item.alert_level = list(map(int, item.alert_level.split(",")))
|
||||||
|
return success(r)
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertPush:list")
|
||||||
|
@bp.input(AlertPushQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotAlertPushSchema))
|
||||||
|
def page_alert_push(query_data: AlertPushQuery):
|
||||||
|
"""
|
||||||
|
获取消息通知分页列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
r = get_list_or_page(query_data)
|
||||||
|
for item in r.items:
|
||||||
|
item.alert_level = list(map(int, item.alert_level.split(",")))
|
||||||
|
return success(r)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertPush:add")
|
||||||
|
@bp.input(AlertPushAddRequest,location="json")
|
||||||
|
def add_alert_push(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加消息通知
|
||||||
|
"""
|
||||||
|
|
||||||
|
if "alert_level" in json_data:
|
||||||
|
json_data["alert_level"] = ",".join(map(str, json_data["alert_level"]))
|
||||||
|
alert_push = IotAlertPush(**json_data)
|
||||||
|
alert_push.status = 0
|
||||||
|
db.session.add(alert_push)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertPush:update")
|
||||||
|
@bp.input(AlertPushUpdateRequest(partial=True), location="json")
|
||||||
|
def update_alert_push(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新消息通知
|
||||||
|
"""
|
||||||
|
|
||||||
|
alert_push = db.session.scalar(select(IotAlertPush).where(IotAlertPush.id == id))
|
||||||
|
if not alert_push:
|
||||||
|
raise BizException("消息通知不存在")
|
||||||
|
|
||||||
|
for key, value in json_data.items():
|
||||||
|
if key == "alert_level":
|
||||||
|
value = ",".join(map(str, value))
|
||||||
|
if value is not None:
|
||||||
|
setattr(alert_push, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertPush:delete")
|
||||||
|
def delete_alert_push(id: int):
|
||||||
|
"""
|
||||||
|
删除消息通知
|
||||||
|
"""
|
||||||
|
|
||||||
|
alert_push = db.session.scalar(select(IotAlertPush).where(IotAlertPush.id == id))
|
||||||
|
if not alert_push:
|
||||||
|
raise BizException("消息通知不存在")
|
||||||
|
|
||||||
|
db.session.delete(alert_push)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
def get_list_or_page(query_data: AlertPushQuery):
|
||||||
|
"""
|
||||||
|
获取消息通知列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = select(IotAlertPush).order_by(IotAlertPush.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotAlertPush.target_name.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotAlertPush.status == query_data.status)
|
||||||
|
if query_data.page and query_data.size:
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
else:
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotAlertRule,
|
||||||
|
IotAlertRuleSchema,
|
||||||
|
)
|
||||||
|
from .schemas.alert_rule import (
|
||||||
|
AlertRuleQuery,
|
||||||
|
AlertRuleAddRequest,
|
||||||
|
AlertRuleUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_alert_rule", __name__, url_prefix="/alertRule", tag="告警规则")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertRule:list")
|
||||||
|
@bp.input(AlertRuleQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotAlertRuleSchema(many=True))
|
||||||
|
def get_alert_rule_list(query_data: AlertRuleQuery):
|
||||||
|
"""
|
||||||
|
获取告警规则列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return get_list_or_page(query_data)
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertRule:list")
|
||||||
|
@bp.input(AlertRuleQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotAlertRuleSchema))
|
||||||
|
def get_alert_rule_page(query_data: AlertRuleQuery):
|
||||||
|
"""
|
||||||
|
获取告警规则分页列表
|
||||||
|
"""
|
||||||
|
return page(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertRule:add")
|
||||||
|
@bp.input(AlertRuleAddRequest, location="json")
|
||||||
|
def add_alert_rule(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加告警规则
|
||||||
|
"""
|
||||||
|
alert_rule = IotAlertRule(**json_data)
|
||||||
|
db.session.add(alert_rule)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertRule:update")
|
||||||
|
@bp.input(AlertRuleUpdateRequest(partial=True), location="json")
|
||||||
|
def update_alert_rule(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新告警规则
|
||||||
|
"""
|
||||||
|
alert_rule = db.session.scalar(select(IotAlertRule).where(IotAlertRule.id == id))
|
||||||
|
if not alert_rule:
|
||||||
|
raise BizException("告警规则不存在")
|
||||||
|
|
||||||
|
for key, value in json_data.items():
|
||||||
|
setattr(alert_rule, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:alertRule:delete")
|
||||||
|
def delete_alert_rule(id: int):
|
||||||
|
"""
|
||||||
|
删除告警规则
|
||||||
|
"""
|
||||||
|
alert_rule = db.session.scalar(select(IotAlertRule).where(IotAlertRule.id == id))
|
||||||
|
if not alert_rule:
|
||||||
|
raise BizException("告警规则不存在")
|
||||||
|
|
||||||
|
db.session.delete(alert_rule)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_list_or_page(query_data: AlertRuleQuery):
|
||||||
|
"""
|
||||||
|
获取告警规则列表
|
||||||
|
"""
|
||||||
|
query = select(IotAlertRule).order_by(IotAlertRule.created_at.desc())
|
||||||
|
if query_data.node_id:
|
||||||
|
query = query.filter(IotAlertRule.node_id == query_data.node_id)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotAlertRule.status == query_data.status)
|
||||||
|
if query_data.page and query_data.size:
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
else:
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotDevice,
|
||||||
|
IotDeviceSchema,
|
||||||
|
)
|
||||||
|
from .schemas.device import (
|
||||||
|
DeviceQuery,
|
||||||
|
DeviceAddRequest,
|
||||||
|
DeviceUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_device", __name__, url_prefix="/device", tag="设备管理")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:list")
|
||||||
|
@bp.input(DeviceQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotDeviceSchema(many=True))
|
||||||
|
def list_device(query_data: DeviceQuery):
|
||||||
|
"""
|
||||||
|
获取设备列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:list")
|
||||||
|
@bp.input(DeviceQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotDeviceSchema(many=True)))
|
||||||
|
def page_device(query_data: DeviceQuery):
|
||||||
|
"""
|
||||||
|
分页获取设备列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return page(get_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:add")
|
||||||
|
@bp.input(DeviceAddRequest, location="json")
|
||||||
|
def add_device(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加设备信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断设备编号是否唯一
|
||||||
|
if json_data.get("device_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotDevice.device_number == json_data.get("device_number")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号设备已存在")
|
||||||
|
|
||||||
|
device = IotDevice(**json_data)
|
||||||
|
device.status = 0
|
||||||
|
db.session.add(device)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:update")
|
||||||
|
@bp.input(DeviceUpdateRequest(partial=True), location="json")
|
||||||
|
def update_device(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新设备信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断设备编号是否唯一
|
||||||
|
if json_data.get("device_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotDevice.device_number == json_data.get("device_number"), IotDevice.id != id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号设备已存在")
|
||||||
|
|
||||||
|
device = db.session.scalar(select(IotDevice).filter_by(id=id))
|
||||||
|
if not device:
|
||||||
|
raise BizException("设备信息不存在")
|
||||||
|
for key, value in json_data.items():
|
||||||
|
if value is not None:
|
||||||
|
setattr(device, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:delete")
|
||||||
|
def delete_device(id: int):
|
||||||
|
"""
|
||||||
|
删除设备信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
device = db.session.scalar(select(IotDevice).filter_by(id=id))
|
||||||
|
if not device:
|
||||||
|
raise BizException("设备不存在")
|
||||||
|
|
||||||
|
# 删除设备
|
||||||
|
db.session.delete(device)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.get("/count")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:device:list")
|
||||||
|
def count_device():
|
||||||
|
"""
|
||||||
|
统计设备数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
countData = {}
|
||||||
|
deviceReady = db.session.query(func.count(IotDevice.id).label('number')).filter_by(status=1).first().number
|
||||||
|
deviceUnready = db.session.query(func.count(IotDevice.id).label('number')).filter_by(status=0).first().number
|
||||||
|
deviceFix = db.session.query(func.count(IotDevice.id).label('number')).filter_by(status=2).first().number
|
||||||
|
countData["ready"] = deviceReady
|
||||||
|
countData["unReady"] = deviceUnready
|
||||||
|
countData["fix"] = deviceFix
|
||||||
|
countData["total"] = deviceReady + deviceUnready + deviceFix
|
||||||
|
|
||||||
|
return success(countData)
|
||||||
|
|
||||||
|
def get_page(query_data: DeviceQuery):
|
||||||
|
"""
|
||||||
|
获取设备信息分页
|
||||||
|
"""
|
||||||
|
query = select(IotDevice).order_by(IotDevice.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotDevice.device_name.like(f"%{kw}%")
|
||||||
|
| IotDevice.device_number.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.workshop_id:
|
||||||
|
query = query.filter(IotDevice.workshop_id == query_data.workshop_id)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotDevice.status == query_data.status)
|
||||||
|
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
|
||||||
|
|
||||||
|
def get_list(query_data: DeviceQuery):
|
||||||
|
"""
|
||||||
|
获取设备列表
|
||||||
|
"""
|
||||||
|
query = select(IotDevice).options(noload(IotDevice.workshop)).order_by(IotDevice.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotDevice.device_name.like(f"%{kw}%")
|
||||||
|
| IotDevice.device_number.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.workshop_id:
|
||||||
|
query = query.filter(IotDevice.workshop_id == query_data.workshop_id)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotDevice.status == query_data.status)
|
||||||
|
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,171 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotDevice,
|
||||||
|
IotEndpoint,
|
||||||
|
IotEndpointSchema,
|
||||||
|
)
|
||||||
|
from .schemas.endpoint import (
|
||||||
|
EndpointQuery,
|
||||||
|
EndpointAddRequest,
|
||||||
|
EndpointUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_endpoint", __name__, url_prefix="/endpoint", tag="采集端管理")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:list")
|
||||||
|
@bp.input(EndpointQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotEndpointSchema(many=True))
|
||||||
|
def list_endpoint(query_data: EndpointQuery):
|
||||||
|
"""
|
||||||
|
获取采集端列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:list")
|
||||||
|
@bp.input(EndpointQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotEndpointSchema(many=True)))
|
||||||
|
def page_endpoint(query_data: EndpointQuery):
|
||||||
|
"""
|
||||||
|
分页获取采集端列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return page(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:add")
|
||||||
|
@bp.input(EndpointAddRequest, location="json")
|
||||||
|
def add_endpoint(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加采集端信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断采集端编号是否唯一
|
||||||
|
if json_data.get("endpoint_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotEndpoint.endpoint_number == json_data.get("endpoint_number")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号采集端已存在")
|
||||||
|
|
||||||
|
endpoint = IotEndpoint(**json_data)
|
||||||
|
endpoint.status = 0
|
||||||
|
db.session.add(endpoint)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:update")
|
||||||
|
@bp.input(EndpointUpdateRequest(partial=True), location="json")
|
||||||
|
def update_endpoint(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新采集端信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断采集端编号是否唯一
|
||||||
|
if json_data.get("endpoint_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotEndpoint.endpoint_number == json_data.get("endpoint_number"), IotEndpoint.id != id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号采集端已存在")
|
||||||
|
|
||||||
|
endpoint = db.session.scalar(
|
||||||
|
select(IotEndpoint).filter_by(id=id))
|
||||||
|
if not endpoint:
|
||||||
|
raise BizException("采集端信息不存在")
|
||||||
|
for key, value in json_data.items():
|
||||||
|
if value is not None:
|
||||||
|
setattr(endpoint, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:delete")
|
||||||
|
def delete_endpoint(id: int):
|
||||||
|
"""
|
||||||
|
删除采集端信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
endpoint = db.session.scalar(
|
||||||
|
select(IotEndpoint)
|
||||||
|
.filter_by(id=id))
|
||||||
|
if not endpoint:
|
||||||
|
raise BizException("采集端不存在")
|
||||||
|
|
||||||
|
# 删除
|
||||||
|
db.session.delete(endpoint)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.get("/count")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:endpoint:list")
|
||||||
|
def count_endpoint():
|
||||||
|
"""
|
||||||
|
统计采集端数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
countData = {}
|
||||||
|
endpointReady = db.session.query(func.count(IotEndpoint.id).label('number')).filter_by(status=1).first().number
|
||||||
|
endpointUnready = db.session.query(func.count(IotEndpoint.id).label('number')).filter_by(status=0).first().number
|
||||||
|
endpointFix = db.session.query(func.count(IotEndpoint.id).label('number')).filter_by(status=2).first().number
|
||||||
|
countData["ready"] = endpointReady
|
||||||
|
countData["unReady"] = endpointUnready
|
||||||
|
countData["fix"] = endpointFix
|
||||||
|
countData["total"] = endpointReady + endpointUnready + endpointFix
|
||||||
|
|
||||||
|
return success(countData)
|
||||||
|
|
||||||
|
|
||||||
|
def get_list_or_page(query_data: EndpointQuery):
|
||||||
|
"""
|
||||||
|
获取采集端信息列表
|
||||||
|
"""
|
||||||
|
query = select(IotEndpoint).order_by(IotEndpoint.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotEndpoint.endpoint_name.like(f"%{kw}%")
|
||||||
|
| IotEndpoint.endpoint_number.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotEndpoint.status == query_data.status)
|
||||||
|
if query_data.page and query_data.size:
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
else:
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,245 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotDevice,
|
||||||
|
IotEndpoint,
|
||||||
|
IotNode,
|
||||||
|
IotNodeSchema,
|
||||||
|
)
|
||||||
|
from .schemas.node import (
|
||||||
|
NodeQuery,
|
||||||
|
NodeAddRequest,
|
||||||
|
NodeUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.service.iot import (
|
||||||
|
iot_influxdb,
|
||||||
|
)
|
||||||
|
from iti.applications.service.iot.alert import delete_node_alert_rule
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from sqlalchemy.orm import noload
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_node", __name__, url_prefix="/node", tag="采集节点管理")
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:list")
|
||||||
|
@bp.input(NodeQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotNodeSchema(many=True))
|
||||||
|
def list_node(query_data: NodeQuery):
|
||||||
|
"""
|
||||||
|
获取采集节点列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:list")
|
||||||
|
@bp.input(NodeQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotNodeSchema(many=True)))
|
||||||
|
def page_node(query_data: NodeQuery):
|
||||||
|
"""
|
||||||
|
分页获取采集节点列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return page(get_page(query_data))
|
||||||
|
|
||||||
|
@bp.get("/count")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:list")
|
||||||
|
def count_node():
|
||||||
|
"""
|
||||||
|
统计采集节点数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
countData = {}
|
||||||
|
nodeReady = db.session.query(func.count(IotNode.id).label('number')).filter_by(status=1).first().number
|
||||||
|
nodeUnready = db.session.query(func.count(IotNode.id).label('number')).filter_by(status=0).first().number
|
||||||
|
countData["ready"] = nodeReady
|
||||||
|
countData["unReady"] = nodeUnready
|
||||||
|
countData["total"] = nodeReady + nodeUnready
|
||||||
|
|
||||||
|
return success(countData)
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:add")
|
||||||
|
@bp.input(NodeAddRequest, location="json")
|
||||||
|
def add_node(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加采集节点信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
node = IotNode(**json_data)
|
||||||
|
endpoint = db.session.scalar(
|
||||||
|
select(IotEndpoint)
|
||||||
|
.filter_by(id=node.endpoint_id))
|
||||||
|
if not endpoint:
|
||||||
|
raise BizException("采集端信息不存在")
|
||||||
|
device = db.session.scalar(
|
||||||
|
select(IotDevice)
|
||||||
|
.options(noload(IotDevice.workshop))
|
||||||
|
.filter_by(id=node.device_id))
|
||||||
|
if not device:
|
||||||
|
raise BizException("设备信息不存在")
|
||||||
|
|
||||||
|
# 判断节点编号是否唯一
|
||||||
|
if json_data.get("node_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotNode.node_number == json_data.get("node_number"), IotNode.id != id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号节点已存在")
|
||||||
|
|
||||||
|
node.workshop_id = device.workshop_id
|
||||||
|
node.status = 0
|
||||||
|
db.session.add(node)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:update")
|
||||||
|
@bp.input(NodeUpdateRequest(partial=True), location="json")
|
||||||
|
def update_node(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新采集节点信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断节点编号是否唯一
|
||||||
|
if json_data.get("node_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotNode.node_number == json_data.get("node_number"), IotNode.id != id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号节点已存在")
|
||||||
|
|
||||||
|
node = db.session.scalar(
|
||||||
|
select(IotNode)
|
||||||
|
.options(noload(IotNode.workshop), noload(IotNode.device), noload(IotNode.endpoint))
|
||||||
|
.filter_by(id=id))
|
||||||
|
if not node:
|
||||||
|
raise BizException("节点信息不存在")
|
||||||
|
for key, value in json_data.items():
|
||||||
|
if value is not None:
|
||||||
|
setattr(node, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:delete")
|
||||||
|
def delete_node(id: int):
|
||||||
|
"""
|
||||||
|
删除采集节点信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
node = db.session.scalar(
|
||||||
|
select(IotNode)
|
||||||
|
.options(noload(IotNode.workshop), noload(IotNode.device), noload(IotNode.endpoint))
|
||||||
|
.filter_by(id=id))
|
||||||
|
if not node:
|
||||||
|
raise BizException("采集节点不存在")
|
||||||
|
|
||||||
|
# 删除节点告警规则
|
||||||
|
delete_node_alert_rule(node)
|
||||||
|
|
||||||
|
# 删除
|
||||||
|
db.session.delete(node)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.get("/monitoring/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:node:list")
|
||||||
|
def get_node_alert_data(id: int):
|
||||||
|
"""
|
||||||
|
获取监控数据
|
||||||
|
"""
|
||||||
|
|
||||||
|
node = db.session.scalar(
|
||||||
|
select(IotNode)
|
||||||
|
.options(noload(IotNode.workshop), noload(IotNode.device), noload(IotNode.endpoint))
|
||||||
|
.filter_by(id=id))
|
||||||
|
if not node:
|
||||||
|
raise BizException("采集节点不存在")
|
||||||
|
|
||||||
|
measurement = f"ep{node.endpoint_id}_nd{node.id}"
|
||||||
|
|
||||||
|
resultData = {}
|
||||||
|
resultData["nodeNumber"] = node.node_number
|
||||||
|
resultData["title"] = node.title
|
||||||
|
resultData["dataType"] = node.data_type
|
||||||
|
resultData["tagLabel"] = node.tag_label
|
||||||
|
resultData["mark"] = node.mark
|
||||||
|
|
||||||
|
resultData["monitoringData"] = iot_influxdb.query_table(measurement, node.tag_label)
|
||||||
|
|
||||||
|
return success(resultData)
|
||||||
|
|
||||||
|
|
||||||
|
def get_page(query_data: NodeQuery):
|
||||||
|
"""
|
||||||
|
获取采集节点分页
|
||||||
|
"""
|
||||||
|
query = select(IotNode).order_by(IotNode.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotNode.node_number.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.endpoint_id:
|
||||||
|
query = query.filter(IotNode.endpoint_id == query_data.endpoint_id)
|
||||||
|
if query_data.device_id:
|
||||||
|
query = query.filter(IotNode.device_id == query_data.device_id)
|
||||||
|
elif query_data.workshop_id:
|
||||||
|
query = query.filter(IotNode.workshop_id == query_data.workshop_id)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotNode.status == query_data.status)
|
||||||
|
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
|
||||||
|
|
||||||
|
def get_list(query_data: NodeQuery):
|
||||||
|
"""
|
||||||
|
获取采集节点列表
|
||||||
|
"""
|
||||||
|
query = select(IotNode).options(noload(IotNode.workshop), noload(IotNode.device), noload(IotNode.endpoint)).order_by(IotNode.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotNode.node_number.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.endpoint_id:
|
||||||
|
query = query.filter(IotNode.endpoint_id == query_data.endpoint_id)
|
||||||
|
if query_data.device_id:
|
||||||
|
query = query.filter(IotNode.device_id == query_data.device_id)
|
||||||
|
elif query_data.workshop_id:
|
||||||
|
query = query.filter(IotNode.workshop_id == query_data.workshop_id)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotNode.status == query_data.status)
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class AlertLogQuery(Pagination):
|
||||||
|
"""
|
||||||
|
告警日志信息查询请求
|
||||||
|
"""
|
||||||
|
alert_tag: str = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": "ep1-nd0", "description": "告警标签"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema
|
||||||
|
|
||||||
|
class AlertLogAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警日志信息添加请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
alert_tag = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警标签",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_target_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警对象名称",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
trigger_count = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 1,
|
||||||
|
"description": "触发次数",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 0,
|
||||||
|
"description": "状态",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_content = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警内容",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_level = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 0,
|
||||||
|
"description": "告警级别",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
class AlertLogUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警日志信息更新请求
|
||||||
|
"""
|
||||||
|
alert_tag = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警标签",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_target_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警对象名称",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
trigger_count = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 1,
|
||||||
|
"description": "触发次数",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 0,
|
||||||
|
"description": "状态",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_content = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ep1-nd0",
|
||||||
|
"description": "告警内容",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_level = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 0,
|
||||||
|
"description": "告警级别",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
class NodeCollectData(BaseSchema):
|
||||||
|
"""
|
||||||
|
节点收集数据
|
||||||
|
"""
|
||||||
|
node_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": 1,
|
||||||
|
"description": "节点ID",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_value = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "-2.1",
|
||||||
|
"description": "告警值",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
class NodeAlertLogAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
节点值异常告警日志信息添加请求
|
||||||
|
"""
|
||||||
|
node_data_list = fields.List(
|
||||||
|
fields.Nested(NodeCollectData),
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": [
|
||||||
|
{
|
||||||
|
"node_id": 1,
|
||||||
|
"alert_value": "-2.1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node_id": 2,
|
||||||
|
"alert_value": "100",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "节点收集数据列表",
|
||||||
|
},
|
||||||
|
)
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class AlertPushQuery(Pagination):
|
||||||
|
"""
|
||||||
|
告警推送信息查询请求
|
||||||
|
"""
|
||||||
|
keyword: Optional[str] = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {
|
||||||
|
"description": "关键字 [消息对象名称] 模糊查询"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema
|
||||||
|
|
||||||
|
class AlertPushAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警推送信息添加请求
|
||||||
|
"""
|
||||||
|
target_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ERP",
|
||||||
|
"description": "告警对象名称",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
push_url = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "https://www.baidu.com",
|
||||||
|
"description": "告警推送URL",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_level = fields.List(
|
||||||
|
fields.Integer(),
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "告警级别"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={
|
||||||
|
"example": 1,
|
||||||
|
"description": "状态 0-禁用,1-启用",
|
||||||
|
},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
class AlertPushUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警推送信息更新请求
|
||||||
|
"""
|
||||||
|
target_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "ERP",
|
||||||
|
"description": "告警对象名称",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
push_url = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
"example": "https://www.baidu.com",
|
||||||
|
"description": "告警推送URL",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
alert_level = fields.List(
|
||||||
|
fields.Integer(),
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "告警级别"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态 0-禁用,1-启用"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class AlertRuleQuery(Pagination):
|
||||||
|
"""
|
||||||
|
告警规则信息查询请求
|
||||||
|
"""
|
||||||
|
node_id: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 1, "description": "节点ID"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema
|
||||||
|
|
||||||
|
class AlertRuleAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警规则信息添加请求
|
||||||
|
"""
|
||||||
|
node_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "节点ID"},
|
||||||
|
)
|
||||||
|
rule_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "告警规则1", "description": "告警规则名称"},
|
||||||
|
)
|
||||||
|
alert_rule = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "x<4", "description": "告警规则表达式"},
|
||||||
|
)
|
||||||
|
alert_text = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "节点{{node.title}}告警内容", "description": "告警内容文本模板"},
|
||||||
|
)
|
||||||
|
alert_level = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 0, "description": "告警级别 0-预警,1-一般,2-紧急,3-严重"},
|
||||||
|
load_default=0,
|
||||||
|
)
|
||||||
|
trigger_count = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "阈值触发次数,超过次数后告警"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态 1-启用,0-禁用"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
class AlertRuleUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
告警规则信息更新请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
node_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "节点ID"},
|
||||||
|
)
|
||||||
|
rule_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "告警规则1", "description": "告警规则名称"},
|
||||||
|
)
|
||||||
|
alert_rule = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "x<4", "description": "告警规则表达式"},
|
||||||
|
)
|
||||||
|
alert_text = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "节点{{node.title}}告警内容", "description": "告警内容文本模板"},
|
||||||
|
)
|
||||||
|
alert_level = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 0, "description": "告警级别 0-预警,1-一般,2-紧急,3-严重"},
|
||||||
|
)
|
||||||
|
trigger_count = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "阈值触发次数,超过次数后告警"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态 1-启用,0-禁用"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class DeviceQuery(Pagination):
|
||||||
|
"""
|
||||||
|
设备信息查询请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
keyword: Optional[str] = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {
|
||||||
|
"description": "关键字 [设备名称|设备编号] 模糊查询"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
workshop_id: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 1, "description": "车间ID"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema # For the type check
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
新增设备信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
workshop_id = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "车间ID"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
device_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备名称", "descriptrion": "设备名称"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
device_number = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备编号", "description": "设备编号"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
description = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备描述", "description": "设备描述"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
brand_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "品牌名称", "description": "品牌名称"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
specification_model = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "规格型号", "description": "规格型号"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
更新设备信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
workshop_id = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "车间ID"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
device_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备名称", "descriptrion": "设备名称"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
device_number = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备编号", "description": "设备编号"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
description = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "设备描述", "description": "设备描述"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
brand_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "品牌名称", "description": "品牌名称"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
specification_model = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "规格型号", "description": "规格型号"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态(0-已停机,1-生产中,2-维修中)"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class EndpointQuery(Pagination):
|
||||||
|
"""
|
||||||
|
采集端信息查询请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
keyword: Optional[str] = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {
|
||||||
|
"description": "关键字 [采集端名称|采集端编号|采集端IP] 模糊查询"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema # For the type check
|
||||||
|
|
||||||
|
|
||||||
|
class EndpointAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
采集端新增信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
endpoint_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端名称", "description": "采集端名称"},
|
||||||
|
)
|
||||||
|
endpoint_number = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端编号", "description": "采集端编号"},
|
||||||
|
)
|
||||||
|
description = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "采集端描述", "description": "采集端描述"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
ip = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端IP", "description": "采集端IP"},
|
||||||
|
)
|
||||||
|
port = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端端口", "description": "采集端端口"},
|
||||||
|
)
|
||||||
|
opc_url_temp = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "{_ip_}:{_port_}", "description": "OPC URL模板"},
|
||||||
|
)
|
||||||
|
brand_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "品牌名称", "description": "品牌名称"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
specification_model = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "规格型号", "description": "规格型号"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EndpointUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
更新采集端信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
endpoint_name = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端名称", "descriptrion": "采集端名称"},
|
||||||
|
)
|
||||||
|
endpoint_number = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端编号", "description": "采集端编号"},
|
||||||
|
)
|
||||||
|
description = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "采集端描述", "description": "采集端描述"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
ip = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端IP", "description": "采集端IP"},
|
||||||
|
)
|
||||||
|
port = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "采集端端口", "description": "采集端端口"},
|
||||||
|
)
|
||||||
|
opc_url_temp = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "{_ip_}:{_port_}", "description": "OPC URL模板"},
|
||||||
|
)
|
||||||
|
brand_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "品牌名称", "description": "品牌名称"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
specification_model = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "规格型号", "description": "规格型号"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态(0-已停用,1-生产中,2-维修中)"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class NodeQuery(Pagination):
|
||||||
|
"""
|
||||||
|
节点信息查询请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
keyword: Optional[str] = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": "tt_01", "description": "查询关键字[节点编号]"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
workshop_id: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 1, "description": "车间ID"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
device_id: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 1, "description": "设备ID"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
endpoint_id: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 1, "description": "采集端ID"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema # For the type check
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
节点新增信息
|
||||||
|
"""
|
||||||
|
device_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "设备ID"},
|
||||||
|
)
|
||||||
|
endpoint_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "采集端ID"},
|
||||||
|
)
|
||||||
|
node_number = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "tt_01", "description": "节点编号"},
|
||||||
|
)
|
||||||
|
title = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "节点ID", "description": "节点ID"},
|
||||||
|
)
|
||||||
|
mark = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "采集标识", "description": "采集标识"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
mark_type = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "读写标识", "description": "采集类型 1:只读 2:只写 3:读写"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
tag_label = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "变量别名", "description": "变量别名"},
|
||||||
|
)
|
||||||
|
data_type = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "text", "description": "值类型 text: 文本 int: 整型 float: 浮点型 boolean:布尔型"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NodeUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
节点更新信息
|
||||||
|
"""
|
||||||
|
device_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "设备ID"},
|
||||||
|
)
|
||||||
|
endpoint_id = fields.Integer(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": 1, "description": "采集端ID"},
|
||||||
|
)
|
||||||
|
node_number = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "tt_01", "description": "节点编号"},
|
||||||
|
)
|
||||||
|
title = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "节点ID", "description": "节点ID"},
|
||||||
|
)
|
||||||
|
mark = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "采集标识", "description": "采集标识"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
mark_type = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "读写标识", "description": "采集类型 1:只读 2:只写 3:读写"},
|
||||||
|
load_default=1,
|
||||||
|
)
|
||||||
|
tag_label = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "变量别名", "description": "变量别名"},
|
||||||
|
)
|
||||||
|
data_type = fields.String(
|
||||||
|
required=True,
|
||||||
|
metadata={"example": "text", "description": "值类型 text: 文本 int: 整型 float: 浮点型 boolean:布尔型"},
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态(0-禁用,1-启用)"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
from dataclasses import field
|
||||||
|
from marshmallow_dataclass import dataclass
|
||||||
|
from marshmallow import validates_schema, ValidationError
|
||||||
|
from iti.applications.common.utils.schema import BaseSchema, Pagination
|
||||||
|
from typing import ClassVar, Optional
|
||||||
|
from apiflask import fields
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(base_schema=BaseSchema)
|
||||||
|
class WorkshopQuery(Pagination):
|
||||||
|
"""
|
||||||
|
车间信息查询请求
|
||||||
|
"""
|
||||||
|
|
||||||
|
keyword: Optional[str] = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {
|
||||||
|
"description": "关键字 [车间名称|车间编号|负责人姓名] 模糊查询"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
status: int = field(
|
||||||
|
default=None,
|
||||||
|
metadata={
|
||||||
|
"required": False,
|
||||||
|
"metadata": {"example": 0, "description": "状态"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Schema: ClassVar[BaseSchema] = BaseSchema # For the type check
|
||||||
|
|
||||||
|
|
||||||
|
class WorkshopAddRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
新增车间信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
workshop_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "车间名称", "description": "车间名称"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
workshop_number = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "车间编号", "description": "车间编号"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
total_area = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "1234", "description": "总面积(单位:平方米)"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
director_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "负责人姓名", "description": "负责人姓名"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
director_phone = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "负责人电话", "description": "负责人电话"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
remark = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "备注", "description": "备注"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WorkshopUpdateRequest(BaseSchema):
|
||||||
|
"""
|
||||||
|
更新车间信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
workshop_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "车间名称", "description": "车间名称"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
workshop_number = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "车间编号", "description": "车间编号"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
total_area = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "1234", "description": "总面积(单位:平方米)"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
|
director_name = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "负责人姓名", "description": "负责人姓名"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
director_phone = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "负责人电话", "description": "负责人电话"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
status = fields.Integer(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": 1, "description": "状态(0-已停用,1-生产中)"},
|
||||||
|
load_default=None,
|
||||||
|
)
|
||||||
|
remark = fields.String(
|
||||||
|
required=False,
|
||||||
|
metadata={"example": "备注", "description": "备注"},
|
||||||
|
load_default="",
|
||||||
|
)
|
||||||
@ -0,0 +1,164 @@
|
|||||||
|
from apiflask import APIBlueprint
|
||||||
|
from iti.applications.extensions import db, sys_log
|
||||||
|
from iti.applications.common.utils import success, page_schema, page
|
||||||
|
from iti.applications.models import (
|
||||||
|
IotWorkshop,
|
||||||
|
IotWorkshopSchema,
|
||||||
|
)
|
||||||
|
from .schemas.workshop import (
|
||||||
|
WorkshopQuery,
|
||||||
|
WorkshopAddRequest,
|
||||||
|
WorkshopUpdateRequest,
|
||||||
|
)
|
||||||
|
from iti.applications.common import ModelFilter
|
||||||
|
from iti.applications.common.exceptions.biz_exp import BizException
|
||||||
|
from flask_jwt_extended import jwt_required
|
||||||
|
from sqlalchemy import select, delete, exists
|
||||||
|
from sqlalchemy.sql.functions import func
|
||||||
|
from iti.applications.common import permission
|
||||||
|
|
||||||
|
bp = APIBlueprint("iot_workshop", __name__, url_prefix="/workshop", tag="车间管理")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get("/list")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:list")
|
||||||
|
@bp.input(WorkshopQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(IotWorkshopSchema(many=True))
|
||||||
|
def list_workshop(query_data: WorkshopQuery):
|
||||||
|
"""
|
||||||
|
获取车间列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return success(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get("/page")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:list")
|
||||||
|
@bp.input(WorkshopQuery.Schema(partial=True), location="query")
|
||||||
|
@bp.output(page_schema(IotWorkshopSchema(many=True)))
|
||||||
|
def page_workshop(query_data: WorkshopQuery):
|
||||||
|
"""
|
||||||
|
分页获取车间列表
|
||||||
|
"""
|
||||||
|
|
||||||
|
return page(get_list_or_page(query_data))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/add")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:add")
|
||||||
|
@bp.input(WorkshopAddRequest, location="json")
|
||||||
|
def add_workshop(json_data: dict):
|
||||||
|
"""
|
||||||
|
添加车间信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断车间编号是否唯一
|
||||||
|
if json_data.get("workshop_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotWorkshop.workshop_number == json_data.get("workshop_number")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号车间已存在")
|
||||||
|
|
||||||
|
workshop = IotWorkshop(**json_data)
|
||||||
|
workshop.status = 0
|
||||||
|
db.session.add(workshop)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.put("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:update")
|
||||||
|
@bp.input(WorkshopUpdateRequest(partial=True), location="json")
|
||||||
|
def update_workshop(id: int, json_data: dict):
|
||||||
|
"""
|
||||||
|
更新车间信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 判断车间编号是否唯一
|
||||||
|
if json_data.get("workshop_number") is not None:
|
||||||
|
if db.session.scalar(
|
||||||
|
select(
|
||||||
|
exists().where(
|
||||||
|
IotWorkshop.workshop_number == json_data.get("workshop_number"), IotWorkshop.id != id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise BizException("同编号车间已存在")
|
||||||
|
|
||||||
|
workshop = db.session.scalar(select(IotWorkshop).filter_by(id=id))
|
||||||
|
if not workshop:
|
||||||
|
raise BizException("车间信息不存在")
|
||||||
|
for key, value in json_data.items():
|
||||||
|
if value is not None:
|
||||||
|
setattr(workshop, key, value)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:delete")
|
||||||
|
def delete_workshop(id: int):
|
||||||
|
"""
|
||||||
|
删除车间信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
workshop = db.session.scalar(select(IotWorkshop).filter_by(id=id))
|
||||||
|
if not workshop:
|
||||||
|
raise BizException("车间信息不存在")
|
||||||
|
|
||||||
|
# 删除
|
||||||
|
db.session.delete(workshop)
|
||||||
|
db.session.commit()
|
||||||
|
return success()
|
||||||
|
|
||||||
|
@bp.get("/count")
|
||||||
|
@jwt_required()
|
||||||
|
@bp.doc(security="JWT")
|
||||||
|
@permission("iot:workshop:list")
|
||||||
|
def count_workshop():
|
||||||
|
"""
|
||||||
|
统计车间数量
|
||||||
|
"""
|
||||||
|
|
||||||
|
countData = {}
|
||||||
|
workshopReady = db.session.query(func.count(IotWorkshop.id).label('number')).filter_by(status=1).first().number
|
||||||
|
workshopUnready = db.session.query(func.count(IotWorkshop.id).label('number')).filter_by(status=0).first().number
|
||||||
|
countData["ready"] = workshopReady
|
||||||
|
countData["unReady"] = workshopUnready
|
||||||
|
countData["total"] = workshopReady + workshopUnready
|
||||||
|
|
||||||
|
return success(countData)
|
||||||
|
|
||||||
|
|
||||||
|
def get_list_or_page(query_data: WorkshopQuery):
|
||||||
|
"""
|
||||||
|
获取车间信息列表或分页
|
||||||
|
"""
|
||||||
|
query = select(IotWorkshop).order_by(IotWorkshop.created_at.desc())
|
||||||
|
if query_data.keyword:
|
||||||
|
kw = ModelFilter.escape_like(query_data.keyword)
|
||||||
|
query = query.filter(
|
||||||
|
IotWorkshop.workshop_name.like(f"%{kw}%")
|
||||||
|
| IotWorkshop.workshop_number.like(f"%{kw}%")
|
||||||
|
| IotWorkshop.director_name.like(f"%{kw}%")
|
||||||
|
)
|
||||||
|
if query_data.status is not None:
|
||||||
|
query = query.filter(IotWorkshop.status == query_data.status)
|
||||||
|
if query_data.page and query_data.size:
|
||||||
|
return db.paginate(query, page=query_data.page, per_page=query_data.size)
|
||||||
|
else:
|
||||||
|
return db.session.scalars(query).all()
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
from .influxdb_mgr import iot_influxdb
|
||||||
|
from .rocketmq_mgr import iot_rocketmq
|
||||||
|
|
||||||
|
|
||||||
|
def init_iot(app) -> None:
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
iot_influxdb.init_app(app)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"初始化influxdb_mgr失败: {e}", exc_info=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
iot_rocketmq.init_app(app)
|
||||||
|
iot_rocketmq.start_consumer("iot-collect-topic", "*")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"初始化rocketmq_mgr失败: {e}", exc_info=True)
|
||||||
Loading…
Reference in New Issue