Xiaomi Roborock zone cleanup rule

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

3 Likes