FireLeave_tool/connect/heartbeat.go
2026-07-03 20:55:15 +08:00

138 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package connect
import (
"fmt"
"os"
"os/exec"
"strings"
"sync"
"time"
"FireLeave_tool/logger"
)
var (
InferenceProcesses sync.Map // key: deviceUUID string, value: *exec.Cmd
// 记录最后一次收到心跳的时间
inferenceLastHeartbeat sync.Map // key: deviceUUID string, value: time.Time
)
// UpdateInferenceHeartbeat 每收到一帧 /video/post 就调用这个
func UpdateInferenceHeartbeat(deviceUUID string) {
inferenceLastHeartbeat.Store(deviceUUID, time.Now())
// 输出心跳日志
if strings.Contains(deviceUUID, "_fire_check") {
logger.Logger.Printf("推理心跳收到 | 时间: %s | UUID: %s | 类型: fire_check", time.Now().Format("2006/01/02 15:04:05.000"), deviceUUID)
} else {
logger.Logger.Printf("推理心跳收到 | 时间: %s | UUID: %s | 类型: fire_leave", time.Now().Format("2006/01/02 15:04:05.000"), deviceUUID)
}
}
// ShouldRestartInference 判断是否需要重启推理程序
func ShouldRestartInference(deviceUUID string) bool {
val, ok := inferenceLastHeartbeat.Load(deviceUUID)
if !ok {
return true // 从未收到过心跳,肯定要启动
}
last := val.(time.Time)
return time.Since(last) > 85*time.Second
}
// StopInferenceProcess 停止推理进程(供 main 和 DeviceManager 调用)
func StopInferenceProcess(deviceUUID string) {
if raw, ok := InferenceProcesses.Load(deviceUUID); ok {
if cmd, ok := raw.(*exec.Cmd); ok && cmd.Process != nil {
logger.Logger.Printf("正在停止推理进程 (DeviceUUID=%s, PID=%d)", deviceUUID, cmd.Process.Pid)
cmd.Process.Kill()
cmd.Wait()
}
InferenceProcesses.Delete(deviceUUID)
}
}
// StartInferenceProcess 重启推理程序(保持原端口!)
func StartInferenceProcess(deviceData *DeviceData) {
// 重启fire_leave推理程序
StopInferenceProcess(deviceData.DeviceUUID)
portFireLeave, err := GlobalPortManager.GetPort(deviceData.DeviceUUID)
if err != nil {
logger.Logger.Printf("获取fire_leave端口失败无法重启推理程序 (DeviceUUID=%s): %v", deviceData.DeviceUUID, err)
return
}
// 重启fire_check推理程序
StopInferenceProcess(fmt.Sprintf("%s_fire_check", deviceData.DeviceUUID))
portFireCheck, err := GlobalPortManager.GetPort(fmt.Sprintf("%s_fire_check", deviceData.DeviceUUID))
if err != nil {
logger.Logger.Printf("获取fire_check端口失败无法重启推理程序 (DeviceUUID=%s): %v", deviceData.DeviceUUID, err)
return
}
// 为fire_leave推理程序获取检测区域
fireLeaveDetectAreaStr := ProcessDetectAreaForInference(deviceData.FireLeaveDetectArea)
// 启动fire_leave推理程序
inferenceCmdFireLeave := exec.Command(
"./yolov5",
"-s", deviceData.CameraRTSP,
"-m", "model",
"-c", deviceData.DeviceUUID,
"-p", fmt.Sprintf("%d", portFireLeave),
"-w", fireLeaveDetectAreaStr,
"-r", fmt.Sprintf("%d", deviceData.Confidence),
)
inferenceCmdFireLeave.Stdout = os.Stdout
inferenceCmdFireLeave.Stderr = os.Stderr
logger.Logger.Printf("正在重启fire_leave推理程序 (使用原端口 %d): %v", portFireLeave, inferenceCmdFireLeave.Args)
if err := inferenceCmdFireLeave.Start(); err != nil {
logger.Logger.Printf("fire_leave推理程序重启失败 (DeviceUUID=%s): %v", deviceData.DeviceUUID, err)
return
}
// 保存fire_leave进程对象
InferenceProcesses.Store(deviceData.DeviceUUID, inferenceCmdFireLeave)
logger.Logger.Printf("fire_leave推理程序已成功重启PID=%d (DeviceUUID=%s, Port=%d)",
inferenceCmdFireLeave.Process.Pid, deviceData.DeviceUUID, portFireLeave)
// 为fire_check推理程序获取检测区域
fireCheckDetectAreaStr := ProcessDetectAreaForInference(deviceData.FireCheckDetectArea)
// 启动fire_check推理程序
inferenceCmdFireCheck := exec.Command(
"./yolov5",
"-s", deviceData.CameraRTSP,
"-m", "fire_check",
"-c", fmt.Sprintf("%s_fire_check", deviceData.DeviceUUID),
"-p", fmt.Sprintf("%d", portFireCheck),
"-w", fireCheckDetectAreaStr,
"-r", fmt.Sprintf("%d", deviceData.Confidence),
"-R",
)
inferenceCmdFireCheck.Stdout = os.Stdout
inferenceCmdFireCheck.Stderr = os.Stderr
logger.Logger.Printf("正在重启fire_check推理程序 (使用原端口 %d): %v", portFireCheck, inferenceCmdFireCheck.Args)
if err := inferenceCmdFireCheck.Start(); err != nil {
logger.Logger.Printf("fire_check推理程序重启失败 (DeviceUUID=%s): %v", deviceData.DeviceUUID, err)
return
}
// 保存fire_check进程对象
InferenceProcesses.Store(fmt.Sprintf("%s_fire_check", deviceData.DeviceUUID), inferenceCmdFireCheck)
logger.Logger.Printf("fire_check推理程序已成功重启PID=%d (DeviceUUID=%s, Port=%d)",
inferenceCmdFireCheck.Process.Pid, deviceData.DeviceUUID, portFireCheck)
// 重启后立即刷新一次心跳,防止 30s 检测又触发
UpdateInferenceHeartbeat(deviceData.DeviceUUID)
UpdateInferenceHeartbeat(fmt.Sprintf("%s_fire_check", deviceData.DeviceUUID))
}