139 lines
4.8 KiB
Go
139 lines
4.8 KiB
Go
package connect
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"os/exec"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
|
||
"FireLeave_tool/logger"
|
||
"FireLeave_tool/portmanager"
|
||
)
|
||
|
||
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 := portmanager.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 := portmanager.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))
|
||
}
|