rytilahti / python-miio

Python library & console tool for controlling Xiaomi smart appliances
https://python-miio.readthedocs.io
GNU General Public License v3.0
3.68k stars 552 forks source link

[dreame.vacuum.r2211o] "vacuum-extend:stop-clean" pauses clean instead of finishing it #1880

Closed bdaase closed 9 months ago

bdaase commented 9 months ago

Describe the bug For the dreame.vacuum.r2211o (Xiaomi S10+) the command "vacuum-extend:stop-clean" pauses the clean instead of finishing it. I would have expected this command to return the robot back to its dock, especially since miiocli genericmiot --ip <ip> --token <token> actions doesn't list a special "home" action.

Version information (please complete the following information):

Device information: If the issue is specific to a device [Use miiocli device --ip <ip address> --token <token> info]:

Stop Sweeping (vacuum:stop-sweeping) Access: --x Extras: {'urn': , 'siid': 2, 'aiid': 2, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:stop-sweeping:00002805:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='vacuum' internal_id='00007810' model='dreame-r2211o' version=1 unexpected=None>, description='Stop Sweeping', service=MiotService(siid=2, urn=<URN urn:miot-spec-v2:service:vacuum:00007810:dreame-r2211o:1 parent:None>, description='Robot Cleaner'), aiid=2, inputs=[], outputs=[])}

Start Room Sweep (vacuum:start-room-sweep) Access: --x Extras: {'urn': , 'siid': 2, 'aiid': 3, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:start-room-sweep:00002826:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='vacuum' internal_id='00007810' model='dreame-r2211o' version=1 unexpected=None>, description='Start Room Sweep', service=MiotService(siid=2, urn=<URN urn:miot-spec-v2:service:vacuum:00007810:dreame-r2211o:1 parent:None>, description='Robot Cleaner'), aiid=3, inputs=[MiotProperty(urn=<URN urn:miot-spec-v2:property:room-ids:00000073:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='vacuum' internal_id='00007810' model='dreame-r2211o' version=1 unexpected=None>, description='Room IDs', service=MiotService(siid=2, urn=, description='Robot Cleaner'), piid=4, format=<class 'str'>, access=[], unit=None, range=None, choices=None, gatt_access=None, value=None)], outputs=[])} Inputs: [PropertyDescriptor(id='vacuum:room-ids', name='Room IDs', type=<class 'str'>, unit=None, status_attribute='vacuum_room_ids', access=<AccessFlags: 0>, constraint=<PropertyConstraint.Unset: 1>)]

Start Charge (battery:start-charge) Access: --x Extras: {'urn': , 'siid': 3, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:start-charge:00002802:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='battery' internal_id='00007805' model='dreame-r2211o' version=1 unexpected=None>, description='Start Charge', service=MiotService(siid=3, urn=<URN urn:miot-spec-v2:service🔋00007805:dreame-r2211o:1 parent:None>, description='Battery'), aiid=1, inputs=[], outputs=[])}

Reset Brush Life (brush-cleaner:reset-brush-life) Access: --x Extras: {'urn': , 'siid': 9, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:reset-brush-life:00002830:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='brush-cleaner' internal_id='0000784C' model='dreame-r2211o' version=1 unexpected=None>, description='Reset Brush Life', service=MiotService(siid=9, urn=<URN urn:miot-spec-v2:service:brush-cleaner:0000784C:dreame-r2211o:1 parent:None>, description='Main Cleaning Brush'), aiid=1, inputs=[], outputs=[])}

Reset Brush Life (brush-cleaner:reset-brush-life-2) Access: --x Extras: {'urn': , 'siid': 10, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:reset-brush-life:00002830:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='brush-cleaner' internal_id='0000784C' model='dreame-r2211o' version=1 unexpected=None>, description='Reset Brush Life', service=MiotService(siid=10, urn=<URN urn:miot-spec-v2:service:brush-cleaner:0000784C:dreame-r2211o:1 parent:None>, description='Side Cleaning Brush'), aiid=1, inputs=[], outputs=[])}

Reset Filter Life (filter:reset-filter-life) Access: --x Extras: {'urn': , 'siid': 11, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:miot-spec-v2:action:reset-filter-life:00002803:dreame-r2211o:1 parent:namespace='miot-spec-v2' type='service' name='filter' internal_id='0000780B' model='dreame-r2211o' version=1 unexpected=None>, description='Reset Filter Life', service=MiotService(siid=11, urn=<URN urn:miot-spec-v2:service:filter:0000780B:dreame-r2211o:1 parent:None>, description='Filter'), aiid=1, inputs=[], outputs=[])}

