Browse Source

增加ota升级管理

liuxiulin 7 tháng trước cách đây
mục cha
commit
5c875c0e52

+ 3 - 2
pkg/models/device.go

@@ -51,6 +51,7 @@ type DeviceChartData struct {
 type UpgradeParams struct {
 	VendorID string `json:"vendor_id"`
 	DeviceID string `json:"device_id"`
+	FileID   int    `json:"file_id"`
 	File     []byte `json:"file"`
 	FileName string `json:"file_name"`
 	FileSize int64  `json:"file_size"`
@@ -59,7 +60,7 @@ type UpgradeParams struct {
 // Validate 验证
 func (a *UpgradeParams) Validate() error {
 	if a.DeviceID == "" {
-		return errors.New("非法参数[DeviceID, Label]")
+		return errors.New("非法参数[DeviceIDs, Label]")
 	}
 	return nil
 }
@@ -98,7 +99,7 @@ type SendCommandParams struct {
 // Validate 验证
 func (a *SendCommandParams) Validate() error {
 	if a.DeviceId == "" {
-		return errors.New("非法参数[DeviceID, Label]")
+		return errors.New("非法参数[DeviceIDs, Label]")
 	}
 	return nil
 }

+ 40 - 0
pkg/models/ota.go

@@ -0,0 +1,40 @@
+package models
+
+import (
+	"errors"
+	"github.com/jinzhu/gorm"
+)
+
+type Ota struct {
+	gorm.Model
+	RecordId string `gorm:"column:record_id;size:32;index"`
+	Name     string `gorm:"column:name;size:30"`
+	Url      string `gorm:"column:url;size:200"`
+	Version  string `gorm:"column:version;size:20"`
+	Size     int    `gorm:"column:size;"`
+	VendorId string `gorm:"column:vendor_id;size:32;"`
+}
+
+// Validate 验证
+func (a *Ota) Validate() error {
+	if a.Url == "" {
+		return errors.New("非法参数:[url]")
+	}
+	return nil
+}
+
+type OtaUpgradeParams struct {
+	VendorId  string   `json:"vendor_id"`
+	FileId    string   `json:"file_id"`
+	ProductId string   `json:"product_id"`
+	DeviceIDs []string `json:"device_id"`
+}
+
+// Validate 验证
+func (a *OtaUpgradeParams) Validate() error {
+	if a.FileId == "" {
+		return errors.New("非法参数:[file_id]")
+	}
+
+	return nil
+}

+ 1 - 0
pkg/mysql/migrate.go

@@ -48,6 +48,7 @@ func MigrateDatabase(dbhost, dbport, dbname, dbuser, dbpass string) error {
 		&models.RuleChain{},
 		&models.DeviceNetConfig{},
 		&models.SubDevice{},
+		&models.Ota{},
 	).Error
 	if err != nil {
 		fmt.Printf("%s", err.Error())

+ 1 - 1
services/knowoapi/controllers/file.go

@@ -13,7 +13,7 @@ type FileController struct {
 }
 
 // Post 上传文件
-// Post /device/file
+// Post /file
 func (a *FileController) Post() {
 	fileInfo, err := a.Service.Upload(a.Ctx, "file", "sparrow")
 	if err != nil {

+ 106 - 0
services/knowoapi/controllers/ota.go

@@ -0,0 +1,106 @@
+package controllers
+
+import (
+	"github.com/kataras/iris/v12"
+	"sparrow/pkg/models"
+	"sparrow/services/knowoapi/services"
+)
+
+// OtaController api
+type OtaController struct {
+	Ctx     iris.Context
+	Service services.OtaService
+	Token   Token
+}
+
+// Post post
+// POST /user/rule_chain
+func (a *OtaController) Post() {
+	ptl := new(models.Ota)
+	if err := parseBody(a.Ctx, ptl); err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	ptl.VendorId = a.Token.getVendorID(a.Ctx)
+	err := a.Service.Create(ptl)
+	if err != nil {
+		responseError(a.Ctx, ErrDatabase, err.Error())
+		return
+	}
+	done(a.Ctx, ptl)
+}
+
+// Delete delete
+// DELETE /user/rule_chain
+func (a *OtaController) Delete() {
+	Ota := new(models.Ota)
+	if err := parseBody(a.Ctx, Ota); err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	if err := a.Service.Delete(Ota); err != nil {
+		responseError(a.Ctx, ErrDatabase, err.Error())
+		return
+	}
+	done(a.Ctx, Ota)
+}
+
+// Put 更新
+// PUT /user/ota
+func (a *OtaController) Put() {
+	params := new(models.Ota)
+	if err := parseBody(a.Ctx, params); err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	if err := a.Service.Update(params); err != nil {
+		responseError(a.Ctx, ErrDatabase, err.Error())
+		return
+	}
+	done(a.Ctx, "已保存")
+}
+
+// Get  Ota
+// GET /user/ota?pi=&ps=&name=&vendor
+func (a *OtaController) Get() {
+	pi, err := a.Ctx.URLParamInt("pi")
+	if err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	ps, err := a.Ctx.URLParamInt("ps")
+	if err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	name := a.Ctx.URLParam("name")
+	version := a.Ctx.URLParam("version")
+	vendorId := a.Token.getVendorID(a.Ctx)
+	datas, total, err := a.Service.Query(pi, ps, name, vendorId, version)
+	if err != nil {
+		responseError(a.Ctx, ErrDatabase, err.Error())
+		return
+	}
+
+	done(a.Ctx, map[string]interface{}{
+		"list":  datas,
+		"total": total,
+	})
+}
+
+// POSTUpgrade  Ota
+// POSTUpgrade /user/ota/upgrade
+func (a *OtaController) POSTUpgrade() {
+	params := new(models.OtaUpgradeParams)
+	if err := parseBody(a.Ctx, params); err != nil {
+		badRequest(a.Ctx, err)
+		return
+	}
+	params.VendorId = a.Token.getVendorID(a.Ctx)
+	err := a.Service.Upgrade(*params)
+	if err != nil {
+		responseError(a.Ctx, ErrDatabase, err.Error())
+		return
+	}
+	done(a.Ctx, "下发成功")
+}

+ 2 - 0
services/knowoapi/model/all.go

@@ -17,6 +17,7 @@ type All struct {
 	Relation    *Relation
 	RuleChain   *RuleChain
 	RuleNode    *RuleNode
+	Ota         *Ota
 }
 
 // Init 初始化所有model
@@ -34,5 +35,6 @@ func (a *All) Init(db *gorm.DB) *All {
 	a.Relation = new(Relation).Init(db)
 	a.RuleChain = new(RuleChain).Init(db)
 	a.RuleNode = new(RuleNode).Init(db)
+	a.Ota = new(Ota).Init(db)
 	return a
 }

+ 14 - 0
services/knowoapi/model/device.go

@@ -149,3 +149,17 @@ func (a *Device) GetDevicesByVenderId(vendorid string) (datas []models.Device, e
 	a.db.Where("vendor_id = ?", vendorid).Find(&datas)
 	return
 }
+
+// Query 获取厂商已经激活的设备列表
+func (a *Device) Query(vendorId, productId string, deviceIDs []string) (datas []models.Device, err error) {
+	tx := a.db.Where("vendor_id = ?", vendorId)
+	if productId != "" {
+		tx = tx.Where("product_id = ?", productId)
+	}
+	if len(deviceIDs) > 0 {
+		tx = tx.Where("device_identifier in (?)", deviceIDs)
+	}
+	err = tx.Find(&datas).Error
+
+	return
+}

+ 73 - 0
services/knowoapi/model/ota.go

@@ -0,0 +1,73 @@
+package model
+
+import (
+	"fmt"
+	"sparrow/pkg/models"
+
+	"github.com/jinzhu/gorm"
+)
+
+// Ota model
+type Ota struct {
+	db *gorm.DB
+}
+
+// Init init Ota
+func (a *Ota) Init(db *gorm.DB) *Ota {
+	a.db = db
+	return a
+}
+
+// Query query all roles
+func (a *Ota) Query(pi, ps int, name, vendorId, version string) (datas []models.Ota, total int, err error) {
+	tx := a.db.Where("1=1")
+	if version != "" {
+		tx = tx.Where("version like ?", "%"+version+"%")
+	}
+	if name != "" {
+		tx = tx.Where("name like ?", "%"+name+"%")
+	}
+	if vendorId != "" {
+		tx = tx.Where("vendor_id = ?", vendorId)
+	}
+	err = tx.Limit(ps).Offset((pi - 1) * ps).Find(&datas).Error
+	err = tx.Model(&models.Ota{}).Count(&total).Error
+	return
+}
+
+// Get 获取数据内容
+func (a *Ota) Get(vendorId string, recordId string) (data models.Ota, err error) {
+	cache := getCache()
+	key := fmt.Sprintf("OtaId:%s", recordId)
+	if v, ok := cache.Get(key); ok {
+		_d := v.(*models.Ota)
+		data = *_d
+	} else {
+		err = a.db.Where("vendor_id = ? and record_id = ?", vendorId, recordId).First(&data).Error
+		if err == nil {
+			cache.Set(key, &data)
+		}
+	}
+	return
+}
+
+// Create 创建
+func (a *Ota) Create(Ota *models.Ota) error {
+	return a.db.Save(Ota).Error
+
+}
+
+// Delete delete
+func (a *Ota) Delete(Ota *models.Ota) error {
+	cache := getCache()
+	key := fmt.Sprintf("Ota:%d", Ota.ID)
+	if _, ok := cache.Get(key); ok {
+		cache.Delete(key)
+	}
+	return a.db.Unscoped().Delete(Ota).Error
+}
+
+// Update update
+func (a *Ota) Update(Ota *models.Ota) error {
+	return a.db.Save(Ota).Error
+}

+ 5 - 1
services/knowoapi/router.go

@@ -53,6 +53,7 @@ func registerRouters(srv *iris.Application, models *model.All, gen *generator.Ke
 	ruleChainService := services.NewRuleChainService(models)
 	subDeviceService := services.NewSubDeviceService(models)
 	fileService := services.NewFileService()
+	otaService := services.NewOtaService(models)
 	v1router := srv.Party("/api/v1")
 
 	// 登陆,注册
@@ -83,9 +84,12 @@ func registerRouters(srv *iris.Application, models *model.All, gen *generator.Ke
 	//device api
 	deviceAPI := mvc.New(userRouter.Party("/device"))
 	deviceAPI.Register(deviceService).Handle(new(controllers.DeviceController))
-
+	//file api
 	fileAPI := mvc.New(userRouter.Party("/file"))
 	fileAPI.Register(fileService).Handle(new(controllers.FileController))
+	//ota api
+	otaApi := mvc.New(userRouter.Party("/ota"))
+	otaApi.Register(otaService).Handle(new(controllers.OtaController))
 
 	//管理员接口组
 	adminRouter := v1router.Party("/admin", newJWThandle())

+ 1 - 1
services/knowoapi/services/device.go

@@ -359,7 +359,7 @@ func (a deviceservice) sendCommand(args rpcs.ArgsSendCommand) error {
 	var reply rpcs.ReplySendCommand
 	err := server.RPCCallByName(nil, rpcs.ControllerName, "Controller.SendCommand", args, &reply)
 	if err != nil {
-		server.Log.Errorf("设备状态数据获取失败:%v", err)
+		server.Log.Errorf("指令下发失败:%v", err)
 		return err
 	}
 	return nil

+ 93 - 0
services/knowoapi/services/ota.go

@@ -0,0 +1,93 @@
+package services
+
+import (
+	"fmt"
+	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/util/guid"
+	"sparrow/pkg/models"
+	"sparrow/pkg/rpcs"
+	"sparrow/pkg/server"
+	"sparrow/services/knowoapi/model"
+)
+
+// OtaService Ota service
+type OtaService interface {
+	Create(*models.Ota) error
+	Delete(*models.Ota) error
+	Update(*models.Ota) error
+	Query(int, int, string, string, string) ([]models.Ota, int, error)
+	Get(string, string) (models.Ota, error)
+	Upgrade(params models.OtaUpgradeParams) error
+}
+
+type otaService struct {
+	models *model.All
+}
+
+// NewOtaService new Ota service
+func NewOtaService(models *model.All) OtaService {
+	return otaService{
+		models: models,
+	}
+}
+
+func (a otaService) Query(pi, ps int, name, vendorId, version string) ([]models.Ota, int, error) {
+	return a.models.Ota.Query(pi, ps, name, vendorId, version)
+}
+
+func (a otaService) Get(vendorId, recordId string) (models.Ota, error) {
+	return a.models.Ota.Get(vendorId, recordId)
+}
+
+func (a otaService) Create(Ota *models.Ota) error {
+	Ota.RecordId = guid.S()
+	return a.models.Ota.Create(Ota)
+}
+
+func (a otaService) Delete(Ota *models.Ota) error {
+	return a.models.Ota.Delete(Ota)
+}
+
+func (a otaService) Update(Ota *models.Ota) error {
+	return a.models.Ota.Update(Ota)
+}
+
+func (a otaService) Upgrade(params models.OtaUpgradeParams) error {
+	ota, err := a.Get(params.VendorId, params.FileId)
+	if err != nil {
+		return err
+	}
+
+	devices, err := a.models.Device.Query(params.VendorId, params.ProductId, params.DeviceIDs)
+
+	client := ghttp.NewClient()
+	file := client.GetVar(fmt.Sprintf("%s%s", "https://app.yongxulvjian.com", ota.Url))
+
+	var fileArgs rpcs.ArgsOtaFile
+	fileArgs.FileData = file.Bytes()
+	fileArgs.FileId = int(ota.ID)
+	var reply rpcs.ReplyEmptyResult
+
+	go func() {
+		for _, device := range devices {
+			err = server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.SavaFile", fileArgs, &reply)
+			if err != nil {
+				server.Log.Errorf("OTA升级文件保存失败:%v", err)
+			}
+			var commandArgs rpcs.ArgsSendCommand
+			commandArgs.Cmd = string(models.OtaUpgrade)
+			commandArgs.DeviceId = device.DeviceIdentifier
+			commandArgs.Params = map[string]interface{}{
+				"fileId":   ota.ID,
+				"fileSize": ota.Size,
+			}
+
+			var commandReply rpcs.ReplySendCommand
+			err = server.RPCCallByName(nil, rpcs.ControllerName, "Controller.SendCommand", commandArgs, &commandReply)
+			if err != nil {
+				server.Log.Errorf("OTA升级指令下发失败:%v", err)
+			}
+		}
+	}()
+	return nil
+}

+ 1 - 1
services/registry/registry_test.go

@@ -163,7 +163,7 @@ package main
 //
 //	founddev := &models.Device{}
 //	arg := &rpcs.ArgsDeviceAuth{
-//		DeviceID: int64(int(device.ID)),
+//		DeviceIDs: int64(int(device.ID)),
 //	}
 //	err = r.FindDeviceById(arg, founddev)
 //	if err != nil {