@@ -325,7 +325,7 @@ class State:
325325 brightness : int
326326 nightlight : Nightlight
327327 on : bool
328- playlist : int
328+ playlist : Playlist | int | None
329329 preset : Preset | int | None
330330 segments : list [Segment ]
331331 sync : Sync
@@ -356,14 +356,16 @@ def from_dict(
356356 effects : list [Effect ],
357357 palettes : list [Palette ],
358358 presets : list [Preset ],
359+ playlists : list [Playlist ],
359360 ) -> State :
360361 """Return State object from WLED API response.
361362
362363 Args:
363364 data: The state response received from the WLED device API.
364365 effects: A list of effect objects.
365366 palettes: A list of palette objects.
366- presets: A list of presets objects.
367+ presets: A list of preset objects.
368+ playlists: A list of playlist objects.
367369
368370 Returns:
369371 A State object.
@@ -384,18 +386,24 @@ def from_dict(
384386 for segment_id , segment in enumerate (data .get ("seg" , []))
385387 ]
386388
389+ playlist = data .get ("pl" , - 1 )
387390 preset = data .get ("ps" , - 1 )
388391 if presets :
389392 preset = next (
390393 (item for item in presets if item .preset_id == data .get ("ps" )),
391394 None ,
392395 )
393396
397+ playlist = next (
398+ (item for item in playlists if item .playlist_id == data .get ("pl" )),
399+ None ,
400+ )
401+
394402 return State (
395403 brightness = brightness ,
396404 nightlight = Nightlight .from_dict (data ),
397405 on = on ,
398- playlist = data . get ( "pl" , - 1 ) ,
406+ playlist = playlist ,
399407 preset = preset ,
400408 segments = segments ,
401409 sync = Sync .from_dict (data ),
@@ -469,12 +477,82 @@ def from_dict(
469477 )
470478
471479
480+ @dataclass
481+ class PlaylistEntry :
482+ """Object representing a entry in a WLED playlist."""
483+
484+ duration : int
485+ entry_id : int
486+ preset : Preset | None
487+ transition : int
488+
489+
490+ @dataclass
491+ class Playlist :
492+ """Object representing a WLED playlist."""
493+
494+ end : Preset | None
495+ entries : list [PlaylistEntry ]
496+ name : str
497+ playlist_id : int
498+ repeat : int
499+ shuffle : bool
500+
501+ @staticmethod
502+ def from_dict (
503+ playlist_id : int ,
504+ data : dict [str , Any ],
505+ presets : list [Preset ],
506+ ) -> Playlist :
507+ """Return Playlist object from WLED API response.
508+
509+ Args:
510+ playlist_id: The ID of the playlist.
511+ data: The data from the WLED device API.
512+ presets: A list of preset objects.
513+
514+ Returns:
515+ A Playlist object.
516+ """
517+ playlist = data .get ("playlist" , {})
518+ entries_durations = playlist .get ("dur" , [])
519+ entries_presets = playlist .get ("ps" , [])
520+ entries_transitions = playlist .get ("transition" , [])
521+
522+ entries = [
523+ PlaylistEntry (
524+ entry_id = entry_id ,
525+ duration = entries_durations [entry_id ],
526+ transition = entries_transitions [entry_id ],
527+ preset = next (
528+ (item for item in presets if item .preset_id == preset_id ), None
529+ ),
530+ )
531+ for entry_id , preset_id in enumerate (entries_presets )
532+ ]
533+
534+ end = next (
535+ (item for item in presets if item .preset_id == playlist .get ("end" )),
536+ None ,
537+ )
538+
539+ return Playlist (
540+ playlist_id = playlist_id ,
541+ shuffle = playlist .get ("r" , False ),
542+ name = data .get ("n" , str (playlist_id )),
543+ repeat = playlist .get ("repeat" , 0 ),
544+ end = end ,
545+ entries = entries ,
546+ )
547+
548+
472549class Device :
473550 """Object holding all information of WLED."""
474551
475552 effects : list [Effect ] = []
476553 info : Info
477554 palettes : list [Palette ] = []
555+ playlists : list [Playlist ] = []
478556 presets : list [Preset ] = []
479557 state : State
480558
@@ -523,20 +601,37 @@ def update_from_dict(self, data: dict) -> Device:
523601 self .palettes = palettes
524602
525603 if _presets := data .get ("presets" ):
604+ # The preset data contains both presets and playlists,
605+ # we split those out, so we can handle those correctly.
606+
607+ # Nobody cares about 0.
526608 _presets .pop ("0" )
609+
527610 presets = [
528611 Preset .from_dict (int (preset_id ), preset , self .effects , self .palettes )
529612 for preset_id , preset in _presets .items ()
613+ if "playlist" not in preset
614+ or not ("ps" in preset ["playlist" ] and preset ["playlist" ]["ps" ])
530615 ]
531616 presets .sort (key = lambda x : x .name )
532617 self .presets = presets
533618
619+ playlists = [
620+ Playlist .from_dict (int (playlist_id ), playlist , self .presets )
621+ for playlist_id , playlist in _presets .items ()
622+ if "playlist" in playlist
623+ and "ps" in playlist ["playlist" ]
624+ and playlist ["playlist" ]["ps" ]
625+ ]
626+ playlists .sort (key = lambda x : x .name )
627+ self .playlists = playlists
628+
534629 if _info := data .get ("info" ):
535630 self .info = Info .from_dict (_info )
536631
537632 if _state := data .get ("state" ):
538633 self .state = State .from_dict (
539- _state , self .effects , self .palettes , self .presets
634+ _state , self .effects , self .palettes , self .presets , self . playlists
540635 )
541636
542637 return self
0 commit comments