package em3395ty import ( "database/sql" "log" "time" ) // QueryInterval 查询间隔类型 type QueryInterval string const ( // 预定义的查询间隔 IntervalHourly QueryInterval = "hourly" // 整点查询 IntervalThirtyMin QueryInterval = "30min" // 每30分钟 IntervalTenMin QueryInterval = "10min" // 每10分钟 IntervalThirtySec QueryInterval = "30sec" // 每30秒 IntervalTenSec QueryInterval = "10sec" // 每10秒 IntervalCustom QueryInterval = "custom" // 自定义间隔 ) type EM3395TYScheduler struct { db *sql.DB deviceIDs []string accessToken string tokenExpireAt time.Time ticker *time.Ticker stopChan chan struct{} interval QueryInterval customInterval time.Duration // 自定义间隔时间 } // NewScheduler 创建一个新的EM3395TY调度器,默认整点查询 func NewScheduler(db *sql.DB, deviceIDs []string) *EM3395TYScheduler { return &EM3395TYScheduler{ db: db, deviceIDs: deviceIDs, stopChan: make(chan struct{}), interval: IntervalHourly, } } // SetQueryInterval 设置查询间隔 func (s *EM3395TYScheduler) SetQueryInterval(interval QueryInterval) { s.interval = interval log.Printf("EM3395TY设备查询间隔已设置为: %s", interval) } // SetCustomInterval 设置自定义查询间隔 func (s *EM3395TYScheduler) SetCustomInterval(duration time.Duration) { s.interval = IntervalCustom s.customInterval = duration log.Printf("EM3395TY设备查询间隔已设置为自定义: %s", duration) } // Start 启动定时查询任务 func (s *EM3395TYScheduler) Start() { log.Println("启动EM3395TY设备定时查询任务") // 初始化设备信息 s.initDevices() // 启动查询任务 go s.startQueryTask() } // Stop 停止定时查询任务 func (s *EM3395TYScheduler) Stop() { if s.ticker != nil { s.ticker.Stop() } close(s.stopChan) log.Println("EM3395TY设备定时查询任务已停止") } // initDevices 初始化设备信息 func (s *EM3395TYScheduler) initDevices() { // 获取访问令牌 token, err := GetAccessToken() if err != nil { log.Printf("获取访问令牌失败: %v", err) return } s.accessToken = token s.tokenExpireAt = time.Now().Add(1 * time.Hour) // 假设令牌有效期为1小时 // 检查每个设备是否存在于数据库中,如果不存在则查询设备信息并保存 for _, deviceID := range s.deviceIDs { exists, err := CheckDeviceExists(s.db, deviceID) if err != nil { log.Printf("检查设备 %s 是否存在失败: %v", deviceID, err) continue } if !exists { log.Printf("设备 %s 不存在于数据库中,正在获取设备信息", deviceID) deviceInfo, err := GetDeviceInfo(s.accessToken, deviceID) if err != nil { log.Printf("获取设备 %s 信息失败: %v", deviceID, err) continue } _, err = SaveDeviceInfo(s.db, deviceInfo) if err != nil { log.Printf("保存设备 %s 信息失败: %v", deviceID, err) continue } log.Printf("设备 %s 信息已保存到数据库", deviceID) } else { log.Printf("设备 %s 已存在于数据库中", deviceID) } } } // getIntervalDuration 获取查询间隔时间 func (s *EM3395TYScheduler) getIntervalDuration() time.Duration { switch s.interval { case IntervalHourly: return 1 * time.Hour case IntervalThirtyMin: return 30 * time.Minute case IntervalTenMin: return 10 * time.Minute case IntervalThirtySec: return 30 * time.Second case IntervalTenSec: return 10 * time.Second case IntervalCustom: return s.customInterval default: return 1 * time.Hour } } // startQueryTask 启动查询任务 func (s *EM3395TYScheduler) startQueryTask() { interval := s.getIntervalDuration() if s.interval == IntervalHourly { // 对于整点查询,计算距离下一个整点的时间 now := time.Now() nextHour := time.Date(now.Year(), now.Month(), now.Day(), now.Hour()+1, 0, 0, 0, now.Location()) duration := nextHour.Sub(now) log.Printf("EM3395TY设备第一次查询将在 %s 后进行 (整点: %s)", duration.String(), nextHour.Format("15:04:05")) // 等待到下一个整点 timer := time.NewTimer(duration) select { case <-timer.C: s.queryAllDevices() case <-s.stopChan: timer.Stop() return } s.ticker = time.NewTicker(interval) } else { // 对于非整点查询,立即执行一次查询,然后按照间隔定时执行 log.Printf("EM3395TY设备查询任务已启动,每 %s 查询一次", interval) s.queryAllDevices() s.ticker = time.NewTicker(interval) } // 循环执行查询任务 for { select { case <-s.ticker.C: s.queryAllDevices() case <-s.stopChan: return } } } // queryAllDevices 查询所有设备的状态 func (s *EM3395TYScheduler) queryAllDevices() { log.Println("执行EM3395TY设备查询任务") // 检查令牌是否过期 if time.Now().After(s.tokenExpireAt) { log.Println("访问令牌已过期,正在重新获取") token, err := GetAccessToken() if err != nil { log.Printf("重新获取访问令牌失败: %v", err) return } s.accessToken = token s.tokenExpireAt = time.Now().Add(1 * time.Hour) } // 查询每个设备的状态 for _, deviceID := range s.deviceIDs { log.Printf("正在查询设备 %s 的状态", deviceID) deviceStatus, err := GetDeviceStatus(s.accessToken, deviceID) if err != nil { log.Printf("获取设备 %s 状态失败: %v", deviceID, err) continue } // 保存设备状态到数据库 id, err := SaveDeviceStatus(s.db, deviceID, deviceStatus) if err != nil { log.Printf("保存设备 %s 状态失败: %v", deviceID, err) continue } log.Printf("设备 %s 状态已保存,ID=%d", deviceID, id) // 打印部分关键数据 log.Printf("设备 %s 室内温度: %.1f℃, 室内湿度: %d%%, 室外温度: %.1f℃, 室外湿度: %d%%, 一小时降雨量: %.1fmm", deviceID, float64(deviceStatus.Result.TempCurrent)/10.0, deviceStatus.Result.HumidityValue, float64(deviceStatus.Result.TempCurrentExternal)/10.0, deviceStatus.Result.HumidityOutdoor, float64(deviceStatus.Result.Rain1h)/10.0) } }