[Mqtt] Xiamoi/Roborock with Valetudo

Hello together,

Tl:dr How do you use Valetudos mqtt?

Long Version
I have a Xiamoi/Roborock S5x vacuum roboter which works great. To get rid of the cloud (and another app) I rooted the robot and installed Valetudo which is basically a local cloud replacement running on top of the original firmware. Valetudo sends the robots status via mqtt and uses for that an “official” Home Assistant vacuum mqtt scheme. openHAB supports already a couple of Home Assistant schemes, but unfortunately not the vacuum scheme yet. There is already an issue for openHAB to integrate this, but we all know this could take some time.

In the meantime I would like to know how some of you have integrated valetudo in openHAB. While sending commands can perfectly be done in rules, I am highly interested on how to fetch the current “state” of the robot which is published periodically and at every change via mqtt.

@kofi based on this screenshot, it seems like you have solved this already. If you have time, can you be so kind and share how you have done it?

Create a Generic MQTT Thing and then create a new Channel for each sensor (the robot only reports data) and actuator (openHAB can tell the robot to do something). Link Items to each channel.

The sensors will only have a subscribe topic. Actuators will have both a subscribe anda command topic. In both cases you will likely need to transform the messages.

Hi

here my mqtt thing for valetudo

   Thing topic roborock {
        Channels:
            Type string : state "State" [ stateTopic="valetudo/rockrobo/state" ]
            Type string : attributes "Attributes" [ stateTopic="valetudo/rockrobo/attributes" ]
            Type string : custom_command "Custom Command" [ stateTopic="valetudo/rockrobo/custom_command" ]
    }

To parse and handle the json message received by the attributes topic I use jython, so this will most likely not help you.
In the json message you have to get the value of valetudo_state->id which is numeric.

Here the map between id and state

# codes from https://github.com/rand256/valetudo/blob/testing/lib/miio/Vacuum.js
state_map_id = {
    1: "starting",
    2: "charger_disconnected",
    3: "idle",
    4: "remote_control_active",
    5: "cleaning",
    6: "return_dock",
    7: "manual_mode",
    8: "docked",
    9: "charge_error",
    10: "paused",
    11: "clean_spot",
    12: "error",
    13: "shutting_down",
    14: "updating",
    15: "docking",
    16: "goto_target",
    17: "clean_zone",
    18: "clean_room",
}

Hope that helps

UPDATE

Item:

String ST_KI_VACUUM_MQTT_Attributes "MQTT Attributes [%s]"
    (gVacMQTT)
    { channel="mqtt:topic:local:roborock:attributes" }

and finally the rule I use to update the state in habpanel

@rule("Roborock Attributes MQTT", description="Handle attributes received via MQTT")
@when("Item ST_KI_VACUUM_MQTT_Attributes changed")
def roboMQTTAttributes(event):
    attr = dict()
    try:
        attr = json.loads(event.itemState.toString())
    except:
        roboMQTTAttributes.log.error("Could not parse [{}] to json".format(event.itemState))
        return

    if 'valetudo_state' in attr:
         roboMQTTAttributes.log.error("Updating state to [{}]".format(attr['valetudo_state']))
         id = attr['valetudo'_state']['id]
         if id not in state_map_id:
             log.error("unknown state [{}]".format(id))
             return
         state = state_map_id.get(id)
         send_command_if_different("ST_KI_VACUUM_VIRT_State", state)

The code above is not tested because I have this more integrated in a own class but it should give you an idea how I did it.

1 Like

@rlkoshak thanks. I already thought so but was struggling with the (not yet documented) mqtt text file configuration (which turned out to be rather simple as shown by kofi)

@kofi thank you very much. That helped really a lot! I got the things and unmapped items already working on the frist try. I can imagine that when using jython, the mapping might be even easier to do. I have not tried jython yet but maybe this will make me try it. Thanks!