{"id":34550257,"url":"https://github.com/nihilok/central-heating-api","last_synced_at":"2026-04-14T00:32:05.257Z","repository":{"id":137678184,"uuid":"554987184","full_name":"nihilok/central-heating-api","owner":"nihilok","description":"A simple but full-featured API to control a Central Heating system using microcontrollers running micro-python.","archived":false,"fork":false,"pushed_at":"2026-03-15T19:22:50.000Z","size":1555,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-15T21:55:43.575Z","etag":null,"topics":["fastapi","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nihilok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2022-10-20T18:50:10.000Z","updated_at":"2026-03-15T19:22:54.000Z","dependencies_parsed_at":"2023-12-23T12:35:00.772Z","dependency_job_id":"eb42bd81-ee5b-47fa-bf9f-b374d0985cd3","html_url":"https://github.com/nihilok/central-heating-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nihilok/central-heating-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nihilok%2Fcentral-heating-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nihilok%2Fcentral-heating-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nihilok%2Fcentral-heating-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nihilok%2Fcentral-heating-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nihilok","download_url":"https://codeload.github.com/nihilok/central-heating-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nihilok%2Fcentral-heating-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31776926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T00:11:49.126Z","status":"ssl_error","status_checked_at":"2026-04-14T00:10:29.837Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["fastapi","python"],"created_at":"2025-12-24T07:57:09.486Z","updated_at":"2026-04-14T00:32:05.245Z","avatar_url":"https://github.com/nihilok.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Open Central Heating API\n\n### Pre-requisites\n- Python 3.9+\n\n### Installation (main API)\n- create a new Python virtual environment using `requirements.txt` e.g.\n```sh\npython3 -m venv venv\npip install -r requirements.txt\n```\n- set a JWT secret key for authentication tokens (this invalidates previously issued tokens when rotated)\n```sh\nexport HEATING_API_SECRET_KEY=\"$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')\"\n```\n- set trusted CORS origins (comma-separated, no wildcard)\n```sh\nexport HEATING_API_CORS_ORIGINS=\"http://localhost:3000,http://127.0.0.1:3000\"\n```\n- set sensor ingest token used by sensor nodes posting to `/api/v3/receive/{sensor_id}/`\n```sh\nexport HEATING_API_SENSOR_INGEST_TOKEN=\"\u003cset-a-random-token\u003e\"\n```\n- create a new systemd unit file (change the appropriate paths making sure the ExecStart command is using the python executable from inside your virtual environment)\n```sh\necho \"[Unit]\nDescription=Open Central Heating API\n\n[Service]\nUser=\u003cyour user\u003e\nWorkingDirectory=home/\u003cyour user\u003e/project/directory\nEnvironment=HEATING_API_SECRET_KEY=\u003cset-a-strong-secret-here\u003e\nEnvironment=HEATING_API_CORS_ORIGINS=http://localhost:3000\nEnvironment=HEATING_API_SENSOR_INGEST_TOKEN=\u003cset-a-random-token\u003e\nExecStart=/home/\u003cyour user\u003e/venv/bin/python main.py\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n\" \u003e\u003e central-heating.service \u0026\u0026 sudo mv central-heating.service /etc/systemd/system/\n```\n- reload the systemctl daemon \u0026 enable/start the new service\n```sh\nsudo systemctl daemon-reload\nsudo systemctl enable central-heating\nsudo systemctl start central-heating\n```\n\n### Sync bundled frontend\n\nTo rebuild the `heating-ui` submodule and replace the minified assets served by the API:\n\n```sh\n./scripts/sync-front-end.sh\n```\n\nThis script fails fast if the `heating-ui` submodule is unavailable/uninitialized. If needed:\n\n```sh\ngit submodule update --init --recursive heating-ui\n```\n\n### Installation (micropython devices)\n\nThere are two different micropython controllers in the current setup. A \"relay\" controller and a \"sensor\" controller. The code for these is stored in `./relay_node` and `./sensor_node` respectively and must be flashed to a suitable micropython wifi device. I've used a total of 3 NodeMCU ESP8266 controllers: 2 sensor nodes and 1 relay node.\n\nAfter adjusting the network settings (SSID \u0026 WPA key), all of the python modules in each directory must be flashed to the relevant microcontroller. I recommend using the Thonny IDE to connect to your micropython devices.\n\nFor `sensor_node_transmitter`, set `SENSOR_INGEST_TOKEN` in `sensor_node_lib/constants.py` to the same value configured in `HEATING_API_SENSOR_INGEST_TOKEN` on the API.\n\n### Configuration\n\nIn `data.models` you can see a comment detailing an example configuration. Essentially each heating system needs an URL to read the temperature, and URLS to switch on/off and get the status of the relay respectively.\n\n`data/persistence.json`\n```json\n{\n  \"systems\": [\n    {\n      \"relay\": {\n        \"url_on\": \"http://192.168.1.115/off?pin=2\",\n        \"url_off\": \"http://192.168.1.115/on?pin=2\",\n        \"url_status\": \"http://192.168.1.115/status?pin=2\"\n      },\n      \"sensor\": {\n        \"url\": \"http://192.168.1.116\"\n      },\n      \"system_id\": \"upstairs\",\n      \"program\": true,\n      \"periods\": \"[[3.0, 10.0, 22.0], [18.0, 23.0, 22.0]]\"\n    },\n    {\n      \"relay\": {\n        \"url_on\": \"http://192.168.1.115/off?pin=1\",\n        \"url_off\": \"http://192.168.1.115/on?pin=1\",\n        \"url_status\": \"http://192.168.1.115/status?pin=1\"\n      },\n      \"sensor\": {\n        \"url\": \"http://192.168.1.109\"\n      },\n      \"system_id\": \"downstairs\",\n      \"program\": true,\n      \"periods\": \"[[6.0, 22.0, 22.0]]\"\n    }\n  ]\n}\n```\nHere we have two heating systems (upstairs \u0026 downstairs) that share the same relay node, but have independent sensor nodes. The periods value can be omitted but consists of an array of arrays, where each inner array represents an individual period, where the first value is the start time, the second is the end time, and the last is the target temperature.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnihilok%2Fcentral-heating-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnihilok%2Fcentral-heating-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnihilok%2Fcentral-heating-api/lists"}