npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

homebridge-lk-arc

v0.1.2

Published

Homebridge plugin that exposes LK Systems Arc floor heating rooms as HomeKit thermostats.

Readme

homebridge-lk-arc

npm version CI

Homebridge plugin that shows each LK Systems Arc floor-heating room as a HomeKit thermostat. It talks to the LK cloud at https://link2.lk.nu/ using the same calls as the LK app.

Version 0.1.2. One account, polling, and a target temperature.

The request and response shapes come from angoyd/ha-lksystems (MIT), pinned at commit eab11b3, and from LK's published OpenAPI. Thank you to that project for the API work. This plugin is not affiliated with LK Systems.

What it does

On each poll the plugin:

  1. Signs in with POST auth/auth/login and reads your user id from GET auth/auth/user.
  2. Loads GET service/users/user/{userId}/structure/false.
  3. Treats arc / arc-hub / arc-hub devices as hubs, and arc / arc-sense devices with role arc-sense or arc-tune as rooms.
  4. Prefers one GET service/arc/hub/{hub}/structure/false per hub (measurements are included). Sensors that hub call does not cover are read with GET service/arc/sense/{mac}/measurement/true.
  5. Skips a sensor whose desiredTemperature is null, and removes a HomeKit accessory when its room disappears.
  6. Maps each room to a Thermostat: temperatures and humidity are the cloud values divided by 10. Heating is inferred (current below target means heating). The target mode is heat only, in Celsius.

Setting the temperature in Home sends POST control/arc/sense/{mac}/temperature with {"temperature": <tenths>} after a short debounce. The value is clamped to 5–30 °C and rounded to the nearest 0.5 °C. If it matches the last known setpoint, nothing is sent. Hub structure is read from LK's cache, so for 20 seconds after a successful write the plugin keeps the temperature it just sent if that cache still shows the previous one.

Passwords and tokens are masked in the log.

The Home app shows the LK zone name (zone.zoneName). It is written to the accessory, Accessory Information, and the thermostat's Name and ConfiguredName. When a battery or humidity reading is present, those services are named <room> Battery and <room> Humidity. A name you set in the Home app is kept until that zone name changes in LK, and it is never written back to LK.

If you already paired the rooms with 0.1.0, the names are filled in automatically the first time 0.1.1 runs. Those cached accessories have no saved LK name yet, so Name and ConfiguredName are written once. After that, a Home app rename is left alone. If a room is still blank, remove that accessory in the Home app and add the bridge again.

Install

You need Node.js 18.20, 20, or 22, and Homebridge 1.8 (2.0 beta should work).

In the Homebridge UI, open Plugins and search for LK Arc or homebridge-lk-arc. From a shell:

npm install -g homebridge-lk-arc

On a machine that uses hb-service (the usual Raspberry Pi image):

sudo hb-service add homebridge-lk-arc

Restart Homebridge if it does not restart on its own. Then add the platform (the UI form comes from config.schema.json) or paste the block below into config.json.

To update later, install the package again the same way, or use the update button in the Plugins tab.

Development / testing unreleased code

Use this when you want a git checkout instead of the published package. Do not npm publish from that checkout unless you are cutting a release (see docs/RELEASING.md).

git clone https://github.com/napthemax/homebridge-lk-arc.git
cd homebridge-lk-arc
npm ci
npm run build

From the Homebridge config directory (often ~/.homebridge):

npm install /absolute/path/to/homebridge-lk-arc

npm link also works if Homebridge and the plugin run as the same user:

cd /absolute/path/to/homebridge-lk-arc
npm link
cd ~/.homebridge
npm link homebridge-lk-arc

Restart Homebridge after the install.

Raspberry Pi / hb-service

The Homebridge Raspberry Pi image runs as the homebridge user, with config and plugins under /var/lib/homebridge.

sudo hb-service stop
sudo -u homebridge git clone https://github.com/napthemax/homebridge-lk-arc.git /var/lib/homebridge/homebridge-lk-arc
cd /var/lib/homebridge/homebridge-lk-arc
sudo -u homebridge npm ci
sudo -u homebridge npm run build
cd /var/lib/homebridge
sudo -u homebridge npm install /var/lib/homebridge/homebridge-lk-arc
sudo hb-service start

npm install -g /var/lib/homebridge/homebridge-lk-arc is the other option when you intentionally install that checkout globally for hb-service. After an update, run npm run build again and reinstall from the same path so Homebridge picks up dist/.

Update an existing test install

From the checkout used for the first run, pull, rebuild, and reinstall it into Homebridge. Then restart Homebridge (sudo hb-service restart, or the restart button in the UI).

cd /var/lib/homebridge/homebridge-lk-arc && git pull && npm ci && npm run build && cd /var/lib/homebridge && npm install /var/lib/homebridge/homebridge-lk-arc

