Skip to content
Open
4 changes: 4 additions & 0 deletions backend_py/src/models/cameras.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
INTEGER_MENU = 9


class ControlTypeEnum(str, Enum):

Check failure on line 25 in backend_py/src/models/cameras.py

View workflow job for this annotation

GitHub Actions / build

ruff (UP042)

backend_py/src/models/cameras.py:25:7: UP042 Class ControlTypeEnum inherits from both `str` and `enum.Enum` help: Inherit from `enum.StrEnum`
INTEGER = "INTEGER"
BOOLEAN = "BOOLEAN"
MENU = "MENU"
Expand All @@ -34,14 +34,14 @@
INTEGER_MENU = "INTEGER_MENU"


class StreamEncodeTypeEnum(str, Enum):

Check failure on line 37 in backend_py/src/models/cameras.py

View workflow job for this annotation

GitHub Actions / build

ruff (UP042)

backend_py/src/models/cameras.py:37:7: UP042 Class StreamEncodeTypeEnum inherits from both `str` and `enum.Enum` help: Inherit from `enum.StrEnum`
MJPG = "MJPG"
H264 = "H264"
SOFTWARE_H264 = "SOFTWARE_H264"
NONE = "NONE"


class StreamTypeEnum(str, Enum):

Check failure on line 44 in backend_py/src/models/cameras.py

View workflow job for this annotation

GitHub Actions / build

ruff (UP042)

backend_py/src/models/cameras.py:44:7: UP042 Class StreamTypeEnum inherits from both `str` and `enum.Enum` help: Inherit from `enum.StrEnum`
UDP = "UDP"

RECORDING = "RECORDING"
Expand Down Expand Up @@ -161,6 +161,8 @@
height: int
interval: IntervalModel
enabled: bool
recording_interval: int
recording_length: int

class Config:
from_attributes = True
Expand Down Expand Up @@ -230,6 +232,8 @@
encode_type: StreamEncodeTypeEnum
enabled: bool
endpoints: list[StreamEndpointModel]
recording_interval: int
recording_length: int

class Config:
from_attributes = True
Expand Down
3 changes: 3 additions & 0 deletions backend_py/src/models/saved_cameras.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class SavedStreamModel(BaseModel):
height: int
interval: IntervalModel
enabled: bool
# Defaults keep settings saved before interval recording loadable
recording_interval: int = 0
recording_length: int = 0

class Config:
# use_enum_values = True
Expand Down
5 changes: 4 additions & 1 deletion backend_py/src/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ def __init__(

# Device Manager
self.device_manager = DeviceManager(
settings_manager=self.settings_manager, sio=self.sio, serial=self.serial
settings_manager=self.settings_manager,
sio=self.sio,
serial=self.serial,
serial_mode_fps=False, # Spelunky
)

self.server_logger = logging.getLogger("dwe_os_2.Server")
Expand Down
36 changes: 34 additions & 2 deletions backend_py/src/services/cameras/device_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
from .exceptions import DeviceNotFoundException
from .pwm.serial_pwm_controller import SerialPWMController

LIGHT_PWM_FREQ = 60


def todict(obj, classkey=None) -> Any:
if isinstance(obj, dict):
Expand Down Expand Up @@ -73,6 +75,9 @@ def __init__(
sio: socketio.AsyncServer,
settings_manager: SettingsManager,
serial: SerialPWMController,
# Defines whether or not the serial communication is
# used to set the FPS or just duty cycle
serial_mode_fps=True,
) -> None:
super().__init__()

Expand All @@ -85,6 +90,7 @@ def __init__(
self.stream_errors: list[str] = []

self.serial = serial
self.serial_mode_fps = serial_mode_fps

self.logger = logging.getLogger("dwe_os_2.cameras.DeviceManager")

Expand Down Expand Up @@ -143,6 +149,13 @@ def create_device(self, device_info: DeviceInfo) -> Device | None:
lambda _: self._append_stream_error(DeviceModel.model_validate(device)),
)

# if not self.serial_mode_fps:
# device.stream_runner.on("stream_active",
# lambda: self._set_light(True))
#
# device.stream_runner.on("stream_inactive",
# lambda: self._set_light(False))

# Hack to allow shd to save follower and leader settings on removal
device.on("save", lambda: self.settings_manager.save_device(device))

Expand All @@ -155,11 +168,21 @@ def create_device(self, device_info: DeviceInfo) -> Device | None:
)

# Only followers will update PWM frequency
if self.serial and device.can_follow:
if self.serial and device.can_follow and self.serial_mode_fps:
device.on("pwm_frequency", self.serial.apply_from_fps)

return device

def _set_light(self, enabled: bool) -> None:
"""
Sends a signal to the PWM controller assuming it is connected to a light
"""

self.logger.info(f"Applying value to light: {enabled}")

if self.serial:
self.serial.apply(LIGHT_PWM_FREQ, 100 if enabled else 0)

def _append_stream_error(self, device: DeviceModel) -> None:
"""
Helper function to append a gst error
Expand Down Expand Up @@ -218,9 +241,18 @@ def configure_device_stream(self, stream_info: StreamInfoModel) -> bool:
encode_type: StreamEncodeTypeEnum = stream_info.encode_type
stream_type: StreamTypeEnum = stream_info.stream_type
endpoints = stream_info.endpoints
recording_interval = stream_info.recording_interval
recording_length = stream_info.recording_length

device.configure_stream(
encode_type, width, height, interval, stream_type, endpoints
encode_type,
width,
height,
interval,
stream_type,
recording_interval,
recording_length,
endpoints,
)

if stream_info.enabled:
Expand Down
6 changes: 6 additions & 0 deletions backend_py/src/services/cameras/drivers/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ def configure_stream(
height: int,
interval: IntervalModel,
stream_type: StreamTypeEnum,
recording_interval: int,
recording_length: int,
stream_endpoints: list[StreamEndpointModel] | None = None,
) -> None:
if stream_endpoints is None:
Expand Down Expand Up @@ -249,6 +251,8 @@ def configure_stream(
self.stream.endpoints = stream_endpoints
self.stream.encode_type = encode_type
self.stream.stream_type = stream_type
self.stream.recording_interval = recording_interval
self.stream.recording_length = recording_length

# Update the pwm frequency with the new fps
# TODO: This should be on a command bus or something, not emitted from
Expand Down Expand Up @@ -314,6 +318,8 @@ def load_settings(self, saved_device: SavedDeviceModel) -> None:
saved_device.stream.height,
saved_device.stream.interval,
saved_device.stream.stream_type,
saved_device.stream.recording_interval,
saved_device.stream.recording_length,
saved_device.stream.endpoints,
)

Expand Down
2 changes: 2 additions & 0 deletions backend_py/src/services/cameras/drivers/shd/shd.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ def start_stream(self) -> None:
self.stream.height,
self.stream.interval,
self.stream.stream_type,
self.stream.recording_interval,
self.stream.recording_length,
[],
)

Expand Down
6 changes: 3 additions & 3 deletions backend_py/src/services/cameras/pwm/serial_pwm_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ def apply(self, frequency: float, duty_cycle: int) -> None:
# have the correct clock frequency
self.frequency = frequency
self.duty_cycle = duty_cycle
if not self.found_port:
return
command = f"{frequency + self.frequency_offset},{duty_cycle}\n"

self.logger.info(f"Sending command {command.strip()}")
if not self.found_port:
return
if self.serial:
self.logger.info(f"Sending command {command.strip()}")
self.serial.write(command.encode("utf-8"))

def apply_from_fps(self, fps: int) -> None:
Expand Down
Loading
Loading