Skip to content

added custom background image with path and other overlay support#922

Open
hansherlighed wants to merge 1 commit intoPiotrMachowski:masterfrom
hansherlighed:custom-background-image
Open

added custom background image with path and other overlay support#922
hansherlighed wants to merge 1 commit intoPiotrMachowski:masterfrom
hansherlighed:custom-background-image

Conversation

@hansherlighed
Copy link
Copy Markdown

@hansherlighed hansherlighed commented Apr 9, 2026

Overview

This PR adds two major features to the Roborock Custom Map integration and lovelace-xiaomi-vacuum-map-card:

PR for RoborockCustomMap needed for this to work Lash-L/RoborockCustomMap#38

  1. Static background image support in the card: overlay a custom floor plan image (architectural drawing, manual map, etc.) underneath the live vacuum map, with calibration-based alignment
  2. Configurable map rendering in the integration: select which overlays to show (path, charger, obstacles, etc.), hide floor/walls/rooms for transparent rendering, and rotate the map if needed

These work together to enable transparent vacuum overlays on top of static floor plans, replacing the official map with a custom rendering.

What's New

lovelace-xiaomi-vacuum-map-card Changes

  • New map_source fields:
    • background_image (string): URL of a static image to display underneath the map
    • map_image_opacity (0.0–1.0): fade out the live map to reveal the background
    • background_image_calibration (1–3 point pairs): align the background to vacuum coordinates via affine/similarity/translation transforms
  • Added computeBackgroundMatrix() function for 1/2/3-point calibration
  • Background image rendered at z-index: -1, map overlays rendered on top

RoborockCustomMap Integration Changes

  • New options UI (settings → devices → Roborock Custom Map):

    • Per-drawable toggles: charger, path, cleaned area, obstacles, zones, walls, etc.
    • show_background, show_walls, show_rooms: control map layers
    • show_floor: hide MAP_INSIDE/MAP_SCAN/CARPETS/removed-area pixels (light green zones)
    • Per-map rotation select entity (0°, 90°, 180°, 270°) — rotates both image and calibration
  • Transparent rendering: with all backgrounds disabled + show_floor=False, the rendered image contains only path, charger, and vacuum position on a transparent background

  • Floor color stripping (_remove_floor_colors()): PIL post-processing that makes all floor-colored pixels fully transparent (alpha=0)

  • Map rotation support: rotation stored in hass.data, applied to both the image and calibration point coordinates so overlays stay aligned

  • Race condition fix: _custom_cached_map is only written once after all processing (rendering + floor stripping + rotation), preventing concurrent requests from returning partially-processed images

Why This Approach

Frontend calibration (card) vs. backend rendering (integration)

  • The card handles the background_image_calibration (1–3 points mapping background pixels to vacuum coordinates)
  • The integration handles drawable selection and image transformations (rendering, floor stripping, rotation)
  • This separation allows users to:
    • Use the custom card with any custom integration (not just this one)
    • Use the integration's transparent rendering with other cards
    • Combine them for the best of both worlds

Why rotation in the backend, not CSS

  • Frontend rotation (card-mod) rotates only pixels, leaving calibration unchanged → overlays misalign after rotation
  • Backend rotation rotates both image and calibration map coordinates → overlays and interactions stay correct
  • Persistent: Select entity with RestoreEntity saves orientation across restarts
  • Live: no reload needed; dispatcher signal triggers immediate cache bust

Why transparent rendering instead of cropping

  • With show_floor=False, the custom extractor removes floor colors post-processing, leaving only important overlays
  • PIL is already a dependency (for rotation), so no new deps added
  • Post-processing is fast (single pass over pixel data in executor)

Technical Details

File changes:

lovelace-xiaomi-vacuum-map-card changes:

  • src/types/types.ts: Added BackgroundImageCalibrationPoint interface; added map_source fields
  • src/xiaomi-vacuum-map-card.ts: Added computeBackgroundMatrix(); render <img id="background-image">; apply CSS matrix transform; wire up _updateBackgroundImageTransform()

Backwards Compatibility

  • Custom integration: Default behavior unchanged (no custom options → render default map)
  • Rotation defaults to 0° (no rotation)
  • Existing users unaffected unless they explicitly enable options
  • Card: background_image is optional; if not set, card behaves as before

Tested With

  • Xiaomi Vacuum Map Card (lovelace)
  • Roborock S7 MaxV (multiple maps)
  • Multiple floor plans with different aspect ratios
  • Calibration with 1, 2, and 3 points
  • Map rotation (0°, 90°, 180°, 270°)
  • Drawable toggles and room/zone interactions
  • Transparent rendering + static background overlay

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant