2024-08-19 17:36:01 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-10-09 19:47:17 -04:00
|
|
|
"fmt"
|
2024-08-19 17:36:01 -04:00
|
|
|
"log/slog"
|
2024-10-09 19:47:17 -04:00
|
|
|
"strings"
|
2024-08-19 17:36:01 -04:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
import (
|
|
|
|
"frigate/uptime/notify"
|
2024-10-09 19:47:17 -04:00
|
|
|
"frigate/uptime/ping"
|
2024-08-19 17:36:01 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type CameraMonitor struct {
|
2024-10-09 19:47:17 -04:00
|
|
|
pingInterval time.Duration
|
|
|
|
pingTimeout time.Duration
|
2024-08-19 17:36:01 -04:00
|
|
|
consecutiveDownThreshold int
|
|
|
|
downtime map[string]int
|
|
|
|
notify.Notifier
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewCameraMonitor(pingInterval time.Duration, pingTimeout time.Duration, consecutiveDownThreshold int, notifier notify.Notifier) CameraMonitor {
|
|
|
|
return CameraMonitor{
|
2024-10-09 19:47:17 -04:00
|
|
|
pingInterval: pingInterval,
|
|
|
|
pingTimeout: pingTimeout,
|
2024-08-19 17:36:01 -04:00
|
|
|
consecutiveDownThreshold: consecutiveDownThreshold,
|
2024-10-09 19:47:17 -04:00
|
|
|
downtime: make(map[string]int),
|
|
|
|
Notifier: notifier,
|
2024-08-19 17:36:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CameraMonitor) onCameraUp(camera string) {
|
|
|
|
c.SendNotification(camera, true)
|
2024-10-09 19:47:17 -04:00
|
|
|
slog.Info(fmt.Sprintf("%s camera is back online!", camera))
|
2024-08-19 17:36:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c CameraMonitor) onCameraDown(camera string) {
|
|
|
|
c.SendNotification(camera, false)
|
2024-10-09 19:47:17 -04:00
|
|
|
slog.Info(fmt.Sprintf("%s camera is offline!", camera))
|
2024-08-19 17:36:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c CameraMonitor) onCameraPingResult(camera string, online bool) {
|
|
|
|
if online {
|
|
|
|
if c.downtime[camera] >= c.consecutiveDownThreshold {
|
|
|
|
c.onCameraUp(camera)
|
|
|
|
}
|
|
|
|
c.downtime[camera] = 0
|
|
|
|
} else {
|
|
|
|
c.downtime[camera] += 1
|
|
|
|
if c.downtime[camera] == c.consecutiveDownThreshold {
|
|
|
|
c.onCameraDown(camera)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CameraMonitor) Run(cameras map[string]string) {
|
|
|
|
type pingResult struct {
|
|
|
|
camera string
|
2024-10-09 19:47:17 -04:00
|
|
|
online bool
|
2024-08-19 17:36:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var pingResultChannel = make(chan pingResult, 4)
|
|
|
|
|
|
|
|
for {
|
|
|
|
var unknownPingResultCameras = make(map[string]bool, len(cameras))
|
|
|
|
var startTime = time.Now()
|
|
|
|
var timeoutChannel = time.After(c.pingTimeout)
|
|
|
|
|
|
|
|
// Start all pings
|
|
|
|
for camera, host := range cameras {
|
|
|
|
go func() {
|
|
|
|
pingResultChannel <- pingResult{
|
|
|
|
camera: camera,
|
2024-10-09 19:47:17 -04:00
|
|
|
online: ping.VideoPing(host),
|
2024-08-19 17:36:01 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
unknownPingResultCameras[camera] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout:
|
|
|
|
// Await ping results or timeout
|
|
|
|
for range cameras {
|
|
|
|
select {
|
|
|
|
case cameraPingResult := <-pingResultChannel:
|
2024-10-09 19:47:17 -04:00
|
|
|
slog.Debug(cameraPingResult.camera, "online", cameraPingResult.online)
|
2024-08-19 17:36:01 -04:00
|
|
|
c.onCameraPingResult(cameraPingResult.camera, cameraPingResult.online)
|
|
|
|
delete(unknownPingResultCameras, cameraPingResult.camera) // Maintain set of cameras with unknown ping status
|
|
|
|
case <-timeoutChannel:
|
2024-10-09 19:47:17 -04:00
|
|
|
var b strings.Builder
|
|
|
|
for camera := range unknownPingResultCameras {
|
|
|
|
if b.Len() > 0 {
|
|
|
|
b.WriteString(", ")
|
|
|
|
}
|
|
|
|
b.WriteString(camera)
|
|
|
|
}
|
|
|
|
slog.Warn("Timed out waiting for ping result", "cameras", b.String())
|
2024-08-19 17:36:01 -04:00
|
|
|
break timeout
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle timed out camera pings
|
|
|
|
for camera := range unknownPingResultCameras {
|
|
|
|
c.onCameraPingResult(camera, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
var sleepDuration = c.pingInterval - time.Since(startTime)
|
2024-10-09 19:47:17 -04:00
|
|
|
slog.Debug("Sleeping", "seconds", sleepDuration)
|
2024-08-19 17:36:01 -04:00
|
|
|
time.Sleep(sleepDuration)
|
|
|
|
}
|
|
|
|
}
|