On the Raspberry Pi image those commands need to run as the homebridge user if that user owns /var/lib/homebridge. sudo hb-service stop before the install, and sudo hb-service start after, is the safe order.

Config

{
  "platforms": [
    {
      "platform": "LkArc",
      "name": "LK Arc",
      "email": "[email protected]",
      "password": "your-password",
      "pollIntervalMinutes": 5,
      "debug": false,
      "hideRooms": [],
      "encodeMac": false
    }
  ]
}

| Field | Required | Default | Meaning | |---|---|---|---| | email | yes | | LK account email | | password | yes | | LK account password. Stored in config.json like any Homebridge secret. Never written to the log. | | pollIntervalMinutes | no | 5 | Poll period. Values below 1 are raised to 1. | | debug | no | false | Also print each HTTP line at info level. | | hideRooms | no | empty | Room names or MAC addresses to leave out of HomeKit. | | encodeMac | no | false | Leave this off unless a call fails because of the colon in the MAC. See troubleshooting. |

encodeMac: false sends the MAC the way the Home Assistant integration does (AA:BB:CC:DD:EE:01). true applies encodeURIComponent to that one path segment. The choice lives in formatMacForPath.

Debug

Either is enough; both together just duplicate lines.

  • Plugin flag: "debug": true. Request lines are written with the normal logger so you can see them without Homebridge debug mode.
  • Homebridge debug: homebridge -D, or the Debug switch in the Homebridge UI (it restarts the service with -D). The plugin always sends those lines to log.debug.

A request line looks like:

GET service/arc/hub/ARCHUB000123/structure/false -> 200 (180ms)

Setpoint changes and the discovery summary are logged at info even when debug is off.

Troubleshooting

| What you see | What to try | |---|---| | Login fails | Check the email and password in the LK app. A 401 on auth/auth/login means the cloud rejected those credentials. Confirm the Pi can reach https://link2.lk.nu/. | | No rooms found | The account's user structure has no arc-sense / arc-tune sensor with a non-null desiredTemperature. Cubic detectors and the hub itself are ignored on purpose. Turn on debug and look for Discovered 0 room(s). | | 429 rate limit | The cloud asked us to slow down. The plugin honours Retry-After (or waits 5 seconds) up to three times, then backs off the poll, up to 30 minutes. Raise pollIntervalMinutes. Do not run several bridges against the same public IP if you can avoid it. | | Values not updating | Leave debug on for one poll. A warning that ends with "Keeping last known values" means the last good reading is still on the accessory. Hub structure failures fall back to a per-sensor read. | | Setpoint not applied | Compare the Home app with the LK app after ~10 seconds (the write is debounced 1.5 seconds, then one refresh runs). The plugin does not POST when the rounded value already matches the cloud. A 400 in the log is the cloud rejecting the body. | | MAC encoding | If measurement or setpoint URLs fail and the path contains a raw colon, set "encodeMac": true and restart. Turn it back off if the encoded form is what fails. | | Plugin missing in the UI | Search for homebridge-lk-arc in Plugins, or run sudo hb-service add homebridge-lk-arc, then restart. For a git checkout, npm run build must have produced dist/index.js before you install that directory. |

Known unknowns

These are copied from the API notes. Nothing here was checked against a live LK account while building 0.1.0. The fixtures under test/fixtures/ are synthetic.

  1. auth/auth/refresh was never called by the Home Assistant library. The body and response shape are from LK's OpenAPI only. The units of accessTokenExpire / refreshTokenExpire are not documented. This plugin decides expiry from the JWT exp claim (unix seconds) and, when fewer than five minutes remain, tries refresh and otherwise logs in again.
  2. The 5.0–30.0 °C range and 0.5 °C step are the Home Assistant client's limits. No setpoint min/max comes back from the API.
  3. currentBattery is assumed to be percent. connectionState has no documented enum; only a few clearly negative strings raise a fault. The meaning of actuators, overrideActive, and overrideLevel is unknown, and they are not shown in HomeKit.
  4. The ocp-apim-subscription-key is the public key shipped in the Home Assistant integration. It is not an account password. Whether LK expects other clients to keep using it is unverified.
  5. Exact rate limits are unpublished. The Home Assistant author was told the limit is per source IP and differs per endpoint.
  6. Whether the MAC in the path must be URL-encoded is unverified. The default matches the library and sends the colon form. encodeMac switches it.
  7. service/devices/device/{id}/title is referenced by the library and was not in the fetched OpenAPI dump. This plugin does not call it.
  8. Real response values were not captured from a live account. Field names follow the OpenAPI schemas and the library; the JSON files used in tests are synthetic.

Development

npm ci
npm run lint
npm run build
npm test

Tests use the synthetic fixtures and never call LK. CI runs lint, tsc, and the tests on Node 20 and 22. Publishing is a separate workflow that runs only when a vX.Y.Z tag is pushed.

License

MIT. Copyright (c) 2026 Mats Guldbrand.