TeamsACS 对于 PERIODIC Event 的处理逻辑

更新日期: 2023-04-30 阅读次数: 690 字数: 853 分类: 物联网

Event 类型的判别

tr069/handlers.go

func (s *Tr069Server) processInformEvent(c echo.Context, lastInform *cwmp.Inform) {
	...

	cpe := app.GApp().CwmpTable().GetCwmpCpe(lastInform.Sn)
	cpe.CheckRegister(c.RealIP(), lastInform)
	cpe.UpdateStatus(lastInform)
	// 通知系统更新数据
	cpe.NotifyDataUpdate(false)

	log.Info2(fmt.Sprintf("debug: Events: %+v\n", lastInform.Events))

	switch {
	// 首次接入下发认证配置
	case lastInform.IsEvent(cwmp.EventBootStrap) && lastInform.RetryCount == 0:
		...
	case lastInform.IsEvent(cwmp.EventBoot) && lastInform.RetryCount == 0:
		...
	case lastInform.IsEvent(cwmp.EventPeriodic) && lastInform.RetryCount == 0:
		// here !!
		err := cpe.CreateCwmpPresetEventTask(app.PeriodicEvent, "")
		if err != nil {
			log.Error2("CreateCwmpPresetEventTask error ", zap.String("namespace", "tr069"), zap.Error(err))
		}
	case lastInform.IsEvent(cwmp.EventScheduled) && lastInform.RetryCount == 0:
		...
	case lastInform.IsEvent(cwmp.EventValueChange) && lastInform.RetryCount == 0:
		...
	}
}

基于 Event 类型创建任务队列

app/cwmp_preset.go

顾名思义,CreateCwmpPresetEventTask 根据传过来的 Event 类型,创建对应的计划任务/任务队列。

从上面的 tr069/handlers.go 中判断 Event 类型的逻辑看,只处理三种类型的 Event:

  • BootStrap
  • Boot
  • Periodic

且都没有指定 CreateCwmpPresetEventTask 中的 pid 参数。

确实没有多大意义,因为 pid 不可能预先知道,毕竟是后续人工在 web 管理后台录入的。

// CreateCwmpPresetEventTask Create scheduled event tasks
func (c *CwmpCpe) CreateCwmpPresetEventTask(event string, pid string) (err error) {
	if event == "" {
		return fmt.Errorf("event is empty")
	}
	var presets []models.CwmpPreset
	query := app.gormDB.Where("event = ?", event)
	if pid != "" {
		query = query.Where("id = ?", pid)
	}
	err = query.Order("priority asc").Find(&presets).Error
	if err != nil {
		return err
	}

	batch := common.UUID()

	for _, preset := range presets {
		if !c.MatchTaskTags(preset.TaskTags) {
			continue
		}
		var content models.CwmpPresetContent
		err = yaml.Unmarshal([]byte(preset.Content), &content)
		if err != nil {
			return err
		}

		// Create a factory settings delivery task
		if content.FactoryResetConfig != nil && content.FactoryResetConfig.Enabled {
			err = c.creatFactoryResetConfigDownloadTask(preset.ID, content.FactoryResetConfig, batch, event)
			if err != nil {
				log.Errorf("creatFactoryResetConfigDownloadTask: %s", err)
			}
		}

		// Create a firmware configuration delivery task
		if content.FirmwareConfig != nil && content.FirmwareConfig.Enabled {
			err = c.creatFirmwareConfigDownloadTask(preset.ID, content.FirmwareConfig, batch, event)
			if err != nil {
				log.Errorf("creatFirmwareConfigDownloadTask: %s", err)
			}
		}

		// Create a script to configure the download task
		if content.Downloads != nil {
			for _, download := range content.Downloads {
				err = c.creatDownloadTask(preset.ID, download, batch, event)
				if err != nil {
					log.Errorf("creatDownloadTask: %s", err)
				}
			}
		}

		// Create an upload task
		if content.Uploads != nil {
			for _, upload := range content.Uploads {
				err = c.creatUploadTask(preset.ID, upload, batch, event)
				if err != nil {
					log.Errorf("creatUploadTask: %s", err)
				}
			}
		}

		go func() {
			// Create parameter task
			if content.SetParameterValues != nil {
				err = c.creatSetParameterValuesTask(preset.ID, content.SetParameterValues, batch, event)
				if err != nil {
					log.Errorf("creatGetParameterValuesTask: %s", err)
				}
			}
			// Create a parameter acquisition task
			if content.GetParameterValues != nil {
				err = c.creatGetParameterValuesTask(content.GetParameterValues)
				if err != nil {
					log.Errorf("creatGetParameterValuesTask: %s", err)
				}
			}

		}()
	}

	return nil
}

