优化influxdb链接,修改采集端和设备关联,添加告警功能相关表

iot
DESKTOP-1JS6RSM\Admin 3 months ago
parent 675d2fad8f
commit 191ef60413

@ -13,4 +13,7 @@ from .sys.sys_file import SysFile, SysFileSchema, SysFileDirectory, SysFileDirec
from .iot.iot_workshop import IotWorkshop, IotWorkshopSchema
from .iot.iot_device import IotDevice, IotDeviceSchema
from .iot.iot_endpoint import IotEndpoint, IotEndpointSchema
from .iot.iot_node import IotNode, IotNodeSchema
from .iot.iot_node import IotNode, IotNodeSchema
from .iot.iot_alert_rule import IotAlertRule, IotAlertRuleSchema
from .iot.iot_alert_log import IotAlertLog, IotAlertLogSchema
from .iot.iot_alert_push import IotAlertPush, IotAlertPushSchema

@ -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,31 @@
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 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 = String()
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")

@ -16,8 +16,6 @@ class IotEndpoint(db.Model, TimeModelMixin):
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_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=True, comment="采集端描述")
@ -27,15 +25,6 @@ class IotEndpoint(db.Model, TimeModelMixin):
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:维修中")
#关系
workshop = db.relationship(
"IotWorkshop",
primaryjoin="foreign(IotEndpoint.workshop_id) == IotWorkshop.id",
)
device = db.relationship(
"IotDevice",
primaryjoin="foreign(IotEndpoint.device_id) == IotDevice.id",
)
class IotEndpointSchema(BaseSchema):
@ -46,8 +35,6 @@ class IotEndpointSchema(BaseSchema):
name = "IotEndpoint"
id = Integer()
workshop_id = Integer()
device_id = Integer()
endpoint_name = String()
endpoint_number = String()
description = String()
@ -59,9 +46,6 @@ class IotEndpointSchema(BaseSchema):
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")
class IotEndpointSimpleSchema(BaseSchema):

@ -3,6 +3,9 @@ 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")
@ -12,5 +15,8 @@ def register_iot_bp(app):
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,96 @@
from apiflask import APIBlueprint
from iti.applications.service.iot.alert import add_endpoint_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,
)
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("/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,83 @@
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):
"""
获取消息通知列表
"""
return success(get_list_or_page(query_data))
@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):
"""
获取消息通知分页列表
"""
return success(get_list_or_page(query_data))
@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):
"""
添加消息通知
"""
alert_push = IotAlertPush(**json_data)
alert_push.status = 0
db.session.add(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,21 @@
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="告警规则")

@ -33,7 +33,7 @@ def list_endpoint(query_data: EndpointQuery):
获取采集端列表
"""
return success(get_list(query_data))
return success(get_list_or_page(query_data))
@bp.get("/page")
@ -47,7 +47,7 @@ def page_endpoint(query_data: EndpointQuery):
分页获取采集端列表
"""
return page(get_page(query_data))
return page(get_list_or_page(query_data))
@bp.post("/add")
@ -72,10 +72,6 @@ def add_endpoint(json_data: dict):
raise BizException("同编号采集端已存在")
endpoint = IotEndpoint(**json_data)
device = db.session.scalar(select(IotDevice).options(noload(IotDevice.workshop)).filter_by(id = endpoint.device_id))
if not device:
raise BizException("设备信息不存在")
endpoint.workshop_id = device.workshop_id
endpoint.status = 0
db.session.add(endpoint)
db.session.commit()
@ -104,9 +100,7 @@ def update_endpoint(id: int, json_data: dict):
raise BizException("同编号采集端已存在")
endpoint = db.session.scalar(
select(IotEndpoint)
.options(noload(IotEndpoint.workshop), noload(IotEndpoint.device))
.filter_by(id=id))
select(IotEndpoint).filter_by(id=id))
if not endpoint:
raise BizException("采集端信息不存在")
for key, value in json_data.items():
@ -128,7 +122,6 @@ def delete_endpoint(id: int):
endpoint = db.session.scalar(
select(IotEndpoint)
.options(noload(IotEndpoint.workshop), noload(IotEndpoint.device))
.filter_by(id=id))
if not endpoint:
raise BizException("采集端不存在")
@ -158,43 +151,21 @@ def count_endpoint():
return success(countData)
def get_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.device_id:
query = query.filter(IotEndpoint.device_id == query_data.device_id)
elif query_data.workshop_id:
query = query.filter(IotEndpoint.workshop_id == query_data.workshop_id)
if query_data.status is not None:
query = query.filter(IotEndpoint.status == query_data.status)
return db.paginate(query, page=query_data.page, per_page=query_data.size)
def get_list(query_data: EndpointQuery):
def get_list_or_page(query_data: EndpointQuery):
"""
获取采集端信息列表
"""
query = select(IotEndpoint).options(noload(IotEndpoint.device), noload(IotEndpoint.workshop)).order_by(IotEndpoint.created_at.desc())
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.device_id:
query = query.filter(IotEndpoint.device_id == query_data.device_id)
elif query_data.workshop_id:
query = query.filter(IotEndpoint.workshop_id == query_data.workshop_id)
if query_data.status is not None:
query = query.filter(IotEndpoint.status == query_data.status)
return db.session.scalars(query).all()
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()

@ -18,6 +18,7 @@ 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
@ -51,6 +52,23 @@ 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()
@ -158,7 +176,7 @@ def get_page(query_data: NodeQuery):
query = select(IotNode).order_by(IotNode.created_at.desc())
if query_data.endpoint_id:
query = query.filter(IotNode.endpoint_id == query_data.endpoint_id)
elif query_data.device_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)
@ -175,7 +193,7 @@ 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.endpoint_id:
query = query.filter(IotNode.endpoint_id == query_data.endpoint_id)
elif query_data.device_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)

@ -0,0 +1,122 @@
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": "告警级别",
},
)

@ -0,0 +1,80 @@
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",
},
)
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",
},
)
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,
)

@ -21,20 +21,6 @@ class EndpointQuery(Pagination):
},
},
)
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"},
},
)
status: int = field(
default=None,
metadata={
@ -50,10 +36,6 @@ class EndpointAddRequest(BaseSchema):
采集端新增信息
"""
device_id = fields.Integer(
required=True,
metadata={"example": 1, "description": "设备ID"},
)
endpoint_name = fields.String(
required=True,
metadata={"example": "采集端名称", "descriptrion": "采集端名称"},
@ -92,10 +74,6 @@ class EndpointUpdateRequest(BaseSchema):
更新采集端信息
"""
device_id = fields.Integer(
required=True,
metadata={"example": 1, "description": "设备ID"},
)
endpoint_name = fields.String(
required=True,
metadata={"example": "采集端名称", "descriptrion": "采集端名称"},

@ -0,0 +1,58 @@
from sqlalchemy.orm import noload
from sqlalchemy.sql._typing import ColumnExpressionArgument
from typing import List, Dict, Any, Optional, Set
from iti.applications.extensions import db
from flask import current_app
from iti.applications.models import (
IotAlertLog,
IotAlertRule,
IotAlertPush,
IotEndpoint,
)
from sqlalchemy import select, distinct
def add_endpoint_alert_log(endpoint_id: int):
"""
添加采集端告警日志
Args:
endpoint_id: 采集端ID
"""
endpoint = db.session.scalar(select(IotEndpoint).filter_by(id=endpoint_id))
if not endpoint:
return "采集端不存在"
alert_tag = f"ep{endpoint.id}_nd0"
alert_log = db.session.scalar(select(IotAlertLog).filter_by(alert_tag=alert_tag))
if alert_log:
alert_log.trigger_count += 1
if alert_log.trigger_count >= 3:
alert_log.status = 1
push_alert(alert_log)
else:
dict_data = dict(
alert_tag=alert_tag,
alert_target_name=f"{endpoint.endpoint_name}({endpoint.endpoint_number})",
alert_level=1,
status=0,
trigger_count=1,
alert_content=f"采集端 {endpoint.endpoint_name}({endpoint.endpoint_number}) 网络不可达",
)
alert_log = IotAlertLog(**dict_data)
db.session.add(alert_log)
db.session.commit()
return ""
def push_alert(alert_log: IotAlertLog):
"""
推送告警消息
Args:
alert_log: 告警日志
"""
level = f"{alert_log.alert_level}"
alert_push_list = db.session.scalars(select(IotAlertPush).filter(IotAlertPush.alert_level.contains(level))).all()
if alert_push_list:
for alert_push in alert_push_list:
# TODO 调用地址发送告警消息
current_app.logger.info(f"推送告警消息到 {alert_push.push_url},内容:{alert_log.alert_content}")

@ -102,7 +102,7 @@ class InfluxDBMgr:
if not hasattr(self, '_query_api') or not self._query_api:
self._query_api = self.client.query_api()
test_query = f'from(bucket: "{self.bucket}") |> range(start: -1m) |> limit(n: 1)'
test_query = f'from(bucket: "{self.bucket}") |> range(start: -5s) |> limit(n: 1)'
self._query_api.query(test_query)
return True
except Exception as e:
@ -154,7 +154,7 @@ class InfluxDBMgr:
flux_query = f'''
from(bucket: "{self.bucket}")
|> range(start: -15m)
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "{query_measurement}")
|> filter(fn: (r) => r._field == "{query_field}")
|> yield(name: "mean")

Loading…
Cancel
Save