Modularize bridge and improve control GUI
This commit is contained in:
@@ -1,20 +1,11 @@
|
||||
import importlib.util
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def load_bridge_module():
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
path = root / "frigate-camera-control-bridge.py"
|
||||
spec = importlib.util.spec_from_file_location("bridge", path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
from frigate_camera_control_bridge.app import CameraControlBridge
|
||||
|
||||
|
||||
class DiscoveryMappingTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.bridge = load_bridge_module()
|
||||
self.bridge = CameraControlBridge
|
||||
|
||||
def test_loopback_ffmpeg_path_resolves_through_go2rtc(self):
|
||||
camera_cfg = {
|
||||
@@ -30,10 +21,10 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
]
|
||||
}
|
||||
|
||||
urls = self.bridge.CameraControlBridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
urls = self.bridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
|
||||
self.assertEqual(urls, ["rtsp://camera-a.example.test:554/Streaming/Channels/101"])
|
||||
self.assertEqual(self.bridge.CameraControlBridge.hosts_from_urls(urls), ["camera-a.example.test"])
|
||||
self.assertEqual(self.bridge.hosts_from_urls(urls), ["camera-a.example.test"])
|
||||
|
||||
def test_wrapped_go2rtc_stream_resolves_inner_camera_url(self):
|
||||
camera_cfg = {
|
||||
@@ -49,7 +40,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
]
|
||||
}
|
||||
|
||||
urls = self.bridge.CameraControlBridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
urls = self.bridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
|
||||
self.assertEqual(
|
||||
urls,
|
||||
@@ -57,7 +48,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
"rtsp://camera-a.example.test:554/Streaming/Channels/101?profile=main#hardware",
|
||||
],
|
||||
)
|
||||
self.assertEqual(self.bridge.CameraControlBridge.hosts_from_urls(urls), ["camera-a.example.test"])
|
||||
self.assertEqual(self.bridge.hosts_from_urls(urls), ["camera-a.example.test"])
|
||||
|
||||
def test_direct_ffmpeg_path_is_used_without_go2rtc(self):
|
||||
camera_cfg = {
|
||||
@@ -68,10 +59,10 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
|
||||
urls = self.bridge.CameraControlBridge.camera_candidate_urls("camera-b", camera_cfg, {})
|
||||
urls = self.bridge.camera_candidate_urls("camera-b", camera_cfg, {})
|
||||
|
||||
self.assertEqual(urls, ["rtsp://camera-b.example.test:554/cam/realmonitor?channel=1&subtype=0"])
|
||||
self.assertEqual(self.bridge.CameraControlBridge.hosts_from_urls(urls), ["camera-b.example.test"])
|
||||
self.assertEqual(self.bridge.hosts_from_urls(urls), ["camera-b.example.test"])
|
||||
|
||||
def test_wrapped_direct_ffmpeg_path_is_used_without_go2rtc(self):
|
||||
camera_cfg = {
|
||||
@@ -82,7 +73,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
|
||||
urls = self.bridge.CameraControlBridge.camera_candidate_urls("camera-b", camera_cfg, {})
|
||||
urls = self.bridge.camera_candidate_urls("camera-b", camera_cfg, {})
|
||||
|
||||
self.assertEqual(
|
||||
urls,
|
||||
@@ -90,7 +81,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
"rtsp://camera-b.example.test:554/cam/realmonitor?channel=1&subtype=0#video=copy",
|
||||
],
|
||||
)
|
||||
self.assertEqual(self.bridge.CameraControlBridge.hosts_from_urls(urls), ["camera-b.example.test"])
|
||||
self.assertEqual(self.bridge.hosts_from_urls(urls), ["camera-b.example.test"])
|
||||
|
||||
def test_direct_path_wins_when_loopback_is_also_present(self):
|
||||
camera_cfg = {
|
||||
@@ -109,7 +100,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
}
|
||||
}
|
||||
|
||||
urls = self.bridge.CameraControlBridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
urls = self.bridge.camera_candidate_urls("camera-a", camera_cfg, streams)
|
||||
|
||||
self.assertEqual(
|
||||
urls,
|
||||
@@ -118,7 +109,7 @@ class DiscoveryMappingTest(unittest.TestCase):
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
self.bridge.CameraControlBridge.hosts_from_urls(urls),
|
||||
self.bridge.hosts_from_urls(urls),
|
||||
[
|
||||
"direct-camera.example.test",
|
||||
],
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
|
||||
from frigate_camera_control_bridge.ui import render_page
|
||||
|
||||
|
||||
class DummyAction:
|
||||
def __init__(self):
|
||||
self.id = "example_camera_siren"
|
||||
self.platform = "switch"
|
||||
self.kind = "dahua_coaxial_io"
|
||||
self.state = "ON"
|
||||
self.auto_off_seconds = 180
|
||||
self.auto_off_at = 1234567890
|
||||
self.cfg = {
|
||||
"name_key": "action.siren",
|
||||
"requires_ack": True,
|
||||
"snapshot": {"camera": "example", "frigate_url": "http://frigate.example.test:5000"},
|
||||
}
|
||||
|
||||
def display_name(self, lang):
|
||||
return "Example siren"
|
||||
|
||||
def command_list(self):
|
||||
return ["on", "off"]
|
||||
|
||||
|
||||
class UiRenderTest(unittest.TestCase):
|
||||
def test_timer_timestamp_and_ack_survive_server_render(self):
|
||||
html = render_page([DummyAction()], "en")
|
||||
|
||||
self.assertIn('data-auto-off-at="1234567890"', html)
|
||||
self.assertIn('data-requires-ack="true"', html)
|
||||
self.assertIn("Example siren", html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user