start-clean (vacuum-extend:start-clean) Access: --x Extras: {'urn': , 'siid': 4, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:start-clean:00002801:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='vacuum-extend' internal_id='00007801' model='dreame-r2211o' version=1 unexpected=None>, description='start-clean', service=MiotService(siid=4, urn=<URN urn:dreame-spec:service:vacuum-extend:00007801:dreame-r2211o:1 parent:None>, description='vacuum-extend'), aiid=1, inputs=[MiotProperty(urn=<URN urn:dreame-spec:property:clean-extend-data:0000000a:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='vacuum-extend' internal_id='00007801' model='dreame-r2211o' version=1 unexpected=None>, description='clean-extend-data', service=MiotService(siid=4, urn=, description='vacuum-extend'), piid=10, format=<class 'str'>, access=[<MiotAccess.Write: 'write'>], unit=None, range=None, choices=None, gatt_access=None, value=None), MiotProperty(urn=, description='work-mode', service=MiotService(siid=4, urn=, description='vacuum-extend'), piid=1, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Notify: 'notify'>], unit=None, range=[0, 50, 1], choices=None, gatt_access=None, value=None)], outputs=[])} Inputs: [PropertyDescriptor(id='vacuum-extend:clean-extend-data', name='clean-extend-data', type=<class 'str'>, unit=None, status_attribute='vacuum_extend_clean_extend_data', access=<AccessFlags.Write: 2>, constraint=<PropertyConstraint.Unset: 1>), RangeDescriptor(id='vacuum-extend:work-mode', name='work-mode', unit=None, status_attribute='vacuum_extend_work_mode', access=<AccessFlags.Read: 1>, min_value=0, max_value=50, step=1, range_attribute=None, type=<class 'int'>, constraint=<PropertyConstraint.Range: 2>)]

stop-clean (vacuum-extend:stop-clean) Access: --x Extras: {'urn': , 'siid': 4, 'aiid': 2, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:stop-clean:00002802:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='vacuum-extend' internal_id='00007801' model='dreame-r2211o' version=1 unexpected=None>, description='stop-clean', service=MiotService(siid=4, urn=<URN urn:dreame-spec:service:vacuum-extend:00007801:dreame-r2211o:1 parent:None>, description='vacuum-extend'), aiid=2, inputs=[], outputs=[])}

map-req (map:map-req) Access: --x Extras: {'urn': , 'siid': 6, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:map-req:00002801:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='map' internal_id='00007803' model='dreame-r2211o' version=1 unexpected=None>, description='map-req', service=MiotService(siid=6, urn=, description='map'), aiid=1, inputs=[MiotProperty(urn=, description='frame-info', service=MiotService(siid=6, urn=<URN urn:dreame-spec:service:map:00007803:dreame-r2211o:1 parent:None>, description='map'), piid=2, format=<class 'str'>, access=[<MiotAccess.Write: 'write'>], unit=None, range=None, choices=None, gatt_access=None, value=None)], outputs=[MiotProperty(urn=<URN urn:dreame-spec:property:map-data:00000001:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='map' internal_id='00007803' model='dreame-r2211o' version=1 unexpected=None>, description='map-data', service=MiotService(siid=6, urn=, description='map'), piid=1, format=<class 'str'>, access=[<MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=None, gatt_access=None, value=None), MiotProperty(urn=<URN urn:dreame-spec:property:object-name:00000003:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='map' internal_id='00007803' model='dreame-r2211o' version=1 unexpected=None>, description='object-name', service=MiotService(siid=6, urn=, description='map'), piid=3, format=<class 'str'>, access=[<MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=None, gatt_access=None, value=None), MiotProperty(urn=, description='robot-time', service=MiotService(siid=6, urn=<URN urn:dreame-spec:service:map:00007803:dreame-r2211o:1 parent:None>, description='map'), piid=5, format=<class 'int'>, access=[<MiotAccess.Notify: 'notify'>], unit=None, range=[0, 999999999999999, 1], choices=None, gatt_access=None, value=None)])} Inputs: [PropertyDescriptor(id='map:frame-info', name='frame-info', type=<class 'str'>, unit=None, status_attribute='map_frame_info', access=<AccessFlags.Write: 2>, constraint=<PropertyConstraint.Unset: 1>)]

update-map (map:update-map) Access: --x Extras: {'urn': , 'siid': 6, 'aiid': 2, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:update-map:00002802:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='map' internal_id='00007803' model='dreame-r2211o' version=1 unexpected=None>, description='update-map', service=MiotService(siid=6, urn=, description='map'), aiid=2, inputs=[MiotProperty(urn=, description='map-extend-data', service=MiotService(siid=6, urn=, description='map'), piid=4, format=<class 'str'>, access=[<MiotAccess.Write: 'write'>], unit=None, range=None, choices=None, gatt_access=None, value=None)], outputs=[MiotProperty(urn=<URN urn:dreame-spec:property:result-code:00000006:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='map' internal_id='00007803' model='dreame-r2211o' version=1 unexpected=None>, description='result-code', service=MiotService(siid=6, urn=<URN urn:dreame-spec:service:map:00007803:dreame-r2211o:1 parent:None>, description='map'), piid=6, format=<class 'int'>, access=[<MiotAccess.Notify: 'notify'>], unit=None, range=[-10000, 10000, 1], choices=None, gatt_access=None, value=None)])} Inputs: [PropertyDescriptor(id='map:map-extend-data', name='map-extend-data', type=<class 'str'>, unit=None, status_attribute='map_map_extend_data', access=<AccessFlags.Write: 2>, constraint=<PropertyConstraint.Unset: 1>)]

