Explorar o código

编码完成upgrade_app的rpc方法调用

niujiuru hai 2 semanas
pai
achega
d69faf4596
Modificáronse 3 ficheiros con 84 adicións e 3 borrados
  1. 1 1
      go.mod
  2. 42 0
      reporter/protocol.go
  3. 41 2
      reporter/reporter.go

+ 1 - 1
go.mod

@@ -4,6 +4,7 @@ go 1.24.2
 
 require (
 	github.com/eclipse/paho.mqtt.golang v1.5.1
+	github.com/sirupsen/logrus v1.9.3
 	gopkg.in/ini.v1 v1.67.0
 	hnyfkj.com.cn/rtu/linux v0.0.0
 )
@@ -15,7 +16,6 @@ require (
 	github.com/hashicorp/errwrap v1.0.0 // indirect
 	github.com/hashicorp/go-multierror v1.1.1 // indirect
 	github.com/jlaffaye/ftp v0.2.0 // indirect
-	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/vishvananda/netlink v1.3.1 // indirect
 	github.com/vishvananda/netns v0.0.5 // indirect
 	golang.org/x/net v0.44.0 // indirect

+ 42 - 0
reporter/protocol.go

@@ -3,6 +3,7 @@ package reporter
 import (
 	"encoding/json"
 	"fmt"
+	"net/url"
 
 	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
 )
@@ -75,3 +76,44 @@ func makeLogoutNotif(imei string) ([]byte, error) {
 
 	return json.Marshal(msg)
 }
+
+func parseUpgradeAppReq(params json.RawMessage) (serverAddr, loginUser, loginPass, remoteFile, md5value string, err error) {
+	if len(params) == 0 {
+		return "", "", "", "", "", fmt.Errorf("missing params")
+	}
+
+	var upgrade struct {
+		URL string `json:"url"` // 升级包的URL地址
+		MD5 string `json:"md5"` // 升级包的MD5校验值, 32个十六进制数字组成, 16字节
+	}
+	if err := json.Unmarshal(params, &upgrade); err != nil {
+		return "", "", "", "", "", err
+	}
+
+	u, err := url.Parse(upgrade.URL)
+	if err != nil {
+		return "", "", "", "", "", fmt.Errorf("invalid URL: %s", upgrade.URL)
+	}
+
+	if u.Scheme != "ftp" {
+		return "", "", "", "", "", fmt.Errorf("unsupported scheme: %s", u.Scheme)
+	}
+
+	host := u.Hostname()
+	port := u.Port()
+	if port == "" {
+		port = "21"
+	}
+	serverAddr = fmt.Sprintf("%s:%s", host, port)
+
+	loginUser = u.User.Username()
+	loginPass, _ = u.User.Password()
+
+	remoteFile = u.Path
+	if remoteFile == "" {
+		return "", "", "", "", "", fmt.Errorf("missing remote file path")
+	}
+	md5value = upgrade.MD5
+
+	return serverAddr, loginUser, loginPass, remoteFile, md5value, nil
+}

+ 41 - 2
reporter/reporter.go

@@ -13,6 +13,7 @@ import (
 	"time"
 
 	mqtt "github.com/eclipse/paho.mqtt.golang"
+	"github.com/sirupsen/logrus"
 	gps "hnyfkj.com.cn/rtu/linux/air530z"
 	mcu "hnyfkj.com.cn/rtu/xy_v/mcu_ctrl_board"
 
@@ -386,17 +387,55 @@ func (r *MQTTReporter) execOneCmd(msg mqtt.Message) {
 		if err == nil {
 			resp, _ = jsonrpc2.BuildResult(req, map[string]string{"filename": rf})
 		} else {
-			resp = jsonrpc2.BuildError(req, -32700, fmt.Sprintf("拍照失败: %s", err.Error()))
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
 		}
 	// 下发升级指令
 	case "upgrade_app":
+		server, user, pass, rf, md5val1, err := parseUpgradeAppReq(req.Params)
+		if err != nil {
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
+			break
+		}
+
+		mcu.GlobalWorkState.Add(mcu.AppUpgrading)
+		defer mcu.GlobalWorkState.Remove(mcu.AppUpgrading)
+
+		lf, err := ftpclient.DownloadFileFromFtp(r.ctx, server, user, pass, rf, ftpclient.DefaultDownloadTimeout)
+		if err != nil {
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
+			break
+		}
+
+		md5val2, err := FileMD5(lf)
+		if err != nil {
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
+			break
+		}
+
+		if !strings.EqualFold(md5val1, md5val2) {
+			resp = jsonrpc2.BuildError(req, -32700, fmt.Sprintf("MD5校验失败(%s != %s)", md5val1, md5val2))
+			break
+		}
+
+		cmdStr := "tar xzf " + lf + " -C " + filepath.Dir(baseapp.EXEC_DIR)
+		cmd := exec.Command("sh", "-c", cmdStr)
+		cmd.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
+		cmd.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
+		err = cmd.Run()
+		os.Remove(lf)
+		if err == nil {
+			resp, _ = jsonrpc2.BuildResult(req, "Success")
+		} else {
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
+			break
+		}
 	// 下发重启指令
 	case "reboot":
 		cmd := exec.Command("reboot")
 		if err := cmd.Run(); err == nil {
 			resp, _ = jsonrpc2.BuildResult(req, "Success")
 		} else {
-			resp = jsonrpc2.BuildError(req, -32700, fmt.Sprintf("重启失败: %s", err.Error()))
+			resp = jsonrpc2.BuildError(req, -32700, err.Error())
 		}
 	// 调用无效方法
 	default: