{"id":51437016,"url":"https://github.com/oleost/ventreg","last_synced_at":"2026-07-05T08:00:28.788Z","repository":{"id":367565217,"uuid":"1281220541","full_name":"oleost/VentReg","owner":"oleost","description":"Home Assistant: kurvestyring av tilluftstemperatur (Flexit) basert på utetemperatur","archived":false,"fork":false,"pushed_at":"2026-06-26T14:53:55.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-26T15:13:04.562Z","etag":null,"topics":["flexit","hacs","heating-curve","home-assistant","homeassistant-integration","ventilation"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/oleost.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":"2026-06-26T10:38:03.000Z","updated_at":"2026-06-26T14:53:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/oleost/VentReg","commit_stats":null,"previous_names":["oleost/ventreg"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/oleost/VentReg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleost%2FVentReg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleost%2FVentReg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleost%2FVentReg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleost%2FVentReg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oleost","download_url":"https://codeload.github.com/oleost/VentReg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oleost%2FVentReg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35147199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["flexit","hacs","heating-curve","home-assistant","homeassistant-integration","ventilation"],"created_at":"2026-07-05T08:00:22.372Z","updated_at":"2026-07-05T08:00:28.771Z","avatar_url":"https://github.com/oleost.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VentiReg\n\n[![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg)](https://github.com/hacs/integration)\n[![GitHub release](https://img.shields.io/github/v/release/oleost/VentReg?include_prereleases\u0026sort=semver)](https://github.com/oleost/VentReg/releases)\n[![License](https://img.shields.io/github/license/oleost/VentReg)](LICENSE)\n\nHome Assistant custom integration for **curve control of supply air temperature** on ventilation\nunits (primarily Flexit), based on outdoor temperature — the way a heating curve / weather\ncompensation works.\n\nCold outside → warmer supply air, warm outside → cooler supply air, with a linear transition\nbetween configurable breakpoints.\n\n```\nSupply air\n 22°C │●─────╮\n      │       ╲\n 10°C │        ╰──────●\n      └──┬────────────┬────► Outdoor temperature\n        5°C          20°C\n```\n\n## Contents\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Setup](#setup)\n- [Entities](#entities)\n- [Graphical curve card](#graphical-curve-card)\n- [The `ventireg.set_curve` service](#the-ventiregset_curve-service)\n- [How the regulation works](#how-the-regulation-works)\n- [Troubleshooting](#troubleshooting)\n- [Limitations](#limitations)\n- [License](#license)\n\n## Features\n\n- **Multi-point curve** (at least 2 points), linear interpolation, flat (clamp) outside the end points.\n- **Everything configurable in the UI** — outdoor sensor, climate entity, curve points, interval, tolerance, rounding step.\n- **Graphical card** with drag-the-points editing (auto-registered, no build step).\n- **Auto-pause:** if anything other than VentiReg changes the setpoint, regulation stops automatically\n  (a manual change is never overwritten).\n- **Notification:** persistent notification in Home Assistant 24 hours after auto-pause occurred.\n- **Switch** for on/off, status sensor (`On` / `Off` / `Auto paused`) and a sensor for the calculated setpoint.\n- Rounds the setpoint to 0.5 °C (Flexit step).\n\n## Requirements\n\n- Home Assistant with [HACS](https://hacs.xyz/) installed.\n- A **climate entity** (`climate.*`) where the **target temperature controls the supply air** —\n  typically from [Flexit Nordic (BACnet)](https://www.home-assistant.io/integrations/flexit_bacnet/)\n  or a Modbus/ESPHome solution. Verify that `climate.set_temperature` actually moves the supply\n  air setpoint on your unit (see [Troubleshooting](#troubleshooting)).\n- An **outdoor temperature sensor** (`sensor.*`) with a numeric value in °C.\n\n## Installation\n\n### Via HACS (recommended)\n\n1. HACS → **Integrations** → three dots in the top right → **Custom repositories**.\n2. Paste `https://github.com/oleost/VentReg`, choose category **Integration**, and add it.\n3. Search for **VentiReg** in HACS and install it.\n4. **Restart Home Assistant.**\n5. **Settings → Devices \u0026 services → Add integration → VentiReg.**\n\n### Updating\n\nHACS → VentiReg → **Update** → restart HA. Do a hard refresh in the browser\n(Ctrl/Cmd+Shift+R) so the new card is loaded.\n\n### Manual installation\n\nCopy `custom_components/ventireg/` to `config/custom_components/` in HA, and restart.\n\n## Setup\n\nWhen you \"Add integration\" (and later via **Configure**) you set:\n\n| Field | Description | Default |\n|---|---|---|\n| Outdoor temperature sensor | `sensor.*` measuring outdoors | – |\n| Ventilation (climate) | `climate.*` where target = supply air temperature | – |\n| Curve points | `outdoor:supply`, separated by comma/newline, e.g. `5:22, 20:10` | `-5:23, 5:20, 10:18, 20:10` |\n| Update interval | Minutes between each computation | 15 |\n| Tolerance | °C deviation regarded as an external change | 0.5 |\n| Rounding step | Step the setpoint is rounded to | 0.5 |\n\n**Curve points format:** each point is `outdoor_temperature:supply_air_temperature`. Decimals use\na period. Points are separated by comma, semicolon or newline. Examples:\n\n```\n-5:23, 5:20, 10:18, 20:10         # four points (default)\n5:22, 20:10                       # simplest, two points\n-20:23, -10:23, 0:22, 10:21, 20:15, 25:15   # multi-point\n```\n\nSettings can be changed at any time via **Configure** on the integration — without reinstalling\nanything.\n\n## Entities\n\nThe integration creates one device with the following entities (the actual `entity_id` may vary\nwith the HA language — check under Devices \u0026 services):\n\n| Entity (typical id) | Type | Description |\n|---|---|---|\n| `switch.ventireg_regulation` | switch | On = active regulation. Off = stopped (manually **or** auto-paused). |\n| `sensor.ventireg_status` | sensor (enum) | `On` / `Off` / `Auto paused`. |\n| `sensor.ventireg_calculated_setpoint`¹ | sensor (°C) | The setpoint the curve gives right now. Has the attributes `curve_points`, `outdoor_temp` and `status` (used by the card). |\n\n¹ The entity id follows your **HA language**. In English it is\n`sensor.ventireg_calculated_setpoint`, in Norwegian `sensor.ventireg_beregnet_settpunkt`.\n**Check the actual id** under Settings → Devices \u0026 services → VentiReg, and use it in the\ncard/service configuration below.\n\n## Graphical curve card\n\nThe integration **registers the card automatically** as a Lovelace resource (the way HACS does) —\nyou do *not* need to add a dashboard resource manually. It happens right after Home Assistant has\nstarted. (Requires an HA restart the first time; if you use YAML dashboards, see\n[Troubleshooting](#troubleshooting).)\n\n### Add the card to a dashboard\n\nEdit the dashboard → **+ Add card** → search **VentiReg Curve**, or use YAML:\n\n```yaml\ntype: custom:ventireg-card\nentity: sensor.ventireg_calculated_setpoint   # use your actual entity id (see note ¹)\ntitle: Outdoor compensation curve\n```\n\n### Card options\n\n| Field | Required | Description |\n|---|---|---|\n| `type` | yes | Must be `custom:ventireg-card`. |\n| `entity` | yes | The calculated-setpoint sensor (the one with the `curve_points` attribute). |\n| `title` | no | Card heading. Default \"Outdoor compensation curve\". |\n| `min_outdoor` | no | Fixed left edge of the X axis (°C). Default about -25. |\n| `max_outdoor` | no | Fixed right edge of the X axis (°C). Default about 30. |\n| `x_step` | no | Outdoor-temperature snapping while dragging (degrees). Default 1. |\n\n### Usage\n\n- **Drag each point freely** — left/right changes outdoor temperature, up/down changes supply air.\n- A point cannot cross its neighbours (the curve stays in increasing order). Y snaps to\n  0.5 °C, X to `x_step` (default 1°). While dragging, the point's `outdoor° / supply°` is shown.\n- The change is saved **when you release**, via `ventireg.set_curve`.\n- The **dashed line** shows the current outdoor temperature, and the **dot** shows the current\n  setpoint (\"ACT SP\").\n\nThe card is just a nicer way to edit the curve — it can **also** be changed via **Configure**\n(text field) or the service below. All three paths write to the same setting.\n\n## The `ventireg.set_curve` service\n\nOverwrite the curve points from an automation, a script or Developer Tools.\n\n| Parameter | Required | Description |\n|---|---|---|\n| `entity_id` | no | Any VentiReg entity of the instance. Can be omitted if you only have one instance. |\n| `curve` | yes | String (`\"5:22, 20:10\"`) **or** a list of `[outdoor, supply]` pairs. |\n\n```yaml\nservice: ventireg.set_curve\ndata:\n  entity_id: sensor.ventireg_calculated_setpoint   # your actual entity id\n  curve: \"0:23, 10:18, 20:10\"\n```\n\n## How the regulation works\n\nEvery 15 minutes (configurable), and only when the switch is **on**:\n\n1. Read the outdoor temperature and compute the supply air from the curve (linear interpolation,\n   clamped outside the end points).\n2. Round to 0.5 °C.\n3. **Check first:** does the climate setpoint deviate from what VentiReg last set (≥ tolerance)?\n   - **Yes** → someone else changed it → **auto-pause** (switch off, status \"Auto paused\"),\n     write nothing. After 24 h paused, a persistent notification is sent.\n   - **No** → write the curve value to the climate entity and remember it.\n\n**Resume:** turn the switch back on. VentiReg then resets the reference and writes the curve\nvalue **immediately** (doesn't wait 15 min), so it doesn't pause itself again.\n\n\u003e Manual **off** (you turn the switch off yourself) produces no notification — the notification\n\u003e only applies to auto-pause.\n\n## Troubleshooting\n\n**The card doesn't show up / \"Custom element doesn't exist: ventireg-card\".**\nRestart HA after installing/updating. The card is registered as a Lovelace resource right after\nstartup; check **Settings → Dashboards → Resources** — `/ventireg/ventireg-card.js` should be\nlisted. Then do a hard refresh (Ctrl/Cmd+Shift+R). If you use a **YAML dashboard** (`mode: yaml`),\nresources are managed in YAML — add the resource yourself:\n\n```yaml\n# in the dashboard configuration (or lovelace: resources:)\nresources:\n  - url: /ventireg/ventireg-card.js\n    type: module\n```\n\n**The setpoint on the unit doesn't move.**\nConfirm that `climate.set_temperature` on your Flexit actually controls the *supply air*. Test in\nDeveloper Tools → Services: call `climate.set_temperature` on the entity and see if the supply air\nchanges. If your unit controls supply air via a `number.*` entity instead,\n[open an issue](https://github.com/oleost/VentReg/issues).\n\n**It goes to \"Auto paused\" unexpectedly.**\nThen something else (an app, another automation, a manual change on the panel) changed the\nsetpoint by ≥ tolerance. Increase the tolerance if needed, or turn the switch back on to resume.\n\n**Nothing happens / status doesn't change.**\nCheck that the outdoor sensor has a valid numeric value (not `unavailable`/`unknown`), and that\nthe switch is on. Look for \"VentiReg\" messages in the log.\n\n## Limitations\n\n- `_last_set` (the reference for pause detection) is kept in memory and saved to disk, but an\n  external change made *while HA was down* is not detected until the next normal cycle.\n- The card lets you drag the points **freely** (outdoor + supply), but cannot **add/remove**\n  points in the graph yet — use the text field under Configure to change the number of points.\n- The interpolation is linear and clamps outside the end points (no extrapolation).\n\nSee [CLAUDE.md](CLAUDE.md) for architecture and design choices.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleost%2Fventreg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foleost%2Fventreg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foleost%2Fventreg/lists"}