CreateCwmpPresetEventTask 归属于指定的 cpe

cpe.CreateCwmpPresetEventTask(app.PeriodicEvent, "")

cpe 由 inform 消息中的 Sn,即设备序列号,查询得到。(但是这里可能有问题,我的 CPE 模拟器 sn 不是 000000,数据库里是!)

cpe := app.GApp().CwmpTable().GetCwmpCpe(lastInform.Sn)

cwmp_preset 表

默认是空表,没有任何数据。

我感觉这个是用于新 CPE 设备连上 ACS 之后,自动获取配置的功能。

例如,在 web 管理后台,新增一堆规则,然后新设备连上之后,自动执行。

CREATE TABLE "cwmp_preset" (
	"id" BIGINT NOT NULL DEFAULT 'nextval(''cwmp_preset_id_seq''::regclass)',
	"name" TEXT NULL DEFAULT NULL,
	"priority" BIGINT NULL DEFAULT NULL,
	"event" TEXT NULL DEFAULT NULL,
	"sched_policy" TEXT NULL DEFAULT NULL,
	"sched_key" TEXT NULL DEFAULT NULL,
	"interval" BIGINT NULL DEFAULT NULL,
	"content" TEXT NULL DEFAULT NULL,
	"task_tags" TEXT NULL DEFAULT NULL,
	"created_at" TIMESTAMPTZ NULL DEFAULT NULL,
	"updated_at" TIMESTAMPTZ NULL DEFAULT NULL,
	PRIMARY KEY ("id"),
	INDEX "idx_cwmp_preset_task_tags" ("task_tags")
)

对应 model

models/cwmp.go

CREATE TABLE "cwmp_preset" (
	"id" BIGINT NOT NULL DEFAULT 'nextval(''cwmp_preset_id_seq''::regclass)',
	"name" TEXT NULL DEFAULT NULL,
	"priority" BIGINT NULL DEFAULT NULL,
	"event" TEXT NULL DEFAULT NULL,
	"sched_policy" TEXT NULL DEFAULT NULL,
	"sched_key" TEXT NULL DEFAULT NULL,
	"interval" BIGINT NULL DEFAULT NULL,
	"content" TEXT NULL DEFAULT NULL,
	"task_tags" TEXT NULL DEFAULT NULL,
	"created_at" TIMESTAMPTZ NULL DEFAULT NULL,
	"updated_at" TIMESTAMPTZ NULL DEFAULT NULL,
	PRIMARY KEY ("id"),
	INDEX "idx_cwmp_preset_task_tags" ("task_tags")
)

对应的还有记录历史的表:

type CwmpPresetTask struct {
	ID        int64     `json:"id,string"` // 主键 ID
	PresetId  int64     `json:"preset_id,string" gorm:"index"`
	Sn        string    `json:"sn" gorm:"index"`
	Name      string    `json:"name" `
	Oid       string    `json:"oid" gorm:"index"`
	Event     string    `json:"event" `
	Batch     string    `json:"batch" `
	Onfail    string    `json:"onfail" `
	Session   string    `json:"session" gorm:"index"`
	Request   string    `json:"request" `
	Response  string    `json:"response"`
	Content   string    `json:"content"`
	Status    string    `json:"status" gorm:"index"`
	ExecTime  time.Time `json:"exec_time"` // 执行时间
	RespTime  time.Time `json:"resp_time"` // 响应时间
	CreatedAt time.Time `json:"created_at" gorm:"index"`
	UpdatedAt time.Time `json:"updated_at"`
}

tags: tr069

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式