@@ -711,6 +711,103 @@ async def set_vacuum_mode(self, serial: str, value: str):
711711 raise
712712
713713
714+ async def exec_device_command (self , serial : str , action : str ):
715+ """Execute a device command via execCmdService.
716+
717+ Discovered actions for the Luma Smart Litter Box:
718+ CLEAN / STOP_CLEAN / SUSPEND_CLEAN / RESTART_CLEAN
719+ EMPTY / STOP_EMPTY / RESTART_EMPTY
720+ LEVELING / RESTART_LEVELING
721+ VACUUM (air purifier)
722+ OPEN_DOOR / CLOSE_DOOR
723+ STOP / CANCEL
724+ """
725+ _LOGGER .debug (f"Executing device command: serial={ serial } , action={ action } " )
726+ try :
727+ request_id = str (uuid .uuid4 ()).replace ("-" , "" )
728+ response = await self .session .post ("/device/device/execCmdService" , json = {
729+ "deviceSn" : serial ,
730+ "action" : action ,
731+ "requestId" : request_id ,
732+ })
733+ _LOGGER .debug (f"execCmdService({ action } ) returned: { response } " )
734+ return response
735+ except Exception as e :
736+ _LOGGER .error (f"Failed to exec command { action } for device { serial } : { e } " )
737+ raise
738+
739+ async def trigger_manual_clean (self , serial : str ):
740+ """Trigger a manual clean cycle on a litter box device."""
741+ return await self .exec_device_command (serial , "CLEAN" )
742+
743+ async def trigger_empty_waste (self , serial : str ):
744+ """Trigger waste bin emptying on a litter box device."""
745+ return await self .exec_device_command (serial , "EMPTY" )
746+
747+ async def trigger_level_litter (self , serial : str ):
748+ """Trigger litter leveling on a litter box device."""
749+ return await self .exec_device_command (serial , "LEVELING" )
750+
751+ async def trigger_stop_device_action (self , serial : str ):
752+ """Stop the current device action."""
753+ return await self .exec_device_command (serial , "STOP" )
754+
755+ async def trigger_open_door (self , serial : str ):
756+ """Open the litter box door."""
757+ return await self .exec_device_command (serial , "OPEN_DOOR" )
758+
759+ async def trigger_close_door (self , serial : str ):
760+ """Close the litter box door."""
761+ return await self .exec_device_command (serial , "CLOSE_DOOR" )
762+
763+ async def trigger_vacuum (self , serial : str ):
764+ """Trigger the air purifier (vacuum) on a litter box device."""
765+ return await self .exec_device_command (serial , "VACUUM" )
766+
767+ async def set_clean_mode (self , serial : str , clean_mode : str , auto_delay_sec : int = 60 ):
768+ """Set the litter box clean mode (AUTO/MANUAL) and auto-delay."""
769+ _LOGGER .debug (f"Setting clean mode: serial={ serial } , mode={ clean_mode } , delay={ auto_delay_sec } " )
770+ try :
771+ response = await self .session .post ("/device/setting/updateCleanModeSetting" , json = {
772+ "deviceSn" : serial ,
773+ "cleanMode" : clean_mode ,
774+ "autoDelaySec" : auto_delay_sec ,
775+ })
776+ _LOGGER .debug (f"Clean mode update returned code: { response } " )
777+ return response
778+ except Exception as e :
779+ _LOGGER .error (f"Failed to set clean mode for device { serial } : { e } " )
780+ raise
781+
782+ async def set_deodorization_setting (self , serial : str , mode : str , switch : bool ):
783+ """Update deodorization mode and master switch."""
784+ _LOGGER .debug (f"Setting deodorization: serial={ serial } , mode={ mode } , switch={ switch } " )
785+ try :
786+ response = await self .session .post ("/device/setting/updateDeodorizationSetting" , json = {
787+ "deviceSn" : serial ,
788+ "deodorizationMode" : mode ,
789+ "deodorizationModeSwitch" : switch ,
790+ })
791+ _LOGGER .debug (f"Deodorization setting returned code: { response } " )
792+ return response
793+ except Exception as e :
794+ _LOGGER .error (f"Failed to set deodorization for device { serial } : { e } " )
795+ raise
796+
797+ async def set_volume (self , serial : str , volume : int ):
798+ """Set speaker volume (0-100)."""
799+ _LOGGER .debug (f"Setting volume: serial={ serial } , volume={ volume } " )
800+ try :
801+ response = await self .session .post ("/device/setting/updateVolumeSetting" , json = {
802+ "deviceSn" : serial ,
803+ "volume" : volume ,
804+ })
805+ _LOGGER .debug (f"Volume setting returned code: { response } " )
806+ return response
807+ except Exception as e :
808+ _LOGGER .error (f"Failed to set volume for device { serial } : { e } " )
809+ raise
810+
714811 # Not supported by the dockstream device firmware yet. hoping that maybe it will be in the future, so leaving code here.
715812 # async def set_water_sensing_delay(self, serial: str, value: float, current_mode: int):
716813 # """Set the water sensing delay."""
0 commit comments