If you haven’t created your floorplan image yet, I’d reccomend you take a look at my previous post on how to use Sweet Home 3D to create your floorplan. To create our interactive floorplan we will be using a picture-elements card. I’d reccomend reading Jaun’s write up on using picture elements to create a 2D floorplan using a picture-elements card.

In the remainder of this post I will document the basic code and configuration as well as diving into some of the specifics for more advanced functionality.

Creating the Images

To get started you will need two 3D renders of your floorplan. The first should be with all of the lights on and the second should be with all of the lights off. If you want more accurate lighting when you have multiple lights in a room you can also go wild and create a different render for every combination of lights on/off in a room. That was a bit overkill for me, so I instead decided on 2 renders and using some photo editing software like gimp to create images of rooms with the lights off.

I ended up creating layers on top of the base image which I decided would be the floorplan with all of the lights on. I then created a new layer for each room with the lights off by duplicating the lights off layer and deleting any part of the duplicated layer that was not part of the room I was creating the image for. See the example below of the layer for the kitchen with the lights off.

The image above will be layered on top of the base image with the lights on and will be toggled in homeassistant in order to show the lights on or off in the kitchen based on the state of the kitchen lights. You will need to repeat this process for each room in order to generate all images of the rooms with the lights off. You will want each of these images to be the exact same size as the base image. In my case I ended up with 28 total images.

Adding a Floorplan View and Toggling Lights

Below is a concise example of how to create a view for your floorplan that will allow you to toggle the lights in the kitchen. They will turn on/off based on the state of light.kitchen in home assistant.

title : Floorplan path : floorplan panel : true icon : mdi:floor-plan cards : - type : picture-elements image : /local/first_floor_lights_on.png elements : # Lighting Overlays - type : image entity : light.kitchen tap_action : none hold_action : none state_image : " on" : /local/transparent_square.png " off" : /local/first_floor_kitchen_lights_off.png style : top : 50% left : 50% width : 100% # Light Toggles - type : image entity : light.kitchen tap_action : action : toggle image : /local/transparent_square.png style : top : 71% left : 40.5%

A few things to note about the above example:

Set panel: true for your view. This will allow it to take up the entire viewport and ensure that the layered images properly line up when you set the css style attributes for placement of the button to toggle the light.

for your view. This will allow it to take up the entire viewport and ensure that the layered images properly line up when you set the css style attributes for placement of the button to toggle the light. For each light overlay set the tap_action and hold_action to none . If you do not do this, the entire image will be clickable and only toggle the last overlay in your list. Instead we will add a light toggle of a small transparent square that will sit on top of the light in the picture. This way we will be able to click on a small portion of the image to toggle the state of the light.

and to . If you do not do this, the entire image will be clickable and only toggle the last overlay in your list. Instead we will add a light toggle of a small transparent square that will sit on top of the light in the picture. This way we will be able to click on a small portion of the image to toggle the state of the light. The on image for the state_image of each lighting overlay should also be set to the transparent square image. This will let the base image show which has the lights on.

image for the of each lighting overlay should also be set to the transparent square image. This will let the base image show which has the lights on. Note the style attributes for the lighting overlay. These values will be the same for each overlay image.

attributes for the lighting overlay. These values will be the same for each overlay image. Ensure that you put all of your lighting overlays at the top of your view. All of the toggles should be below your overlays. If you do not do this, then you will not be able to click on any of your toggles. So the order matters.

In order to accurately place the transparent square over top of the portion of the image you want to click on you will need to set it’s position in the style portion of the the toggle image. I used the chrome or firefox developer tools to find the transparent_square.png image then adjust it’s CSS top and left attributes until it’s centered over the light that I want to click. In order to make it easier to see I added a red border in the style until I found the correct position. For example:

- type : image entity : light.kitchen tap_action : action : toggle image : /local/transparent_square.png style : top : 71% left : 40.5% border : 5px solid red

The code above will result in the image you see below. You can then freely adjust the attributes until it’s in the desired location and then remove the border from your configuration.

Creating a Floor Toggle

Creating a button to toggle the floor was something I struggled to find solutions for. After some investigation I settled on using an input select in combination with a conditional card. Then on each card view I added a service button which toggles between the floors.

First I created my input select in configuration.yaml.

configuration.yaml

input_select : floorplan_floor : name : The select floor to show when viewing the floorplan. options : - " 1st Floor" - " 2nd Floor" initial : " 1st Floor" icon : mdi:floor-plan

Next I modified my floorplan lovelace view to be a horizontal stack with conditional cards. Each card is for each floor in the house. Based on the value of the input select floorplan_floor one of the 2 cards will be displayed.

lovelace/floorplan.yaml

