重构部分枚举, 让models包不依赖其他项目中的包
This commit is contained in:
@@ -10,14 +10,14 @@ import (
|
||||
// 活跃告警会被更新(如确认状态),因此保留 gorm.Model 以包含所有标准字段。
|
||||
type ActiveAlarm struct {
|
||||
gorm.Model
|
||||
FarmID uint `gorm:"not null;comment:猪场ID" json:"farm_id,omitempty"`
|
||||
DeviceID uint `gorm:"not null;comment:设备ID" json:"device_id,omitempty"`
|
||||
AlarmType string `gorm:"comment:告警类型" json:"alarm_type,omitempty"`
|
||||
AlarmLevel string `gorm:"comment:告警级别" json:"alarm_level,omitempty"`
|
||||
AlarmContent string `gorm:"comment:告警内容描述" json:"alarm_content,omitempty"`
|
||||
TriggerTime time.Time `gorm:"not null;comment:告警触发时间" json:"trigger_time"`
|
||||
IsAcknowledged bool `gorm:"default:false;comment:是否已确认" json:"is_acknowledged,omitempty"`
|
||||
AcknowledgedBy string `gorm:"comment:确认人" json:"acknowledged_by,omitempty"`
|
||||
FarmID uint `gorm:"not null;comment:猪场ID" json:"farm_id,omitempty"`
|
||||
DeviceID uint `gorm:"not null;comment:设备ID" json:"device_id,omitempty"`
|
||||
AlarmType string `gorm:"comment:告警类型" json:"alarm_type,omitempty"`
|
||||
AlarmLevel SeverityLevel `gorm:"comment:告警级别" json:"alarm_level,omitempty"`
|
||||
AlarmContent string `gorm:"comment:告警内容描述" json:"alarm_content,omitempty"`
|
||||
TriggerTime time.Time `gorm:"not null;comment:告警触发时间" json:"trigger_time"`
|
||||
IsAcknowledged bool `gorm:"default:false;comment:是否已确认" json:"is_acknowledged,omitempty"`
|
||||
AcknowledgedBy string `gorm:"comment:确认人" json:"acknowledged_by,omitempty"`
|
||||
// 使用指针类型 *time.Time 来表示可为空的确认时间
|
||||
AcknowledgedTime *time.Time `gorm:"comment:确认时间" json:"acknowledged_time,omitempty"`
|
||||
}
|
||||
@@ -32,16 +32,16 @@ func (ActiveAlarm) TableName() string {
|
||||
// ID 和 CreatedAt 共同构成联合主键,以满足 TimescaleDB 超表的要求。
|
||||
type HistoricalAlarm struct {
|
||||
// 手动定义主键,ID 仍然自增
|
||||
ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id,omitempty"`
|
||||
FarmID uint `gorm:"not null;comment:猪场ID" json:"farm_id,omitempty"`
|
||||
DeviceID uint `gorm:"not null;comment:设备ID" json:"device_id,omitempty"`
|
||||
AlarmType string `gorm:"comment:告警类型" json:"alarm_type,omitempty"`
|
||||
AlarmLevel string `gorm:"comment:告警级别" json:"alarm_level,omitempty"`
|
||||
AlarmContent string `gorm:"comment:告警内容描述" json:"alarm_content,omitempty"`
|
||||
TriggerTime time.Time `gorm:"not null;comment:告警触发时间" json:"trigger_time"`
|
||||
ResolveTime time.Time `gorm:"not null;comment:告警解决时间" json:"resolve_time"`
|
||||
ResolveMethod string `gorm:"comment:告警解决方式" json:"resolve_method,omitempty"`
|
||||
ResolvedBy string `gorm:"comment:告警解决人" json:"resolved_by,omitempty"`
|
||||
ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id,omitempty"`
|
||||
FarmID uint `gorm:"not null;comment:猪场ID" json:"farm_id,omitempty"`
|
||||
DeviceID uint `gorm:"not null;comment:设备ID" json:"device_id,omitempty"`
|
||||
AlarmType string `gorm:"comment:告警类型" json:"alarm_type,omitempty"`
|
||||
AlarmLevel SeverityLevel `gorm:"comment:告警级别" json:"alarm_level,omitempty"`
|
||||
AlarmContent string `gorm:"comment:告警内容描述" json:"alarm_content,omitempty"`
|
||||
TriggerTime time.Time `gorm:"not null;comment:告警触发时间" json:"trigger_time"`
|
||||
ResolveTime time.Time `gorm:"not null;comment:告警解决时间" json:"resolve_time"`
|
||||
ResolveMethod string `gorm:"comment:告警解决方式" json:"resolve_method,omitempty"`
|
||||
ResolvedBy string `gorm:"comment:告警解决人" json:"resolved_by,omitempty"`
|
||||
// 将 CreatedAt 作为联合主键的一部分,用于 TimescaleDB 分区
|
||||
CreatedAt time.Time `gorm:"primaryKey;comment:创建时间" json:"created_at"`
|
||||
}
|
||||
|
||||
@@ -5,12 +5,41 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/utils/command_generater"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ModbusFunctionCode 定义Modbus功能码的枚举类型
|
||||
type ModbusFunctionCode byte
|
||||
|
||||
// 定义常用的Modbus功能码常量及其应用场景
|
||||
const (
|
||||
// ReadCoils 读取线圈状态 (0x01)
|
||||
// 场景: 用于读取数字量输出(DO)或内部标志位的当前状态,这些状态通常是开关量。
|
||||
ReadCoils ModbusFunctionCode = 0x01
|
||||
// ReadDiscreteInputs 读取离散输入状态 (0x02)
|
||||
// 场景: 用于读取数字量输入(DI)的当前状态,这些状态通常是外部传感器的开关量信号。
|
||||
ReadDiscreteInputs ModbusFunctionCode = 0x02
|
||||
// ReadHoldingRegisters 读取保持寄存器 (0x03)
|
||||
// 场景: 用于读取设备内部可读写的参数或数据,例如温度设定值、电机速度等模拟量或配置数据。
|
||||
ReadHoldingRegisters ModbusFunctionCode = 0x03
|
||||
// ReadInputRegisters 读取输入寄存器 (0x04)
|
||||
// 场景: 用于读取设备的模拟量输入(AI)数据,这些数据通常是只读的,例如当前温度、压力、电压等实时测量值。
|
||||
ReadInputRegisters ModbusFunctionCode = 0x04
|
||||
// WriteSingleCoil 写入单个线圈 (0x05)
|
||||
// 场景: 用于控制单个数字量输出(DO),例如打开或关闭一个继电器、指示灯等。
|
||||
WriteSingleCoil ModbusFunctionCode = 0x05
|
||||
// WriteSingleRegister 写入单个保持寄存器 (0x06)
|
||||
// 场景: 用于修改设备内部的单个可写参数,例如设置一个温度控制器的目标温度、调整一个阀门的开度等。
|
||||
WriteSingleRegister ModbusFunctionCode = 0x06
|
||||
// WriteMultipleCoils 写入多个线圈 (0x0F)
|
||||
// 场景: 用于批量控制多个数字量输出(DO),例如同时打开或关闭一组继电器。
|
||||
WriteMultipleCoils ModbusFunctionCode = 0x0F
|
||||
// WriteMultipleRegisters 写入多个保持寄存器 (0x10)
|
||||
// 场景: 用于批量修改设备内部的多个可写参数,例如一次性更新多个配置参数或模拟量输出值。
|
||||
WriteMultipleRegisters ModbusFunctionCode = 0x10
|
||||
)
|
||||
|
||||
// DeviceCategory 定义了设备模板的宽泛类别
|
||||
type DeviceCategory string
|
||||
|
||||
@@ -51,7 +80,7 @@ func (sc *SwitchCommands) SelfCheck() error {
|
||||
// SensorCommands 定义了传感器读取指令所需的Modbus参数
|
||||
type SensorCommands struct {
|
||||
// ModbusFunctionCode 记录Modbus功能码,例如 ReadHoldingRegisters。(一般是第二字节)
|
||||
ModbusFunctionCode command_generater.ModbusFunctionCode `json:"modbus_function_code"`
|
||||
ModbusFunctionCode ModbusFunctionCode `json:"modbus_function_code"`
|
||||
// ModbusStartAddress 记录Modbus寄存器的起始地址,用于生成指令。(一般是第三到四字节)
|
||||
ModbusStartAddress uint16 `json:"modbus_start_address"`
|
||||
// ModbusQuantity 记录Modbus寄存器的数量,用于生成指令。(一般是五到六字节)
|
||||
@@ -62,7 +91,7 @@ type SensorCommands struct {
|
||||
func (sc *SensorCommands) SelfCheck() error {
|
||||
// 校验ModbusFunctionCode是否为读取类型
|
||||
switch sc.ModbusFunctionCode {
|
||||
case command_generater.ReadCoils, command_generater.ReadDiscreteInputs, command_generater.ReadHoldingRegisters, command_generater.ReadInputRegisters:
|
||||
case ReadCoils, ReadDiscreteInputs, ReadHoldingRegisters, ReadInputRegisters:
|
||||
// 支持的读取功能码
|
||||
default:
|
||||
return fmt.Errorf("'sensor' 指令集 ModbusFunctionCode %X 无效或不是读取类型", sc.ModbusFunctionCode)
|
||||
|
||||
@@ -154,7 +154,6 @@ func (PendingCollection) TableName() string {
|
||||
}
|
||||
|
||||
// --- 用户审计日志 ---
|
||||
// TODO 这些变量放这个包合适吗?
|
||||
|
||||
// --- 审计日志状态常量 ---
|
||||
type AuditStatus string
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// GetAllModels 返回一个包含所有数据库模型实例的切片。
|
||||
@@ -129,3 +131,68 @@ func (a *UintArray) Scan(src interface{}) error {
|
||||
*a = arr
|
||||
return nil
|
||||
}
|
||||
|
||||
// SeverityLevel 定义了系统中告警、通知、日志的统一级别枚举。
|
||||
// 它以中文形式存储在数据库中,提高了可读性。
|
||||
type SeverityLevel string
|
||||
|
||||
const (
|
||||
// DebugLevel 调试级别,用于开发和诊断问题。
|
||||
DebugLevel SeverityLevel = "Debug"
|
||||
// InfoLevel 信息级别,用于记录常规操作。
|
||||
InfoLevel SeverityLevel = "Info"
|
||||
// WarnLevel 警告级别,表示出现潜在问题,需要关注。
|
||||
WarnLevel SeverityLevel = "Warn"
|
||||
// ErrorLevel 错误级别,表示发生了需要处理的错误。
|
||||
ErrorLevel SeverityLevel = "Error"
|
||||
// DPanicLevel 开发时崩溃级别,在开发模式下会触发 panic。
|
||||
DPanicLevel SeverityLevel = "DPanic"
|
||||
// PanicLevel 崩溃级别,记录日志后会立即触发 panic。
|
||||
PanicLevel SeverityLevel = "Panic"
|
||||
// FatalLevel 致命级别,记录日志后会调用 os.Exit(1) 退出程序。
|
||||
FatalLevel SeverityLevel = "Fatal"
|
||||
)
|
||||
|
||||
// ToZapLevel 将我们的自定义级别转换为 zapcore.Level,以便与日志记录器兼容。
|
||||
func (al SeverityLevel) ToZapLevel() zapcore.Level {
|
||||
switch al {
|
||||
case DebugLevel:
|
||||
return zapcore.DebugLevel
|
||||
case InfoLevel:
|
||||
return zapcore.InfoLevel
|
||||
case WarnLevel:
|
||||
return zapcore.WarnLevel
|
||||
case ErrorLevel:
|
||||
return zapcore.ErrorLevel
|
||||
case DPanicLevel:
|
||||
return zapcore.DPanicLevel
|
||||
case PanicLevel:
|
||||
return zapcore.PanicLevel
|
||||
case FatalLevel:
|
||||
return zapcore.FatalLevel
|
||||
default:
|
||||
// 默认情况下返回 Info 级别,保证程序健壮性
|
||||
return zapcore.InfoLevel
|
||||
}
|
||||
}
|
||||
|
||||
// Scan 实现了 sql.Scanner 接口,GORM 在从数据库读取数据时会调用此方法。
|
||||
func (al *SeverityLevel) Scan(value interface{}) error {
|
||||
bytes, ok := value.([]byte)
|
||||
if !ok {
|
||||
// 尝试处理其他可能的类型,例如字符串
|
||||
s, ok := value.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("无法将值 %v (类型 %T) 扫描为 SeverityLevel", value, value)
|
||||
}
|
||||
*al = SeverityLevel(s)
|
||||
return nil
|
||||
}
|
||||
*al = SeverityLevel(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value 实现了 driver.Valuer 接口,GORM 在将数据写入数据库时会调用此方法。
|
||||
func (al SeverityLevel) Value() (driver.Value, error) {
|
||||
return string(al), nil
|
||||
}
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/notify"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// NotifierType 定义了通知器的类型。
|
||||
type NotifierType string
|
||||
|
||||
const (
|
||||
// NotifierTypeSMTP 表示 SMTP 邮件通知器。
|
||||
NotifierTypeSMTP NotifierType = "邮件"
|
||||
// NotifierTypeWeChat 表示企业微信通知器。
|
||||
NotifierTypeWeChat NotifierType = "企业微信"
|
||||
// NotifierTypeLark 表示飞书通知器。
|
||||
NotifierTypeLark NotifierType = "飞书"
|
||||
// NotifierTypeLog 表示日志通知器,作为最终的告警记录渠道。
|
||||
NotifierTypeLog NotifierType = "日志"
|
||||
)
|
||||
|
||||
// NotificationStatus 定义了通知发送尝试的状态枚举。
|
||||
type NotificationStatus string
|
||||
|
||||
@@ -19,40 +29,12 @@ const (
|
||||
NotificationStatusSkipped NotificationStatus = "已跳过" // 通知因某些原因被跳过(例如:用户未配置联系方式)
|
||||
)
|
||||
|
||||
// LogLevel is a custom type for zapcore.Level to handle database scanning and valuing.
|
||||
type LogLevel zapcore.Level
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
func (l *LogLevel) Scan(value interface{}) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
s = string(v)
|
||||
case string:
|
||||
s = v
|
||||
default:
|
||||
return errors.New("LogLevel的类型无效")
|
||||
}
|
||||
|
||||
var zl zapcore.Level
|
||||
if err := zl.UnmarshalText([]byte(s)); err != nil {
|
||||
return err
|
||||
}
|
||||
*l = LogLevel(zl)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (l LogLevel) Value() (driver.Value, error) {
|
||||
return (zapcore.Level)(l).String(), nil
|
||||
}
|
||||
|
||||
// Notification 表示已发送或尝试发送的通知记录。
|
||||
type Notification struct {
|
||||
gorm.Model
|
||||
|
||||
// NotifierType 通知器类型 (例如:"邮件", "企业微信", "飞书", "日志")
|
||||
NotifierType notify.NotifierType `gorm:"type:varchar(20);not null;index" json:"notifier_type"`
|
||||
NotifierType NotifierType `gorm:"type:varchar(20);not null;index" json:"notifier_type"`
|
||||
// UserID 接收通知的用户ID,用于追溯通知记录到特定用户
|
||||
UserID uint `gorm:"index" json:"user_id"` // 增加 UserID 字段,并添加索引
|
||||
// Title 通知标题
|
||||
@@ -60,7 +42,7 @@ type Notification struct {
|
||||
// Message 通知内容
|
||||
Message string `gorm:"type:text;not null" json:"message"`
|
||||
// Level 通知级别 (例如:INFO, WARN, ERROR)
|
||||
Level LogLevel `gorm:"type:varchar(10);not null" json:"level"`
|
||||
Level SeverityLevel `gorm:"type:varchar(10);not null" json:"level"`
|
||||
// AlarmTimestamp 通知内容生成时的时间戳,与 ID 构成复合主键
|
||||
AlarmTimestamp time.Time `gorm:"primaryKey;not null" json:"alarm_timestamp"`
|
||||
// ToAddress 接收地址 (例如:邮箱地址, 企业微信ID, 日志标识符)
|
||||
|
||||
Reference in New Issue
Block a user