178 lines
3.9 KiB
Go
178 lines
3.9 KiB
Go
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)
|
|
}
|