package scheduler import ( "log" "rain_monitor/db" "rain_monitor/modbus" "time" ) // 任务配置 type TaskConfig struct { WeatherStationInterval time.Duration // 气象站查询间隔 RainGaugeInterval time.Duration // 雨量计查询间隔 Enabled bool // 是否启用定时查询 } var ( config TaskConfig weatherTick *time.Ticker stopChan chan struct{} ) // 初始化默认配置 func init() { config = TaskConfig{ WeatherStationInterval: 15 * time.Minute, // 默认15分钟查询一次气象站 RainGaugeInterval: time.Hour, // 默认每小时查询一次雨量计 Enabled: true, // 默认启用 } stopChan = make(chan struct{}) } // StartScheduler 启动定时任务调度器 func StartScheduler() { if !config.Enabled { log.Println("定时查询任务已禁用") return } log.Printf("启动定时查询任务,气象站间隔: %v, 雨量计整点查询", config.WeatherStationInterval) // 启动气象站查询任务 weatherTick = time.NewTicker(config.WeatherStationInterval) go func() { for { select { case <-weatherTick.C: queryWeatherStation() case <-stopChan: return } } }() // 启动雨量计整点查询任务 go scheduleHourlyRainGaugeQuery() } // 计算到下一个整点的等待时间 func durationUntilNextHour() time.Duration { now := time.Now() nextHour := time.Date(now.Year(), now.Month(), now.Day(), now.Hour()+1, 0, 0, 0, now.Location()) return nextHour.Sub(now) } // 整点查询雨量计任务 func scheduleHourlyRainGaugeQuery() { for { select { case <-stopChan: return default: // 计算到下一个整点的等待时间 waitTime := durationUntilNextHour() log.Printf("下一次雨量计查询将在 %s 后进行 (整点: %s)", waitTime.String(), time.Now().Add(waitTime).Format("15:04:05")) // 等待到下一个整点 timer := time.NewTimer(waitTime) select { case <-timer.C: queryRainGauge() case <-stopChan: timer.Stop() return } } } } // StopScheduler 停止定时任务调度器 func StopScheduler() { if weatherTick != nil { weatherTick.Stop() } close(stopChan) log.Println("定时查询任务已停止") } // SetTaskConfig 设置任务配置 func SetTaskConfig(newConfig TaskConfig) { // 先停止现有任务 StopScheduler() // 更新配置 config = newConfig // 重新启动任务 if config.Enabled { StartScheduler() } } // queryWeatherStation 查询气象站并保存数据 func queryWeatherStation() { log.Println("执行气象站查询任务") // 发送查询命令 err := modbus.QueryDevice(modbus.DeviceWeatherStation) if err != nil { log.Printf("气象站查询失败: %v", err) return } // 等待设备响应 time.Sleep(2 * time.Second) // 获取最新数据 weatherData := modbus.GetLatestWeatherData() if weatherData == nil { log.Println("未获取到气象站数据") return } // 保存到数据库 _, err = db.SaveWeatherData(weatherData) if err != nil { log.Printf("保存气象站数据失败: %v", err) return } log.Printf("气象站数据已保存,温度: %.1f℃, 湿度: %.1f%%", weatherData.Temperature, weatherData.Humidity) } // queryRainGauge 查询雨量计并保存数据 func queryRainGauge() { log.Println("执行雨量计查询任务 (整点)") // 发送查询命令 err := modbus.QueryDevice(modbus.DeviceRainGauge) if err != nil { log.Printf("雨量计查询失败: %v", err) return } // 等待设备响应 time.Sleep(2 * time.Second) // 获取最新数据 rainData := modbus.GetLatestRainData() if rainData == nil { log.Println("未获取到雨量计数据") return } // 保存到数据库 _, err = db.SaveRainGaugeData(rainData) if err != nil { log.Printf("保存雨量计数据失败: %v", err) return } log.Printf("雨量计数据已保存,当天降雨量: %.1fmm, 总降雨量: %.1fmm", rainData.DailyRainfall, rainData.TotalRainfall) }