title : Floorplan path : floorplan panel : true icon : mdi:floor-plan cards : - type : horizontal-stack cards : - type : conditional conditions : - entity : input_select.floorplan_floor state : " 1st Floor" card : !include _floorplan_first_floor.yaml - type : conditional conditions : - entity : input_select.floorplan_floor state : " 2nd Floor" card : !include _floorplan_second_floor.yaml

Finally on each of the floor picture-elements cards I added a service button in addition to my lighting overlays and toggles. Since I only have 2 floors I simply used the input_select.select_next service call to toggle between the floors when the button is clicked.

lovelace/_floorplan_first_floor.yaml

type : picture-elements image : /local/floorplan/first_floor_lights_on.png elements : # Lighting Overlays... # Light Toggles... # Floor Toggle - type : service-button title : 2nd Floor service : input_select.select_next service_data : entity_id : input_select.floorplan_floor style : top : 15% left : 5% background : " #eaeaea" border-radius : 5%

You can see the floor toggle in action in this demo.

Miscellaneous Sensors

I decided to show some miscellaneous sensors using state-icon ’s. I have multiple motion sensors and cameras so I wanted to display them on the floorplan as well. A quick example of each can be seen below. Each of the items is an element in the picture-elements card for the floor.

# Sensors - type : state-icon entity : binary_sensor.mud_room_motion_sensor icon : ' mdi:run' style : top : 84% left : 34% --iron-icon-stroke-color : " #969696" border-radius : 50% text-align : center background-color : " rgba(255, 255, 255, 0.3)" - type : state-icon entity : binary_sensor.back_door_camera_armed title : " Tap: Toggle Armed Status" tap_action : action : call-service service : script.camera_toggle_motion_detection service_data : entity_id : camera.back_door state_check_entity_id : binary_sensor.camera_back_door_camera_armed style : top : 70% left : 27% --iron-icon-stroke-color : " #969696" --paper-item-icon-active-color : " #ff0000" transform : scaleX(-1) border-radius : 50% text-align : center background-color : " rgba(255, 255, 255, 0.3)"

Both use state-icon types. For styling I used a semi-transparent circle which you can see in the screenshot below. By default clicking on any of the icons will bring up a dialog box showing the state history for the entity that was clicked on.

For the cameras I added a tap_action that calls a script which will arm/disarm the camera. If you hold-click on one of the camera sensors it will bring up the state history.

To display temperature readings reported by the various motion sensors I settled on using state-label’s. These will also by default show the state history of the temperature in a graph when they are clicked.

# Temperature Labels - type : state-label entity : sensor.kitchen_sensor_temperature style : top : 68% left : 35% color : " #000" border-radius : 50% text-align : center background-color : " rgba(255, 255, 255, 0.3)" font-size : 11px font-weight : bold

TV Toggle

One of the other cool things about my floorplan is the ability to see at a glance if the TV is on or off. Additionally clicking on the TV will toggle it on/off. You can see below on the left what the TV looks like when it is off versus the right when it is on.

This is accomplished similar to the lights where there is an overlay image that is the same size as the base image and then a separate element for toggling the TV.

- type : image entity : switch.tv_power tap_action : none hold_action : none state_image : " on" : /local/floorplan/first_floor_tv_on.png " off" : /local/floorplan/transparent_square.png style : top : 50% left : 50% width : 100% # TV Toggle - type : image entity : switch.tv_power tap_action : action : toggle image : /local/floorplan/transparent_square.png style : top : 35.2% left : 49.1% width : 3% height : 3%

The on image for the TV state is simply a semi-transparent white rectangle that is slightly larger than the TV and has a gaussian blur. I also manually adjusted the width and height of the tv toggle so that it’s a rectangle that more or less encompases the TV in the floorplan.

To create the actual switch I used a command_line platform switch. I have a raspberry pi connected to my TV that has the cec-client installed. I run a command over SSH to get the status of the TV. You can see the switch below (with the IP address obfuscated).

configuration.yaml

switch : - platform : command_line switches : tv_power : command_on : " ssh -o ConnectTimeout=2 root@19x.xxx.x.xxx -i /config/my.key -o StrictHostKeyChecking=no 'echo on 0 | cec-client -s -d 1'" command_off : " ssh -o ConnectTimeout=2 root@19x.xxx.x.xxx -i /config/my.key -o StrictHostKeyChecking=no 'echo standby 0 | cec-client -s -d 1'" command_state : " tvstatus() { local RESULTS; RESULTS=$(ssh -o ConnectTimeout=2 root@19x.xxx.x.xxx -i /config/my.key -o StrictHostKeyChecking=no \" echo pow 0 | cec-client -s -d 1 | grep -q 'power status: on' \" ); echo $?; }; tvstatus" value_template : ' {{ value == "0" }}' friendly_name : Downstairs TV

Wrap Up

It took me quite some time to figure out how to do all of the cool things I’ve documented above. I hope this helps out others who want to add a 3D floorplan to their home assistant installation.