In case you are coming from koreader/contrib, make sure that you checkout the latest commit.
Jump to the [Installation], [Configuration] or [Examples] section
homeassistant.koplugin: a template query [left] & QuickMenu gesture [right]
- 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
If you’re looking for a Home Assistant KOReader status sensor that shows your e-book reader’s state, including the title, author, and battery level, check out heartbeat.koplugin
Download the latest release and unpack homeassistant.koplugin.zip:
Follow the Configuration section.
Tip: You can install and configure the plugin in KOReader for macOS or Linux first. This makes it easier to fix configuration errors before copying the files to your e-reader.
Warning
Be aware of proper indentation, {} and , otherwise you will get syntax errors
After editing config.lua, copy the files to your KOReader device:
Copy the entire homeassistant.koplugin folder into koreader/plugins/
The plugin appears under Tools → Page 2 → Home Assistant or can be called from KOReader gestures.
All configuration lives in config.lua.
It consists of connection settings and a list of entries (Home Assistant entities).
First, add your Home Assistant connection details.
Change host, port, https and token according to your personal setup:
return {
host = "192.168.1.10",
port = 8123,
https = false,
token =
"PasteYourHomeAssistantLong-LivedAccessTokenHere",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.
Inside the entities table in 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.
Let's start with a simple example: "turn on a light".
The entry in 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...
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 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.
You may target multiple entities, areas, or labels – but do not mix target types.
| Target Scope | Example 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",
},
},
},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
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.
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 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 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.
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 '-'
}}
]]
},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" },
},You can trigger your Home Assistant entities directly through KOReader gestures.
Each gesture can be assigned to any entity you have configured in config.lua.
For any chosen gesture, you will find your entities in:
General▸ → Pages 1–X [find your Home Assistant entity]
The actions will be named after your entity label.
A complete gesture example:
Settings → Taps and gestures → Gesture manager▸
Long-press on corner▸ → Bottom Left → General▸ → Page 1–X: Toggle: Reading Lamp
The simplest way to access your Home Assistant entities is through a QuickMenu.
- Add as many entities as you want to a gesture (e.g. Long-press on corner▸ → Bottom Left)
- Select Show as QuickMenu in Long-press on corner▸ → Bottom Left → Page 2.
Result:
- KOReader (tested with: 2025.10 "Ghost" on a Kindle Basic 2024)
- Home Assistant & a Long-Lived Access Token
Home Assistant: REST API
Home Assistant: Performing actions
Home Assistant: State and state object







