package config import ( "flag" "fmt" "log/slog" "net" "os" "strings" "github.com/spf13/viper" "joylink.club/bj-rtsts-server/dto" ) type AppConfig struct { Env string Server server Datasource datasource Logging log Messaging messaging Dynamics DynamicsConfig Vobc VobcConfig Interlock InterlockConfig } type server struct { Port int } type datasource struct { Dsn string } type log struct { Level string // 日志打印级别 debug info warn error Format string // 输出日志格式 logfmt, json Path string // 输出日志文件路径 FileName string // 输出日志文件名称 FileMaxSize int // 【日志分割】单个日志文件最多存储量 单位(mb) FileMaxBackups int // 【日志分割】日志备份文件最多数量 MaxAge int // 日志保留时间,单位: 天 (day) Compress bool // 是否压缩日志 Stdout bool // 是否输出到控制台 } type messaging struct { Centrifugo centrifugo } type centrifugo struct { TokenSecret string ApiKey string ApiEndpoint string Address string } // 第三方配置结构 type ThridPartyConfig struct { Id int32 `json:"id"` Dynamics DynamicsConfig `json:"dynamics" description:"动力学配置"` Vobc VobcConfig `json:"vobc" description:"半实物配置"` Interlocks []InterlockConfig `json:"interlock" description:"联锁配置"` RsspAxleCfgs []RsspAxleConfig `json:"rsspAxleCfgs" description:"所有联锁集中站计轴RSSP-I配置"` } type DynamicsConfig struct { Ip string `json:"ip" description:"IP配置"` UdpLocalPort int `json:"udpLocalPort" description:"本机监听接收端口"` UdpRemotePort int `json:"udpRemotePort" description:"远端接收道岔信息端口"` UdpRemoteTrainPort int `json:"udpRemoteTrainPort" description:"远端接收列车信息端口"` HttpPort int `json:"httpPort" description:"http服务端口"` Open bool `json:"open" description:"是否开启"` } type VobcConfig struct { Ip string `json:"ip" description:"IP配置"` LocalPort int `json:"localPort" description:"本机监听接收端口"` RemotePort int `json:"remotePort" description:"远端接收列车信息端口"` Open bool `json:"open" description:"是否开启"` } type InterlockConfig struct { Ip string `json:"ip" description:"IP配置"` LocalPort int `json:"localPort" description:"本机监听接收端口"` RemotePort int `json:"remotePort" description:"远端接收采集信息端口"` Open bool `json:"open" description:"是否开启"` Code string `json:"code" description:"所属集中站"` } // RsspAxleConfig 计轴区段与联锁安全通信配置 type RsspAxleConfig struct { City string `json:"city" description:"所属城市"` LineId string `json:"lineId" description:"所属线路"` CentralizedStation string `json:"centralizedStation" description:"所属集中站"` RsspCfgs []RsspConfig `json:"rsspCfgs" description:"主备安全通道配置"` SendingPeriod uint32 `json:"sendingPeriod" description:"发送周期值"` //接收方每个安全通信会话对应的发送周期值,单位ms SsrRsspTimeout uint32 `json:"ssrRsspTimeout" description:"等待SSR回应的定时器超时值"` //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod Mtv uint32 `json:"mtv" description:"最大时序偏差"` //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值 Udl uint32 `json:"udl" description:"RSD应用数据长度配置值"` //每个安全通信会话RSD应用数据长度发送和接收的配置值(支持固定长度和可变长度);0-可变长度,大于0即固定长度 DeviceA bool `json:"deviceA" description:"true-A机;false-B机"` //true-A机;false-B机 } // RsspConfig CI系统与计轴设备的安全通信协议配置参数 // 计轴设备(管理一个集中站的所有计轴器)配置 type RsspConfig struct { SrcAddr uint16 `json:"srcAddr" description:"16位源地址,本地地址"` //16位源地址,本地地址 DstAddr uint16 `json:"dstAddr" description:"16位目的地址,远程地址"` //16位目的地址,远程地址 DataVer1 uint32 `json:"dataVer1" description:"通道1数据版本"` //通道1数据版本 DataVer2 uint32 `json:"dataVer2" description:"通道2数据版本"` //通道2数据版本 SID1 uint32 `json:"sID1" description:"通道1源标识"` //通道1源标识 SID2 uint32 `json:"sID2" description:"通道2源标识"` //通道2源标识 SINIT1 uint32 `json:"sINIT1" description:"通道1序列初始"` //通道1序列初始 SINIT2 uint32 `json:"sINIT2" description:"通道2序列初始"` //通道2序列初始 SendingPeriod uint32 //接收方每个安全通信会话对应的发送周期值,单位ms SsrRsspTimeout uint32 //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod Mtv uint32 //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值 Udl uint32 //每个安全通信会话RSD应用数据长度发送和接收的配置值(支持固定长度和可变长度);0-可变长度,大于0即固定长度 DeviceA bool //true-A机;false-B机 PicType byte `json:"picType" description:"协议交互类别"` //协议交互类别,message.PicType RemoteIp string `json:"remoteIp" description:"远程服务器ip"` //远程服务器ip RemoteUdpPort int `json:"remoteUdpPort" description:"远程服务器端口"` //远程服务器端口 LocalUdpPort int `json:"localUdpPort" description:"本地服务器端口"` //本地服务器端口 } // CheckAddress 检测目标源地址目的地址是否在配置中 func (c *RsspConfig) CheckAddress(srcAddr uint16, dstAddr uint16) bool { return true } /////////////////////////////////////////////////////////////////////////////////////// var Config AppConfig var SimulationId_prefix = (func() string { ip := "127.0.0.1" addrList, err := net.InterfaceAddrs() if err != nil { panic(dto.ErrorDto{Code: dto.DataOperationError, Message: err.Error()}) } for _, address := range addrList { if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { if ipNet.IP.To4() != nil { ip = ipNet.IP.String() } } } ipArr := strings.Split(ip, ".") return ipArr[2] + "_" + ipArr[3] })() // 获取配置文件名称,从运行flag参数config中获取,若未提供,使用默认'dev' func getConfigName() string { configName := "" flag.StringVar(&configName, "config", "dev", "config name, eg: -config test") flag.Parse() if configName == "" { configName = "dev" } slog.Info("读取配置文件", "配置文件名称", configName) return configName } // 加载配置 func LoadConfig() { cnf := viper.New() cnf.SetConfigName(getConfigName()) cnf.SetConfigType("yml") cnf.AddConfigPath("./config/") cnf.AddConfigPath(".") err := cnf.ReadInConfig() if err != nil { panic(fmt.Errorf("读取配置文件错误: %w", err)) } fmt.Println(os.Args) err = cnf.Unmarshal(&Config) if err != nil { panic(fmt.Errorf("解析配置文件错误: %w", err)) } slog.Info("成功加载配置", "config", Config) }