Jelajahi Sumber

修改优化代码

niujiuru 2 bulan lalu
induk
melakukan
31e1db04fb

+ 8 - 2
Makefile

@@ -33,14 +33,20 @@ D_LIBS2 += -L$(RTU_LINUX_MODULES_PATH)/dh_takephoto/lib/armv7hf -lMVSDK -liImage
 D_LIBS2 += -L$(RTU_LINUX_MODULES_PATH)/dh_takephoto/lib/armv7hf/GenICam/bin -lGCBase_gcc483_v3_0 -lGenApi_gcc483_v3_0 -lLog_gcc483_v3_0 -llog4cpp_gcc483_v3_0 -lMathParser_gcc483_v3_0 -lNodeMapData_gcc483_v3_0 -lXmlParser_gcc483_v3_0
 
 # 编译的目标
-all: networkd
+all: networkd timesyncd
 
 # 可执行程序
 LK_LIBS := $(S_LIBS0) $(S_LIBS1) $(D_LIBS0)
 networkd : libswapi.a libair720u.a libec200u.a
 	mkdir -p ./build
 	$(GO) mod tidy
-	$(SETGO_ENV) CGO_LDFLAGS="$(LK_LIBS)" $(GO_BUILD) $(GO_FLAGS) -o $@ ./networkd.service/main.go
+	$(SETGO_ENV) CGO_LDFLAGS="$(LK_LIBS)" $(GO_BUILD) $(GO_FLAGS) -o $@  ./networkd.service/*.go
+	cp -rf $@ ./build/ && cp -rf $@ ./build/$(basename $@)_$(DATE)$(suffix $@) && rm -rf $@
+
+timesyncd : libswapi.a libair720u.a libec200u.a
+	mkdir -p ./build
+	$(GO) mod tidy
+	$(SETGO_ENV) CGO_LDFLAGS="$(LK_LIBS)" $(GO_BUILD) $(GO_FLAGS) -o $@ ./timesyncd.service/*.go
 	cp -rf $@ ./build/ && cp -rf $@ ./build/$(basename $@)_$(DATE)$(suffix $@) && rm -rf $@
 
 # 静态库模块

+ 28 - 0
networkd.service/api_handlers.go

@@ -0,0 +1,28 @@
+package main
+
+import (
+	"context"
+	"strconv"
+
+	"hnyfkj.com.cn/rtu/linux/netmgrd"
+	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
+)
+
+func getModemInfo(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	result := map[string]string{
+		"imei":  netmgrd.GetIMEI(),
+		"iccid": netmgrd.GetSimICCID(),
+		"rssi":  netmgrd.GetRSSI(),
+	}
+
+	return jsonrpc2.BuildResponse(req, result, nil)
+}
+
+func getNetStatus(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	result := map[string]string{
+		"net_ok":   strconv.FormatBool(netmgrd.IsInetAvailable()),
+		"net_type": netmgrd.GetCurrentNetType().String(),
+	}
+
+	return jsonrpc2.BuildResponse(req, result, nil)
+}

+ 17 - 84
networkd.service/main.go

@@ -2,13 +2,11 @@ package main
 
 import (
 	"context"
-	"encoding/json"
 	"errors"
 	"flag"
 	"fmt"
 	"net/http"
 	"os"
-	"strconv"
 	"time"
 
 	"rtu_linux_services/servicelib"
@@ -34,7 +32,6 @@ type program struct {
 	name        string
 	core_server *jsonrpc2.RPCServer
 	http_server *http.Server
-	done        chan struct{}
 }
 
 // Start should not block. Do the actual work async.
@@ -52,7 +49,7 @@ func (p *program) Start(s service.Service) error {
 		return errors.New("modem init failed")
 	}
 
-	netmgrd.SetTimeSyncEnabled(false) // 关闭时间同步, 由"timesyncd.service"完成
+	netmgrd.SetTimeSyncEnabled(false) // -> "timesyncd.service"
 	netmgrd.ModuleInit()
 
 	p.core_server, err = jsonrpc2.NewRPCServer(p.name, baseapp.Logger)
@@ -62,15 +59,20 @@ func (p *program) Start(s service.Service) error {
 
 	methods := make(jsonrpc2.MethodMap)
 
-	////////////////////////////////////////////////////////////
-	methods["basic.getBuildVer"] = p.getBuildVer /// 获取软件版本
-	methods["basic.getLogLevel"] = p.getLogLevel /// 获取日志级别
-	methods["basic.setLogLevel"] = p.setLogLevel /// 设置日志级别
-	methods["basic.saveLogConf"] = p.saveLogConf /// 保存日志设置
-	////////////////////////////////////////////////////////////
-	methods["core.getModemInfo"] = p.getModemInfo // IMEI、ICCID
-	methods["core.getNetStatus"] = p.getNetStatus // 联网状态信息
-	////////////////////////////////////////////////////////////
+	//////////////////////////////////////////////////////////
+	_getBuildVer := servicelib.MakeGetBuildVer(
+		Version, BuildTime)
+	methods["basic.getBuildVer"] = _getBuildVer // 获取软件版本
+	_getLogLevel := servicelib.GetLogLevel
+	methods["basic.getLogLevel"] = _getLogLevel // 获取日志级别
+	_setLogLevel := servicelib.SetLogLevel
+	methods["basic.setLogLevel"] = _setLogLevel // 设置日志级别
+	_saveLogConf := servicelib.SaveLogConf
+	methods["basic.saveLogConf"] = _saveLogConf // 保存日志设置
+	//////////////////////////////////////////////////////////
+	methods["core.getModemInfo"] = getModemInfo // IMEI、ICCID
+	methods["core.getNetStatus"] = getNetStatus // 联网状态信息
+	//////////////////////////////////////////////////////////
 
 	err = p.core_server.RegisterMethods(methods)
 	if err != nil {
@@ -85,8 +87,6 @@ func (p *program) Start(s service.Service) error {
 		Handler: mux,
 	}
 
-	p.done = make(chan struct{})
-
 	go p.run()
 
 	return nil
@@ -94,10 +94,8 @@ func (p *program) Start(s service.Service) error {
 
 // Do work here
 func (p *program) run() {
-	defer close(p.done)
-
 	baseapp.Logger.Infof(
-		"[%s] http server starting on %s...",
+		"[%s] Http server starting on %s...",
 		p.name,
 		p.http_server.Addr,
 	)
@@ -105,7 +103,7 @@ func (p *program) run() {
 	err := p.http_server.ListenAndServe() // 同步阻塞
 
 	if err != nil && !errors.Is(err, http.ErrServerClosed) {
-		baseapp.Logger.Errorf("[%s] start http server error: %v", p.name, err)
+		baseapp.Logger.Errorf("[%s] Start http server error: %v!!", p.name, err)
 		return
 	}
 }
@@ -123,76 +121,11 @@ func (p *program) Stop(s service.Service) error {
 		_ = p.http_server.Shutdown(ctx)
 	}
 
-	if p.done != nil {
-		<-p.done
-	}
-
 	netmgrd.ModemExit()
 	baseapp.ExitLogger()
 	return nil
 }
 
-func (p *program) getBuildVer(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	result := map[string]string{
-		"version":    Version,
-		"build_time": BuildTime,
-	}
-	return jsonrpc2.BuildResponse(req, result, nil)
-}
-
-func (p *program) getLogLevel(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	level, _ := baseapp.GetLogLevel()
-	result := map[string]string{
-		"log_level": level,
-	}
-	return jsonrpc2.BuildResponse(req, result, nil)
-}
-
-func (p *program) setLogLevel(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	var params map[string]string
-	if err := json.Unmarshal(req.Params, &params); err != nil {
-		return jsonrpc2.BuildError(req, jsonrpc2.ErrInvalidParams, err.Error())
-	}
-
-	level, ok := params["log_level"]
-	if !ok || level == "" {
-		return jsonrpc2.BuildError(req, jsonrpc2.ErrInvalidParams, "missing or empty 'log_level' parameter")
-	}
-
-	err := baseapp.UpdateLogLevel(level)
-	if err != nil {
-		return jsonrpc2.BuildError(req, jsonrpc2.ErrInternal, err.Error())
-	}
-
-	return jsonrpc2.BuildResponse(req, "success", nil)
-}
-
-func (p *program) saveLogConf(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	err := baseapp.SaveLogConfig()
-	if err != nil {
-		return jsonrpc2.BuildError(req, jsonrpc2.ErrInternal, err.Error())
-	}
-
-	return jsonrpc2.BuildResponse(req, "success", nil)
-}
-
-func (p *program) getModemInfo(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	result := map[string]string{
-		"imei":  netmgrd.GetIMEI(),
-		"iccid": netmgrd.GetSimICCID(),
-		"rssi":  netmgrd.GetRSSI(),
-	}
-	return jsonrpc2.BuildResponse(req, result, nil)
-}
-
-func (p *program) getNetStatus(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
-	result := map[string]string{
-		"net_available": strconv.FormatBool(netmgrd.IsInetAvailable()),
-		"net_type":      netmgrd.GetCurrentNetType().String(),
-	}
-	return jsonrpc2.BuildResponse(req, result, nil)
-}
-
 func main() {
 	svcFlag := flag.String("service", "", "Control the system service.")
 	flag.Parse()

networkd.service/reademe.txt → networkd.service/test.txt


servicelib/defaultLogConfig.go → servicelib/default_log_config.go


+ 67 - 0
servicelib/rpc_utils.go

@@ -0,0 +1,67 @@
+package servicelib
+
+import (
+	"context"
+	"encoding/json"
+	"net"
+
+	"hnyfkj.com.cn/rtu/linux/baseapp"
+	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
+)
+
+func MakeGetBuildVer(version, buildTime string) jsonrpc2.MethodHandler {
+	return func(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+		result := map[string]string{
+			"version":    version,
+			"build_time": buildTime,
+		}
+
+		return jsonrpc2.BuildResponse(req, result, nil)
+	}
+}
+
+func GetLogLevel(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	level, _ := baseapp.GetLogLevel()
+	result := map[string]string{
+		"log_level": level,
+	}
+
+	return jsonrpc2.BuildResponse(req, result, nil)
+}
+
+func SetLogLevel(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	var params map[string]string
+	if err := json.Unmarshal(req.Params, &params); err != nil {
+		return jsonrpc2.BuildError(req, jsonrpc2.ErrInvalidParams, err.Error())
+	}
+
+	level, ok := params["log_level"]
+	if !ok || level == "" {
+		return jsonrpc2.BuildError(req, jsonrpc2.ErrInvalidParams, "missing or empty 'log_level' parameter")
+	}
+
+	err := baseapp.UpdateLogLevel(level)
+	if err != nil {
+		return jsonrpc2.BuildError(req, jsonrpc2.ErrInternal, err.Error())
+	}
+
+	return jsonrpc2.BuildResponse(req, "success", nil)
+}
+
+func SaveLogConf(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	err := baseapp.SaveLogConfig()
+	if err != nil {
+		return jsonrpc2.BuildError(req, jsonrpc2.ErrInternal, err.Error())
+	}
+
+	return jsonrpc2.BuildResponse(req, "success", nil)
+}
+
+func IsAddrInUse(network, addr string) bool {
+	ln, err := net.Listen(network, addr)
+	if err != nil {
+		return true
+	}
+	_ = ln.Close()
+	return false
+}

+ 0 - 12
servicelib/util.go

@@ -1,12 +0,0 @@
-package servicelib
-
-import "net"
-
-func IsAddrInUse(network, addr string) bool {
-	ln, err := net.Listen(network, addr)
-	if err != nil {
-		return true
-	}
-	_ = ln.Close()
-	return false
-}

+ 18 - 0
timesyncd.service/api_handlers.go

@@ -0,0 +1,18 @@
+package main
+
+import (
+	"context"
+	"strconv"
+	"time"
+
+	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
+)
+
+func (p *program) getSysTimeStatus(ctx context.Context, req *jsonrpc2.Request) *jsonrpc2.Response {
+	result := map[string]string{
+		"time_synced": strconv.FormatBool(p.timeSyncOK.Load()),
+		"system_time": time.Now().Format("2006-01-02 15:04:05"),
+	}
+
+	return jsonrpc2.BuildResponse(req, result, nil)
+}

+ 214 - 0
timesyncd.service/main.go

@@ -0,0 +1,214 @@
+package main
+
+import (
+	"context"
+	"errors"
+	"flag"
+	"fmt"
+	"net/http"
+	"os"
+	"rtu_linux_services/servicelib"
+	"sync/atomic"
+	"time"
+
+	"github.com/kardianos/service"
+	"hnyfkj.com.cn/rtu/linux/baseapp"
+	"hnyfkj.com.cn/rtu/linux/netmgrd"
+	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
+)
+
+var (
+	Version   = "0.0.0.1"
+	BuildTime = ""
+)
+
+const (
+	network    = "tcp" // http -> tcp
+	listenAddr = "127.0.0.1:7001"
+)
+
+type program struct {
+	name         string
+	core_server  *jsonrpc2.RPCServer
+	http_server  *http.Server
+	timeSyncOK   atomic.Bool
+	stopTimeSync chan struct{}
+}
+
+// Start should not block. Do the actual work async.
+func (p *program) Start(s service.Service) error {
+	baseapp.InitPath()
+	logCfgFile, err := servicelib.EnsureDefaultLogConfig()
+	if err != nil {
+		return err
+	}
+
+	baseapp.InitLogger(logCfgFile)
+	baseapp.Logger.Infof("App Version: %s, Build Time: %s", Version, BuildTime)
+
+	p.core_server, err = jsonrpc2.NewRPCServer(p.name, baseapp.Logger)
+	if err != nil {
+		return err
+	}
+
+	methods := make(jsonrpc2.MethodMap)
+
+	//////////////////////////////////////////////////////////
+	_getBuildVer := servicelib.MakeGetBuildVer(
+		Version, BuildTime)
+	methods["basic.getBuildVer"] = _getBuildVer // 获取软件版本
+	_getLogLevel := servicelib.GetLogLevel
+	methods["basic.getLogLevel"] = _getLogLevel // 获取日志级别
+	_setLogLevel := servicelib.SetLogLevel
+	methods["basic.setLogLevel"] = _setLogLevel // 设置日志级别
+	_saveLogConf := servicelib.SaveLogConf
+	methods["basic.saveLogConf"] = _saveLogConf // 保存日志设置
+	//////////////////////////////////////////////////////////
+	methods["core.getSysTimeStatus"] = p.getSysTimeStatus
+
+	err = p.core_server.RegisterMethods(methods)
+	if err != nil {
+		return err
+	}
+
+	mux := http.NewServeMux()
+	mux.Handle("/rpc", p.core_server)
+
+	p.http_server = &http.Server{
+		Addr:    listenAddr,
+		Handler: mux,
+	}
+
+	p.stopTimeSync = make(chan struct{})
+
+	go p.run()
+
+	return nil
+}
+
+// Do work here
+func (p *program) run() {
+	go p.maintainSystemTime()
+
+	baseapp.Logger.Infof(
+		"[%s] Http server starting on %s...",
+		p.name,
+		p.http_server.Addr,
+	)
+
+	err := p.http_server.ListenAndServe() // 同步阻塞
+
+	if err != nil && !errors.Is(err, http.ErrServerClosed) {
+		baseapp.Logger.Errorf("[%s] Start http server error: %v!!", p.name, err)
+		return
+	}
+}
+
+// Stop should not block. Return with a few seconds.
+func (p *program) Stop(s service.Service) error {
+	if p.stopTimeSync != nil {
+		close(p.stopTimeSync)
+	}
+
+	if p.core_server != nil {
+		p.core_server.Stop()
+	}
+
+	if p.http_server != nil {
+		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+		defer cancel()
+
+		_ = p.http_server.Shutdown(ctx)
+	}
+
+	baseapp.ExitLogger()
+	return nil
+}
+
+func (p *program) syncSysTime() error {
+	_, _, tcpOK, httpOK, httpTime := netmgrd.CheckNetwork()
+	if !(tcpOK || httpOK) {
+		return errors.New("network not available")
+	}
+
+	var err error
+	if !httpTime.IsZero() {
+		err = netmgrd.SetSystemTime(httpTime)
+	}
+
+	if httpTime.IsZero() || err != nil {
+		err = netmgrd.SyncNTPTime()
+	}
+
+	return err
+}
+
+func (p *program) maintainSystemTime() {
+	timer := time.NewTimer(0) // ->立即触发
+	defer timer.Stop()
+
+	for {
+		select {
+		case <-timer.C:
+			if err := p.syncSysTime(); err != nil {
+				p.timeSyncOK.Store(false)
+				baseapp.Logger.Errorf("[%s] Error synchronizing system time: %v!!", p.name, err)
+				timer.Reset(time.Second)
+				continue
+			}
+			p.timeSyncOK.Store(true)
+			baseapp.Logger.Infof("[%s] ✅ System time synchronized successfully: %s", p.name, time.Now().Format("2006-01-02 15:04:05"))
+			timer.Reset(time.Hour)
+
+		case <-p.stopTimeSync:
+			return
+		}
+	} // for end
+}
+
+func main() {
+	svcFlag := flag.String("service", "", "Control the system service.")
+	flag.Parse()
+
+	svcConfig := &service.Config{
+		Name:        "yfkj-timesyncd",
+		DisplayName: "yfkj-timesyncd",
+		Description: "System time synchronization",
+		Option: map[string]any{
+			"Restart": "always", // 无条件重启
+		},
+	}
+
+	prg := &program{
+		name: "TimeSync",
+	}
+
+	svc, err := service.New(prg, svcConfig)
+	if err != nil {
+		fmt.Printf("%s.service creation failed: %v\n",
+			svcConfig.Name, err)
+		os.Exit(1)
+	}
+
+	if len(*svcFlag) != 0 {
+		err := service.Control(svc, *svcFlag)
+		if err != nil {
+			fmt.Printf("%v\n Valid actions: %q\n", err, service.ControlAction)
+		}
+		os.Exit(0)
+	}
+
+	if servicelib.IsAddrInUse(network, listenAddr) { // 查询端口占用,避免运行多份实例
+		fmt.Printf(
+			"%s.service start failed: listen addr %s already in use\n",
+			svcConfig.Name, listenAddr,
+		)
+		os.Exit(1)
+	}
+
+	if err := svc.Run(); err != nil {
+		fmt.Printf("%s.service run failed: %v\n",
+			svcConfig.Name, err)
+		os.Exit(1)
+	}
+}

+ 0 - 0
timesyncd.service/reademe.txt


+ 19 - 0
timesyncd.service/test.txt

@@ -0,0 +1,19 @@
+接口测试:
+
+// ping联通测试
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"ping","params":{},"id":1}'
+
+// 获取软件版本
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"basic.getBuildVer","params":{},"id":2}'
+
+// 获取日志级别
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"basic.getLogLevel","params":{},"id":3}'
+
+// 设置日志级别
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"basic.setLogLevel","params":{"log_level":"trace"},"id":4}'
+
+// 保存日志设置
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"basic.saveLogConf","params":{},"id":5}'
+
+// 获取系统时间同步状态
+curl -s -X POST http://127.0.0.1:7001/rpc -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"core.getSysTimeStatus","params":{},"id":6}'