Xiaomi Roborock zone cleanup rule

Hi,

For some reason the FloleVac stopped showing me the map and I couldn’t get zone coordinates. The Mi app do show the map but there is no way that I know how to get the zone coordinates. So following this I wrote a rule for my vacuum. Improvements are more than welcome :slight_smile:

I have a map file for the zones:

kitchen=-5,0.5,3.6,2.6,1
livingroom=0,0.5,4.2,5.2,1
diningroom=-1.6,5.9,2.9,2.7,1

The parameters are:

bottom (y) - meter from the docking point
left (x) - meter from the docking point
w - zone width in meters
h - zone height in meters
repeat - number of times to clean the zone

Note! I’ve chose to use bootom / left / width / height as for me it was simpler to set the coordinates. The vacuum needs bottom / left / top / right.

I defined a zone item:

String Vacuum_Action_Zone "Zone [%s]"

And the rule is:

rule "Vacuum zone cleanup"
when
	Item Vacuum_Action_Zone received command
then
  if (Vacuum_Status_Status.state == "Charging") {
    // Get zone coordinates
    val zone = transform("MAP", "zones.map", receivedCommand.toString)
    // Make sure we have zone parameters
    if (zone != "") {
      // Zone parameters: bottom(y), left(x), width, height, repeats
      var parameters = zone.split(',')
      // Docking point start position
      val double x = 25500.0;
      val double y = 25500.0;
      // Bottom (y) left (x)
      val double b = Double::parseDouble(parameters.get(0)) * 1000.0 + x
      val double l = Double::parseDouble(parameters.get(1)) * 1000.0 + y
      // Top (y) right (x)
      val double t = b + Double::parseDouble(parameters.get(2)) * 1000.0
      val double r = l + Double::parseDouble(parameters.get(3)) * 1000.0
      // Build zone coordinates (and number of times to scan)
      val coordinates = String::format("[[%.0f,%.0f,%.0f,%.0f,%s]]", b, l, t, r, parameters.get(4));
      logInfo(logName, "Clean {} zone coordinates {}", receivedCommand.toString, coordinates)
      Vacuum_Action_Command.sendCommand('app_zoned_clean' + coordinates)
    }
  }
end

Here more information on the map. I am using the zone cleanup editing to get the coordinates.

The main issue with the zone clean - the map rotation - is not handled here and AFAIK there is no solution for that.

4 Likes

Hi,

I have enhanced the rule to support multi zone configuration. In the zone transform file, single zone is defined by numbers, multi zone is a list of single zones, e.g:

entrance=-1.8,0,2,6,1
kitchen=-5,0.5,3.6,2.6,1
livingroom=0,0.5,4.2,5.2,1
diningroom=-1.6,5.9,2.9,2.7,1
groundfloor=entrance,kitchen

The relevant items are:

String Vacuum_Action_Control    "Control"                                   (Vacuum)            { channel="miio:vacuum:04EFCDCA:actions#control" }
String Vacuum_Action_Command    "Command"                                                       { channel="miio:vacuum:04EFCDCA:actions#commands" }

String Vacuum_Control            "Control"                                                      { expire="1s,state=UNDEF" }
String Vacuum_Zone               "Zone [%s]"                   <floor_plan>

And the rule file is:

// Logging name tag
val logName = "Vacuum"

///////////////////////////////////////////////////////////////////////////////
// Function
///////////////////////////////////////////////////////////////////////////////

val Functions$Function1<String, String> getZoneCoordinates =
[zone |
  var parameters = zone.split(',')
  // Docking point start position
  val double x = 25500.0;
  val double y = 25500.0;
  // Bottom (y) left (x)
  val double b = Double::parseDouble(parameters.get(0)) * 1000.0 + x
  val double l = Double::parseDouble(parameters.get(1)) * 1000.0 + y
  // Top (y) right (x)
  val double t = b + Double::parseDouble(parameters.get(2)) * 1000.0
  val double r = l + Double::parseDouble(parameters.get(3)) * 1000.0
  // Build zone coordinates (and number of times to scan)
  val coordinates = String::format("[%.0f,%.0f,%.0f,%.0f,%s]", b, l, t, r, parameters.get(4));
  coordinates
]

///////////////////////////////////////////////////////////////////////////////
// Rule
///////////////////////////////////////////////////////////////////////////////

rule "Vacuum control"
when
  Item Vacuum_Control received command
then
  logInfo(logName, "Vacuum command: {}", receivedCommand.toString)
  if (receivedCommand.toString == "vacuum") {
    // The final command send to the vacuum
    var String command = ""
    // Get zone coordinates
    var String zone = transform("MAP", "zones.map", Vacuum_Zone.state.toString)
    // We still don't know if this is single or multiple zone
    var parameters = zone.split(',')
    try {
      // Single zone only have numbers
      Double::parseDouble(parameters.get(0))
      command = getZoneCoordinates.apply(zone)
    } catch (Throwable t) {
      // This is multi zone
      parameters.forEach[string z|
        zone = transform("MAP", "zones.map", z)
        command = command + getZoneCoordinates.apply(zone) + ","
      ]
      // Remove last ','
      command = command.substring(0, command.length - 1)
    }
    command = String::format("[%s]", command)
    logInfo(logName, "Clean {} zone coordinates {}", receivedCommand.toString, command)
    Vacuum_Action_Command.sendCommand('app_zoned_clean' + command)
  } else {
    Vacuum_Action_Control.sendCommand(receivedCommand.toString)
  }
end

Comments, suggestion, improvements are welocme

2 Likes

Hi Team,

Where does the ‘zones.map’ file sit (path)

@crockernr

The file should be in transform folder. Here is an example of a file:

entrance=-1.8,0,2,6,1
kitchen=-5,0.5,3.6,2.6,1
livingroom=0,0.5,4.2,5.2,1
diningroom=-1.6,5.9,2.9,2.7,1
sofa=1.4,4.8,3,1,1
carpet=1.4,2.1,2,3,1
groundfloor=entrance,kitchen
1 Like

Hey @smhgit This looks great. I’ve setup the files https://github.com/imaginator/system/commit/ec179aea1e4f1d820a4ccc6334ea78a4354e71f4 and am now trying to call this from the openhab-cli.

What’s the best way to be triggering this from the openhab-cli?

openhab> smarthome:send Vacuum_Control ["vacuum", "kitchen"]
or ???

following up to my own idiocy: smarthome:send Vacuum_Action_Zone kitchen works!.