Add Art-Net / sACN (E1.31) DMX device support
Full-stack implementation of DMX output for stage lighting and LED controllers: - DMXClient with Art-Net and sACN packet builders, multi-universe splitting - DMXDeviceProvider with manual_led_count capability and URL parsing - Device store, API schemas, routes wired with dmx_protocol/start_universe/start_channel - Frontend: add/settings modals with DMX fields, IconSelect protocol picker - Fix add device modal dirty check on type change (re-snapshot after switch) - i18n keys for DMX in en/ru/zh locales Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,9 @@ def _device_to_response(device) -> DeviceResponse:
|
||||
zone_mode=device.zone_mode,
|
||||
capabilities=sorted(get_device_capabilities(device.device_type)),
|
||||
tags=getattr(device, 'tags', []),
|
||||
dmx_protocol=getattr(device, 'dmx_protocol', 'artnet'),
|
||||
dmx_start_universe=getattr(device, 'dmx_start_universe', 0),
|
||||
dmx_start_channel=getattr(device, 'dmx_start_channel', 1),
|
||||
created_at=device.created_at,
|
||||
updated_at=device.updated_at,
|
||||
)
|
||||
@@ -129,6 +132,9 @@ async def create_device(
|
||||
rgbw=device_data.rgbw or False,
|
||||
zone_mode=device_data.zone_mode or "combined",
|
||||
tags=device_data.tags,
|
||||
dmx_protocol=device_data.dmx_protocol or "artnet",
|
||||
dmx_start_universe=device_data.dmx_start_universe or 0,
|
||||
dmx_start_channel=device_data.dmx_start_channel or 1,
|
||||
)
|
||||
|
||||
# WS devices: auto-set URL to ws://{device_id}
|
||||
@@ -313,6 +319,9 @@ async def update_device(
|
||||
rgbw=update_data.rgbw,
|
||||
zone_mode=update_data.zone_mode,
|
||||
tags=update_data.tags,
|
||||
dmx_protocol=update_data.dmx_protocol,
|
||||
dmx_start_universe=update_data.dmx_start_universe,
|
||||
dmx_start_channel=update_data.dmx_start_channel,
|
||||
)
|
||||
|
||||
# Sync connection info in processor manager
|
||||
|
||||
@@ -19,6 +19,10 @@ class DeviceCreate(BaseModel):
|
||||
rgbw: Optional[bool] = Field(None, description="RGBW mode (mock devices)")
|
||||
zone_mode: Optional[str] = Field(None, description="OpenRGB zone mode: combined or separate")
|
||||
tags: List[str] = Field(default_factory=list, description="User-defined tags")
|
||||
# DMX (Art-Net / sACN) fields
|
||||
dmx_protocol: Optional[str] = Field(None, description="DMX protocol: artnet or sacn")
|
||||
dmx_start_universe: Optional[int] = Field(None, ge=0, le=32767, description="DMX start universe")
|
||||
dmx_start_channel: Optional[int] = Field(None, ge=1, le=512, description="DMX start channel (1-512)")
|
||||
|
||||
|
||||
class DeviceUpdate(BaseModel):
|
||||
@@ -34,6 +38,9 @@ class DeviceUpdate(BaseModel):
|
||||
rgbw: Optional[bool] = Field(None, description="RGBW mode (mock devices)")
|
||||
zone_mode: Optional[str] = Field(None, description="OpenRGB zone mode: combined or separate")
|
||||
tags: Optional[List[str]] = None
|
||||
dmx_protocol: Optional[str] = Field(None, description="DMX protocol: artnet or sacn")
|
||||
dmx_start_universe: Optional[int] = Field(None, ge=0, le=32767, description="DMX start universe")
|
||||
dmx_start_channel: Optional[int] = Field(None, ge=1, le=512, description="DMX start channel (1-512)")
|
||||
|
||||
|
||||
class CalibrationLineSchema(BaseModel):
|
||||
@@ -128,6 +135,9 @@ class DeviceResponse(BaseModel):
|
||||
zone_mode: str = Field(default="combined", description="OpenRGB zone mode: combined or separate")
|
||||
capabilities: List[str] = Field(default_factory=list, description="Device type capabilities")
|
||||
tags: List[str] = Field(default_factory=list, description="User-defined tags")
|
||||
dmx_protocol: str = Field(default="artnet", description="DMX protocol: artnet or sacn")
|
||||
dmx_start_universe: int = Field(default=0, description="DMX start universe")
|
||||
dmx_start_channel: int = Field(default=1, description="DMX start channel (1-512)")
|
||||
created_at: datetime = Field(description="Creation timestamp")
|
||||
updated_at: datetime = Field(description="Last update timestamp")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user