position (audio:position) Access: --x Extras: {'urn': , 'siid': 7, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:position:00002801:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='audio' internal_id='00007804' model='dreame-r2211o' version=1 unexpected=None>, description='position', service=MiotService(siid=7, urn=, description='audio'), aiid=1, inputs=[], outputs=[])}

play-sound (audio:play-sound) Access: --x Extras: {'urn': , 'siid': 7, 'aiid': 2, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:play-sound:00002802:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='audio' internal_id='00007804' model='dreame-r2211o' version=1 unexpected=None>, description='play-sound', service=MiotService(siid=7, urn=<URN urn:dreame-spec:service:audio:00007804:dreame-r2211o:1 parent:None>, description='audio'), aiid=2, inputs=[], outputs=[])}

delete-timer (time:delete-timer) Access: --x Extras: {'urn': , 'siid': 8, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:delete-timer:00002801:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='time' internal_id='00007805' model='dreame-r2211o' version=1 unexpected=None>, description='delete-timer', service=MiotService(siid=8, urn=<URN urn:dreame-spec:service:time:00007805:dreame-r2211o:1 parent:None>, description='time'), aiid=1, inputs=[MiotProperty(urn=, description='timer-id', service=MiotService(siid=8, urn=, description='time'), piid=3, format=<class 'str'>, access=[], unit=None, range=None, choices=None, gatt_access=None, value=None)], outputs=[])} Inputs: [PropertyDescriptor(id='time:timer-id', name='timer-id', type=<class 'str'>, unit=None, status_attribute='time_timer_id', access=<AccessFlags: 0>, constraint=<PropertyConstraint.Unset: 1>)]

reset-mop-life (mop:reset-mop-life) Access: --x Extras: {'urn': , 'siid': 18, 'aiid': 1, 'miot_action': MiotAction(urn=<URN urn:dreame-spec:action:reset-mop-life:00002801:dreame-r2211o:1 parent:namespace='dreame-spec' type='service' name='mop' internal_id='0000780c' model='dreame-r2211o' version=1 unexpected=None>, description='reset-mop-life', service=MiotService(siid=18, urn=<URN urn:dreame-spec:service:mop:0000780c:dreame-r2211o:1 parent:None>, description='mop'), aiid=1, inputs=[], outputs=[])}



**To Reproduce**
Steps to reproduce the behavior:
1.  `miiocli genericmiot --ip <ip> --token <token> vacuum-extend:start-clean` --> robot starts clean up
1.  `miiocli genericmiot --ip <ip> --token <token> vacuum-extend:stop-clean` --> robot pauses the clean up but doesn't return to its dock.

**Expected behavior**
I would have expected the robot to return back to the dock.

**Console output**
n/a
bdaase commented 9 months ago

It turns out miiocli genericmiot --ip <ip> --token <token> battery:start-charge actually makes the robot return to its dock. I still find the naming of the actions weird, though.

rytilahti commented 9 months ago

Glad you got it working. The naming for genericmiot actions comes directly from the schema file, but having some set of generic, device class specific actions with nicer aliases could be useful thing in the future.

bdaase commented 9 months ago

Yes, I think the more devices are added in the future, the more important this issue will become. It is also confusing at first that the same action (e.g. start cleaning) has different action definitions depending on the device (e.g. vacuum:start-sweep vs. vacuum-extend:start-clean).

rytilahti commented 9 months ago

Most if not all modern devices use the schema files, so they are implicitly supported already. That vacuum-extend may be some non-standard service which may accept some extra parameters or something else in contrast to the standard one.

But supporting at least the standardized actions for each device class with a nicer name would be great indeed. I haven't been using nor developing this library that much for a while, so it may take some time until I or someone else who wants to contribute goes and makes that happen... I just hope to find some time and motivation early next year to fix any blockers for the 0.6 release.