222 lines
6.0 KiB
Go
222 lines
6.0 KiB
Go
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)
|
||
}
|
||
}
|