{"id":36941181,"url":"https://github.com/moritz-john/homeassistant.koplugin","last_synced_at":"2026-01-24T18:09:14.039Z","repository":{"id":326933116,"uuid":"1106555401","full_name":"moritz-john/homeassistant.koplugin","owner":"moritz-john","description":"This KOReader plugin lets you control Home Assistant entities without leaving your current book!","archived":false,"fork":false,"pushed_at":"2026-01-11T07:42:00.000Z","size":4326,"stargazers_count":15,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-14T00:10:51.443Z","etag":null,"topics":["home-assistant","koreader","koreader-plugin"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moritz-john.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-29T13:41:33.000Z","updated_at":"2026-01-11T07:36:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/moritz-john/homeassistant.koplugin","commit_stats":null,"previous_names":["moritz-john/homeassistant.koplugin"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/moritz-john/homeassistant.koplugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moritz-john%2Fhomeassistant.koplugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moritz-john%2Fhomeassistant.koplugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moritz-john%2Fhomeassistant.koplugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moritz-john%2Fhomeassistant.koplugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moritz-john","download_url":"https://codeload.github.com/moritz-john/homeassistant.koplugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moritz-john%2Fhomeassistant.koplugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28733536,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T17:51:25.893Z","status":"ssl_error","status_checked_at":"2026-01-24T17:50:48.377Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["home-assistant","koreader","koreader-plugin"],"created_at":"2026-01-13T10:48:44.426Z","updated_at":"2026-01-24T18:09:14.029Z","avatar_url":"https://github.com/moritz-john.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# homeassistant.koplugin\n\n\u003e In case you are coming from [koreader/contrib](https://github.com/koreader/contrib), make sure that you checkout [the latest commit](https://github.com/moritz-john/homeassistant.koplugin).\n\n\u003cp align=\"center\"\u003e\n  Jump to the \u003ca href=\"#installation\"\u003e[Installation]\u003c/a\u003e, \u003ca href=\"#configuration\"\u003e[Configuration]\u003c/a\u003e or \u003ca href=\"#examples\"\u003e[Examples]\u003c/a\u003e section\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/homeassistant_koplugin_screenshots.png\"  alt=\"homeassistant.koplugin screenshots\" /\u003e\n  \u003ci\u003ehomeassistant.koplugin: a template query [left] \u0026 QuickMenu gesture [right]\u003c/i\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/ha_koreader_sensor.png\" /\u003e\n  \u003ci\u003eKOReader status sensor in Home Assistant\u003c/i\u003e\n\u003c/p\u003e\n\n## Features\n\n- Control any number of Home Assistant entities from KOReader \n- Action support with custom data attributes e.g.:  \n  - **light.turn_on** with `brightness` and `color` \n  - **media_player.play_media** with `media_content_id` \u0026 `type`\n- Actions with response data (**todo.get_items** or **weather.get_forecasts**)\n- Evaluate Home Assistant templates\n- Advanced targeting: single/multiple entities, areas or labels\n- Entity state queries with customizable attributes e.g.:\n  - **sensor.temperature_outside**: `state`, `unit_of_measurement`\n- Lightweight, unobtrusive interface  \n- Simple text-based configuration  \n- Success/error notifications\n\n## Installation\n\n### Step 1: Download the Plugin\n[Download the latest release](https://github.com/moritz-john/homeassistant.koplugin/releases) and unpack `homeassistant.koplugin.zip`:  \n\n### Step 2: Edit `config.lua`\n\nFollow the [Configuration](#configuration) section.\n\nTip: 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.\n\n\u003e [!warning]\n\u003e Be aware of proper indentation, `{}` and `,` otherwise you will get syntax errors\n\n### Step 3: Copy Files to Your Device\n\nAfter editing `config.lua`, copy the files to your KOReader device:\n\n**Copy the entire `homeassistant.koplugin` folder into `koreader/plugins/`**  \n\n### Step 4: Restart KOReader\n\nThe plugin appears under **Tools → Page 2 → Home Assistant** or can be called from KOReader [gestures](#koreader-gestures).\n\n## Configuration\n\nAll configuration lives in `config.lua`.  \nIt consists of **connection settings** and a list of **entries** (Home Assistant entities).\n\n### Connection Settings\n\nFirst, add your Home Assistant connection details.  \nChange `host`, `port`, `https` and `token` according to your personal setup:\n\n```lua\nreturn {\n    host = \"192.168.1.10\",\n    port = 8123,\n    https = false,\n    token =\n    \"PasteYourHomeAssistantLong-LivedAccessTokenHere\",\n```\n\n\u003e [!tip]\n\u003e **How to create a Long-Lived Access Token:**  \n\u003e [**Home Assistant**](https://my.home-assistant.io/redirect/profile): *Profile → Security (scroll down) → Long-lived access tokens → Create token*  \n\u003e *Copy the token now – you won’t be able to view it again.*\n\n---\n\n### Adding Home Assistant entities\n\nInside the `entities` table in `config.lua`, you can define three types of items:\n\n| Type            | Purpose                                 | Required Fields                 | Optional                |\n| :-------------- | :-------------------------------------- | :------------------------------ | :---------------------- |\n| **action**      | Control an entity (e.g., turn on light) | `label`, `action`, `target`     | `data`, `response_data` |\n| **state query** | Read a state (e.g., check temperature)  | `label`, `target`, `attributes` |                         |\n| **template**    | Evaluate a template                     | `label`, `template`             |                         |\n\n_Think of each entry as a single Home Assistant action or state query that becomes a button or gesture in KOReader._\n\n### Controlling Entities | 'action'\n\nLet's start with a simple example: \"turn on a light\".  \nThe entry in `config.lua` would look like this:\n\n```lua\n{   \n    label = \"Reading Lamp: turn_on\",\n    action = \"light.turn_on\",\n    target = \"light.reading_lamp\",\n},\n```\n\nOf course you are not just limited to `light.turn_on` - any other action works:  \n`scene.turn_on`, `automation.trigger`, `input_button.press`, `fan.toggle`, `switch.turn_off` etc...\n\n### Adding Data to Actions | 'data = {...}'\n\nYou can add additional data to your action. In this example we add the data attributes `brightness` and `rgb_color` to [action **light.turn_on**](https://www.home-assistant.io/integrations/light/#action-lightturn_on) through `data`:\n\n```lua\n{\n    label = \"Reading Lamp: turn blue\",\n    action = \"light.turn_on\",\n    target = \"light.reading_lamp\",\n    data = {\n        brightness = 90,\n        rgb_color = { 0, 0, 255 },\n    },\n},\n```\n_The syntax in `config.lua` is loosely based on the YAML action syntax in Home Assistant._\n\n**Finding Available Action Attributes:**\n\nTo discover what additional data you can send with an action:\n\n- Go to your **Home Assistant instance → Developer Tools → Actions**  \n  Play around with an action call, then click on \"Go to YAML mode\"\n\n- Check the official Home Assistant integration documentation, examples:    \n  [Light](https://www.home-assistant.io/integrations/light/), [Fan](https://www.home-assistant.io/integrations/fan/), [Media player](https://www.home-assistant.io/integrations/media_player/) or [Climate](https://www.home-assistant.io/integrations/climate/)\n\n\u003e [!TIP]\n\u003e Take a look at the [example section](#examples) to see what's possible with `homeassistant.koplugin`.\n\n### Targeting Entities, Areas or Labels\n\nYou may target multiple entities, areas, or labels – but do not mix them.\n\n| Target Scope          | Example `config.lua` Syntax                         |\n| :-------------------- | :-------------------------------------------------- |\n| **Single Entity**     | `target = \"light.reading_lamp\",`                    |\n| **Multiple Entities** | `target = {\"light.lamp_1\", \"light.lamp_2\"},`        |\n| **Area**              | `target = { area_id = \"living_room\" },`             |\n| **Label**             | `target = { label_id = {\"nook\", \"desk\"} },`         |\n| **Special Case**      | `target = \"all\",`                                   |\n| **Unsupported**       | `target = { entity_id = \"lamp\", area_id = \"room\" }` |\n\nYou can either use one single line or indentation:\n\n```lua\n{\n    label = \"Reading Lamp: turn_on\",\n    action = \"light.turn_on\",\n    target = {\n        area_id = {\n            \"living_room\",\n            \"bed_room\",\n        },\n    },\n},\n```\n\n### Actions with Response Data | 'response_data = true'\n\nSome Home Assistant actions can return response data.  \nThe plugin currently supports this for [`todo.get_items`](https://www.home-assistant.io/integrations/todo/#action-todoget_items) and [`weather.get_forecasts`](https://www.home-assistant.io/integrations/weather/#action-weatherget_forecasts).\n\nTo enable this, add the `response_data` field to your configuration.  \nThis feature works with a single target only (target = \" ... \").\n\n#### todo.get_items Example:\n\n```lua\n{\n    type = \"action_response\"\n    label = \"\\u{EE54} Shopping List\",\n    action = \"todo.get_items\",\n    response_data = true,\n    target = \"todo.shopping_list\",\n    -- data = {\n    --     status = \"needs_action\"\n    -- },\n},\n```\n\n\u003cimg src=\"assets/response_data.png\" style=\"width:50%; height:auto;\" /\u003e\n\n#### weather.get_forecasts Example:\n```lua\n{\n    label = \"\\u{E376} Weather Forecast\",\n    action = \"weather.get_forecasts\",\n    target = \"weather.berlin\",\n    response_data = true,\n    data = {\n        type = \"daily\" -- or \"hourly\"\n    },\n},\n```\n\n\u003cimg src=\"assets/weather_response_data.png\" style=\"width:50%; height:auto;\" /\u003e\n\n\u003cbr\u003e\n\n\u003e [!NOTE]\n\u003e This is an opinionated feature. It assumes most users are on Kindle or Kobo devices with limited screen space. \n\u003e For this reason, e.g.: task descriptions are intentionally not shown and weather forecast is limited to 3 items.\n\n### Get Entity States | 'state query'\n\nTo retrieve an entity's state and attributes, omit the `action` field.  \n`attributes` defines which state attributes will be displayed in the result pop-up.\n\n```lua\n{\n    label = \"Temperature Living Room\",\n    target = \"sensor.living_room_temperature\",\n    attributes = { \"state\", \"unit_of_measurement\", \"device_class\" },\n},\n```\n\n\u003cimg src=\"assets/temperature_example.png\" style=\"width:50%; height:auto;\" /\u003e\n\n**Finding Available States \u0026 Attributes:**\n\nGo to **Home Assistant instance → Developer Tools → States**.  \nSelect an entity and check the **State** and **Attributes** sections.\n\n\u003e [!NOTE]\n\u003e **State Query Limitations:**\n\u003e\n\u003e * Queries require a single `entity_id`\n\u003e * Area and label targeting is not supported\n\u003e * Deeply nested JSON attributes may not display cleanly\n\n### Evaluating Templates | 'template'\n\nYou can evaluate Home Assistant templates with `homeassistant.koplugin`.  \n[Templating](https://www.home-assistant.io/docs/configuration/templating/) can display complex \u0026 dynamic information.  \nUse them to create conditional messages, going far beyond what **state** offers.  \n\n```lua\n{   \n    label = \"Time, Sun \u0026 Lights\",\n    template = [[\n    {{ now().strftime('%Y-%m-%d %H:%M:%S') }}\n    Sun: {{ \"sun.sun\" | state_translated }}\n    Lights left on: {{ states.light | selectattr('state', 'eq', 'on') | list | count }}\n    ]]\n},\n```\nBe aware of the `template = [[ ]]` syntax.\n\n\u003cimg src=\"assets/time_sun_template.png\" style=\"width:50%; height:auto;\" /\u003e\n\n\u003cbr\u003e\n\n**How to create and test your templates:**\n  \nGo to your **Home Assistant instance → Developer Tools → Template**  \nUse the [template editor](https://my.home-assistant.io/redirect/developer_template/) to test your code before pasting it into the `template = [[...]]` section of your config.\n\n\u003cimg src=\"assets/template_editor.png\" style=\"width:100%; height:auto;\" /\u003e\n\n## KOReader Home Assistant status sensor\n\nThe plugin can send KOReader's current state (on/off) to a Home Assistant binary sensor. This sensor can be used to trigger automations based on your reading activity.  \nBy default, the sensor is created as `binary_sensor.koreader_status`. You can customize the sensor name in your `config.lua`.\n\n\u003cimg src=\"assets/ha_koreader_sensor.png\" style=\"width:60%; height:auto;\" /\u003e\n\nThe sensor includes the following attributes: `device_model`, `battery_level`, `is_charging` and `last_seen`.\n\nYou can enable or disable this feature under  **Tools → Home Assistant:** \n\n\u003cimg src=\"assets/heartbeat_toggle.png\" style=\"width:60%; height:auto;\" /\u003e\n\n\u003cbr\u003e\n\n\u003e [!NOTE]\n\u003e **Caveats:**  \n\u003e This feature assumes `homeassistant.koplugin` is configured correctly and that KOReader has Wi-Fi connectivity. State updates are sent only on start/resume/suspend and will fail silently if Home Assistant or Wi-Fi is unavailable. The resume state is sent with a 4-second delay.\n\n## Examples\n\n### Actions\n\n**Turn off all switches:**\n\n```lua\n{\n    label = \"All Switches: turn_off\",\n    target = \"all\",\n    action = \"switch.turn_off\",\n},\n```\n\n**Play music through Spotify on your Sonos speaker:**\n\n```lua\n{\n    label = \"Play Music\",\n    action = \"media_player.play_media\",\n    target = \"media_player.sonos\",\n    data = {\n        media_content_id = \"https://open.spotify.com/album/abcdefghij0123456789YZ\",\n        media_content_type = \"music\",\n    },\n},\n```\n\n**Set standing desk height:**\n\n```lua\n{\n    label = \"Set Desk Height to 80cm\",\n    target = \"number.upsy_desky_target_desk_height\",\n    action = \"number.set_value\",    \n    data = {\n        value = 80.0\n    },\n},\n```\n\n**Quit Kodi on a specific device:**\n\n```lua\n{\n    label = \"Quit Kodi\",\n    target = \"media_player.mac_mini\",\n    action = \"kodi.call_method\",\n    data = {\n        method = \"Application.Quit\"\n    },\n},\n```\n\n**Example YAML to `config.lua` syntax with ALL the data:**\n\n\u003cdetails\u003e\n\nIn 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`:\n\n\u003cimg src=\"assets/yaml_play_media.png\" style=\"width:80%; height:auto;\" /\u003e\n\n```lua\n{\n    label = \"Play Nobody 2\",\n    action = \"media_player.play_media\",\n    target = \"media_player.firefox\",\n    data = {\n        media = {\n            media_content_id = \"b594b3cf9c9a6778d0422b542ff654b8\",\n            media_content_type = \"movie\",\n            metadata = {\n                title = \"Nobody 2\",\n                thumbnail = \"http://192.168.10.12:8096//Items/b594b3cf9c9a6778d0422b542ff654b8/Images/Primary?MaxWidth=600\u0026format=jpg\u0026api_key=1f14dc0c0e5f4c9597156f186508316e\",\n                media_class = \"movie\",\n                children_media_class = nil,\n                navigateIds = {\n                    {},\n                    {\n                        media_content_type = \"collection\",\n                        media_content_id = \"f137a2dd21bbc1b99aa5c0f6bf02a805\",\n                    },\n                },\n                browse_entity_id = \"media_player.firefox\",\n            },\n        },\n    },\n},\n```\n\n\u003e [!Note]\n\u003e   \n\u003e This example is intentionally verbose and included for completeness. Most users will never need this level of detail.\n\n\u003c/details\u003e\n\n### Templates\n\n**Get information about the currently playing song (as template):**\n\n```lua\n{\n    label = \"Currently Playing\",\n    template = [[\n    {% set player = 'media_player.firefox' %}\n    {% set duration = state_attr(player, 'media_duration') | int(0) %}\n\n    Song: {{ state_attr(player, 'media_title') or '-' }}\n    Artist: {{ state_attr(player, 'media_artist') or '-' }}\n    Album: {{ state_attr(player, 'media_album_name') or '-' }}\n    Length: {{\n    (duration // 60) ~ ':' ~ '%02d'|format(duration % 60)\n    if duration \u003e 0\n    else '-'\n    }}\n    ]]\n},\n```\n\n\u003cimg src=\"assets/current_song_template.png\" style=\"width:50%; height:auto;\" /\u003e\n\n### State Queries\n\n**Get information about the currently playing song:**\n\n```lua\n{\n    label = \"What's playing?\",\n    target = \"media_player.jellyfin_firefox\",\n    attributes = { \"media_title\", \"media_artist\", \"media_duration\" },\n},\n```\n\n\u003cimg src=\"assets/what_is_playing.png\" style=\"width:50%; height:auto;\" /\u003e\n\n**Check if the light in the shed was left on:**\n\n```lua\n{\n    label = \"Shed Light on?\",\n    target = \"light.shed_ceiling_light\",\n    attributes = { \"state\", \"brightness\", \"last_changed\" },\n},\n```\n\n\u003cimg src=\"assets/light_left_on.png\" style=\"width:50%; height:auto;\" /\u003e\n\n## KOReader Gestures\n\nYou can trigger your Home Assistant entities directly through KOReader gestures.  \nEach gesture can be assigned to any entity you have configured in `config.lua`.\n\nFor any chosen gesture, you will find your entities in:  \n**General▸ → Pages 1–X [find your Home Assistant entity]**\n\nThe actions will be named after your entity `label`.\n\nA complete gesture example:  \n**Settings → Taps and gestures → Gesture manager▸**  \n**Long-press on corner▸ → Bottom Left → General▸ → Page 1–X: Toggle: Reading Lamp**\n\n### QuickMenu\n\nThe simplest way to access your Home Assistant entities is through a [QuickMenu](https://koreader.rocks/user_guide/#L2-quickmenu).\n\n1) Add as many entities as you want to a gesture (e.g. **Long-press on corner▸ → Bottom Left**)  \n2) Select **Show as QuickMenu** in **Long-press on corner▸ → Bottom Left → Page 2**.\n\nResult:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/homeassistant_koplugin_gesture_quick_menu.gif\" style=\"width:70%; height:auto;\" /\u003e\n\u003c/p\u003e\n\n## Requirements\n- KOReader (tested with: 2025.10 \"Ghost\" on a Kindle Basic 2024)  \n- Home Assistant \u0026 a Long-Lived Access Token\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/tools_menu_entry.png\" style=\"width:70%; height:auto;\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"assets/error_message.png\" style=\"width:70%; height:auto;\" /\u003e\n\u003c/p\u003e\n\n### Resources:  \n[KOReader Website](https://koreader.rocks/)\n\n[Home Assistant: REST API](https://developers.home-assistant.io/docs/api/rest/)  \n[Home Assistant: Performing actions](https://www.home-assistant.io/docs/scripts/perform-actions/)  \n[Home Assistant: State and state object ](https://www.home-assistant.io/docs/configuration/state_object/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoritz-john%2Fhomeassistant.koplugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoritz-john%2Fhomeassistant.koplugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoritz-john%2Fhomeassistant.koplugin/lists"}