132 lines
3.1 KiB
Go
132 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"sentinel/pkg/log"
|
|
model2 "sentinel/pkg/model"
|
|
"sentinel/pkg/utils"
|
|
"time"
|
|
)
|
|
|
|
type BusinessService struct {
|
|
mqtt *MQTTService
|
|
deviceID string
|
|
project string
|
|
cmdTopic string
|
|
deviceType string
|
|
}
|
|
|
|
func NewBusinessService(m *MQTTService, project, deviceType, deviceID string) *BusinessService {
|
|
// 根据统一规则生成 topic
|
|
cmdTopic := project + "/cmd/" + deviceType + "/" + deviceID + "/#"
|
|
return &BusinessService{
|
|
mqtt: m,
|
|
project: project,
|
|
deviceID: deviceID,
|
|
cmdTopic: cmdTopic,
|
|
deviceType: deviceType,
|
|
}
|
|
}
|
|
|
|
func (b *BusinessService) Start() error {
|
|
// 订阅 cmd topic
|
|
if err := b.mqtt.Subscribe(b.cmdTopic, 1); err != nil {
|
|
return err
|
|
}
|
|
b.mqtt.SetMessageHandler(b.onMQTTMessage)
|
|
// 第一次连接就发送状态信息
|
|
b.SendStatusInfo()
|
|
|
|
return nil
|
|
}
|
|
|
|
// 消息处理
|
|
func (b *BusinessService) onMQTTMessage(topic string, payload []byte) {
|
|
model := model2.FromStringToMqttTopic(topic)
|
|
// 是指令
|
|
if model.Domain == "cmd" {
|
|
log.Println("收到指令:", model.Resource)
|
|
switch model.Resource {
|
|
case "ping":
|
|
log.Println("pong")
|
|
case "shutdown":
|
|
b.handleShutdown()
|
|
case "restart":
|
|
b.handleRestart()
|
|
case "check_update":
|
|
b.handleCheckUpdate()
|
|
default:
|
|
log.Println("未知的命令:", model.Resource)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (b *BusinessService) SendStatusInfo() {
|
|
info := map[string]interface{}{
|
|
"project": utils.PROJECT,
|
|
"deviceType": utils.DEVICE_TPYE,
|
|
"version": utils.APP_VERSION,
|
|
"online": true,
|
|
"ip": utils.GetLocalIP(),
|
|
"hostname": utils.GetHostname(),
|
|
"mac": utils.GetMacAddress(),
|
|
"os": utils.GetOSInfo(),
|
|
"cpu": utils.GetCPUInfo(),
|
|
"memory_total": utils.GetMemory(),
|
|
"disk_total": utils.GetDisk(),
|
|
"last_seen": time.Now().UTC().Format(time.RFC3339),
|
|
}
|
|
|
|
payload, _ := json.Marshal(info)
|
|
topic := b.project + "/status/" + b.deviceType + "/" + b.deviceID + "/info"
|
|
qos := byte(1)
|
|
retained := true
|
|
|
|
if err := b.mqtt.Publish(topic, qos, retained, payload); err != nil {
|
|
log.Println("[BUS] failed to send status info:", err)
|
|
} else {
|
|
log.Println("[BUS] status info sent:", string(payload))
|
|
}
|
|
}
|
|
|
|
// 关闭程序(立即退出)
|
|
func (b *BusinessService) handleShutdown() {
|
|
os.Exit(0)
|
|
}
|
|
|
|
// 重启程序
|
|
func (b *BusinessService) handleRestart() {
|
|
exe, _ := os.Executable()
|
|
cmd := exec.Command(exe)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
_ = cmd.Start()
|
|
os.Exit(0)
|
|
}
|
|
|
|
// 更新程序
|
|
func (b *BusinessService) handleCheckUpdate() {
|
|
exe, _ := os.Executable()
|
|
updaterPath := filepath.Join(filepath.Dir(exe), "updater")
|
|
if _, err := os.Stat(updaterPath); os.IsNotExist(err) {
|
|
if _, err2 := os.Stat(updaterPath + ".exe"); err2 == nil {
|
|
updaterPath = updaterPath + ".exe"
|
|
} else {
|
|
log.Println("[BUS] updater not found")
|
|
return
|
|
}
|
|
}
|
|
cmd := exec.Command(updaterPath, "--target", exe)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Start(); err != nil {
|
|
log.Println("[BUS] failed to start updater:", err)
|
|
return
|
|
}
|
|
log.Println("[BUS] exiting main program for update")
|
|
os.Exit(0)
|
|
}
|