In case you are coming from koreader/contrib, make sure that you check out the latest commit.
Jump to the [Installation], [Configuration] or [Examples] section
homeassistant.koplugin: a template query [left] & ButtonDialog gesture [right]
Features
- Control any number of Home Assistant entities from KOReader
- Action support with custom data attributes e.g.:
- light.turn_on with
brightnessandcolor - media_player.play_media with
media_content_id&type
- light.turn_on with
- Advanced targeting: single/multiple entities, areas or labels
- Entity state queries with customizable attributes e.g.:
- sensor.temperature_outside:
state,last_updated
- sensor.temperature_outside:
- Evaluate Home Assistant templates
- Simple text-based configuration
Installation
Step 1: Download the Plugin
Download the latest release and unpack homeassistant.koplugin.zip
Step 2: Copy the Plugin to Your Device
Copy the entire homeassistant.koplugin folder into koreader/plugins/.
Step 3: Restart KOReader
On first start, the plugin creates your configuration file in koreader/settings/homeassistant_config.lua.
π koreader/settings/
βββ homeassistant_config.lua
βββ ... (other files)
Step 4: Edit Your Config
Connect your device to your computer and edit koreader/settings/homeassistant_config.lua.
The example entries are placeholders and won't work until you add your host, port and token, and edit the entities to match your own setup. When you're done, set show_setup_hint = false.
See the Configuration section for details.
Step 5: Restart KOReader Again
Restart KOReader so the new config is loaded. The plugin is now available under Tools β Page X β Home Assistant or can be called from KOReader gestures.
Configuration
All configuration lives in koreader/settings/homeassistant_config.lua.
It consists of connection settings and a list of entries (Home Assistant entities).
Warning
Be careful with {} and , otherwise you will get syntax errors.
Connection Settings
First, add your Home Assistant connection details.
Change host, port, https and token according to your personal setup:
return { show_setup_hint = true, host = "192.168.1.10", port = 8123, https = false, token = "PasteYourHomeAssistantLong-LivedAccessTokenHere", entities = { -- your entities go here (see below) }, }
Tip
How to create a Long-Lived Access Token:
Home Assistant: Profile β Security (scroll down) β Long-lived access tokens β Create token
Copy the token now β you wonβt be able to view it again.
Adding Home Assistant entities
Inside the entities table in homeassistant_config.lua, you can define three types of items:
| Type | Purpose | Required Fields | Optional |
|---|---|---|---|
| action | Control an entity (e.g., turn on light) | label, action, target |
data |
| state query | Read a state (e.g., check temperature) | label, target, attributes |
|
| template | Evaluate a template | label, template |
Think of each entry as a single Home Assistant action or state query that becomes a button or gesture in KOReader.
Controlling Entities | 'action'
Let's start with a simple example: "turn on a light".
The entry in homeassistant_config.lua would look like this:
{
label = "Reading Lamp: turn_on",
action = "light.turn_on",
target = "light.reading_lamp",
},You are not limited to light.turn_on - any Home Assistant action works, for example:
scene.turn_on, automation.trigger, input_button.press, fan.toggle, switch.turn_off etc...
Adding Data to Actions | 'data = {...}'
You can add additional data to your action. In this example we add the data attributes brightness and rgb_color to action light.turn_on through data:
{
label = "Reading Lamp: turn blue",
action = "light.turn_on",
target = "light.reading_lamp",
data = {
brightness = 90,
rgb_color = { 0, 0, 255 },
},
},The syntax in homeassistant_config.lua is loosely based on the YAML action syntax in Home Assistant.
Finding Available Action Attributes:
To discover what additional data you can send with an action:
-
Go to your Home Assistant instance β Developer Tools β Actions
Play around with an action call, then click on "Go to YAML mode" -
Check the official Home Assistant integration documentation, examples:
Light, Fan, Media player or Climate
Tip
Take a look at the example section to see what's possible with homeassistant.koplugin.
Targeting Entities, Areas or Labels
You may target multiple entities, areas, or labels β but do not mix target types.
| Target Scope | Example homeassistant_config.lua Syntax |
|---|---|
| Single Entity | target = "light.reading_lamp", |
| Multiple Entities | target = {"light.lamp_1", "light.lamp_2"}, |
| Area | target = { area_id = "living_room" }, |
| Label | target = { label_id = {"nook", "desk"} }, |
| Special Case | target = "all", |
| Unsupported | target = { entity_id = "lamp", area_id = "room" } |
You can either use one single line or indentation:
{
label = "Reading Lamp: turn_on",
action = "light.turn_on",
target = {
area_id = {
"living_room",
"bed_room",
},
},
},Get Entity States | 'state query'
To retrieve an entity's state and/or attributes, omit the action field.
attributes defines which state attributes will be displayed in the result pop-up.
{
label = "\u{E350} Temperature Living Room",
target = "sensor.living_room_temperature",
attributes = { "state", "last_updated" },
},Finding Available States & Attributes:
Go to Home Assistant instance β Developer Tools β States.
Select an entity and check the State and Attributes sections.
Note
State Query Limitations:
- Queries require a single
entity_id - Area and label targeting is not supported
- Deeply nested JSON attributes may not display cleanly
Evaluating Templates | 'template'
You can evaluate Home Assistant templates with homeassistant.koplugin.
Templating can display complex & dynamic information.
Use templates to create conditional messages that go far beyond simple state queries.
{
label = "Time, Sun & Lights",
template = [[
{{ now().strftime('%Y-%m-%d %H:%M:%S') }}
Sun: {{ "sun.sun" | state_translated }}
Lights left on: {{ states.light | selectattr('state', 'eq', 'on') | list | count }}
]]
},Be aware of the template = [[ ]] syntax.
How to create and test your templates:
Go to your Home Assistant instance β Developer Tools β Template
Use the template editor to test your code before pasting it into the template = [[...]] section of your config.
Examples
Actions
Turn off all switches:
{
label = "All Switches: turn_off",
target = "all",
action = "switch.turn_off",
},Play music through Spotify on your Sonos speaker:
{
label = "Play Music",
action = "media_player.play_media",
target = "media_player.sonos",
data = {
media_content_id = "https://open.spotify.com/album/abcdefghij0123456789YZ",
media_content_type = "music",
},
},Set standing desk height:
{
label = "Set Desk Height to 80cm",
target = "number.upsy_desky_target_desk_height",
action = "number.set_value",
data = {
value = 80.0
},
},Quit Kodi on a specific device:
{
label = "Quit Kodi",
target = "media_player.mac_mini",
action = "kodi.call_method",
data = {
method = "Application.Quit"
},
},Example YAML to homeassistant_config.lua syntax with ALL the data:
Details
In theory you can take the whole data part (!) from a Home Assistant YAML action and "convert" it into the Lua syntax required in homeassistant_config.lua:
{
label = "Play Nobody 2",
action = "media_player.play_media",
target = "media_player.firefox",
data = {
media = {
media_content_id = "b594b3cf9c9a6778d0422b542ff654b8",
media_content_type = "movie",
metadata = {
title = "Nobody 2",
thumbnail = "http://192.168.10.12:8096//Items/b594b3cf9c9a6778d0422b542ff654b8/Images/Primary?MaxWidth=600&format=jpg&api_key=1f14dc0c0e5f4c9597156f186508316e",
media_class = "movie",
children_media_class = nil,
navigateIds = {
{},
{
media_content_type = "collection",
media_content_id = "f137a2dd21bbc1b99aa5c0f6bf02a805",
},
},
browse_entity_id = "media_player.firefox",
},
},
},
},[!Note]
This example is intentionally verbose and included for completeness. Most users will never need this level of detail.
Templates
Get information about the currently playing song (as template):
{
label = "Currently Playing",
template = [[
{% set player = 'media_player.firefox' %}
{% set duration = state_attr(player, 'media_duration') | int(0) %}
Song: {{ state_attr(player, 'media_title') or '-' }}
Artist: {{ state_attr(player, 'media_artist') or '-' }}
Album: {{ state_attr(player, 'media_album_name') or '-' }}
Length: {{
(duration // 60) ~ ':' ~ '%02d'|format(duration % 60)
if duration > 0
else '-'
}}
]]
},State Queries
Check if the light in the shed was left on:
{
label = "\u{EA2B} Shed Light on?",
target = "light.shed_ceiling_light",
attributes = { "state", "brightness", "last_changed" },
},KOReader Gestures
You can trigger your Home Assistant entities directly through KOReader gestures.
Each gesture can be assigned to any entity you have configured in homeassistant_config.lua.
For any chosen gesture, you will find your entities in:
GeneralβΈ β Page 1βX: [find your Home Assistant entity]
The actions are named after the label of each entity.
A complete gesture example:
Settings β Taps and gestures β Gesture managerβΈ
Long-press on cornerβΈ β Bottom Left β GeneralβΈ β Page 1βX: Reading Lamp β turn_on
If you want several entities behind a single gesture, you can build a list manually with a Quick Menu.
ButtonDialog
The simplest way to access all your Home Assistant entities is the built-in gesture action β° Home Assistant: all entities.
It opens a ButtonDialog that lists every entity from your configuration file. Tap an entity to run it.
Unlike a manual Quick Menu, it updates itself: changes to homeassistant_config.lua appear after the next KOReader restart.
Result (triggered via Long-press on corner: Bottom Right):
Requirements
- KOReader (tested with: 2026.07.1 on a Kindle Basic 2024)
- Home Assistant & a Long-Lived Access Token
Screenshots
Resources
Home Assistant: REST API
Home Assistant: Performing actions
Home Assistant: State and state object









