homebridge-klarstein-smart-ac
v1.0.1
Published
Homebridge dynamic platform plugin for Klarstein Kraftwerk Smart 12K / Klarstein Smart mobile air conditioners (Tuya / Smart Life). Local control, mock mode, and a datapoint discovery tool.
Maintainers
Readme
Homebridge Klarstein Smart AC
A Homebridge dynamic platform plugin for the Klarstein Kraftwerk Smart 12K and other Klarstein "Smart" / Smart-Life Tuya-based mobile air conditioners. It exposes the AC to Apple HomeKit either as a Heater Cooler tile or as a Thermostat (a circular temperature dial with an Off/Cool/Auto mode dropdown) — your choice per device — with power, setpoint, current temperature, fan speed, and optional Fan and Dry-mode tiles.
Because Tuya datapoints differ across models and firmwares, the plugin is fully configuration-driven and ships a discovery mode + CLI so you can map your exact device. It also includes a mock mode so you can try everything in HomeKit before touching real hardware.
⚠️ Datapoints differ by model/firmware. The default datapoint map is a starting point, not a guarantee. Always confirm your device's real datapoints with discovery (see Datapoint discovery) before relying on them. Example maps in this document are clearly marked UNVERIFIED.
Features
- Two presentations (per device, via
presentation): a Heater Cooler tile (Active, Cool/Auto, cooling setpoint 18–32 °C, current temperature, fan-speed slider, swing) or a Thermostat — a circular temperature dial with an Off / Cool / Auto mode dropdown (Dyson-style climate tile). - Mock mode — a fully working simulated AC; no hardware needed.
- Tuya Local control over your LAN via
tuyapi(no cloud round-trip, fast, private). - Configurable datapoint mapping — handles both the canonical low-DP scheme and the
vendor high-DP scheme (including "inverted" fans where
1= high). - Discovery mode + CLI to dump your device's datapoints safely (secrets are never logged).
- Optional Fan tile — a 3-speed air-flow control that mirrors the AC power — and Dry-mode switch.
- Robust: non-blocking HomeKit getters, background polling, automatic reconnect with backoff, graceful handling of bad config and offline devices.
- Secret-safe logging: local keys/tokens are never printed; device ids are masked.
Supported / target devices
| | |
|---|---|
| Primary target | Klarstein Kraftwerk Smart 12K (12 000 BTU, 3-in-1, Wi-Fi / Klarstein app) |
| Also intended for | Other Klarstein "Smart" portable ACs and many Tuya / Smart Life portable ACs (category kt) |
| Control | Local LAN (recommended) or Mock. (Tuya Cloud is scaffolded but not implemented — see Roadmap.) |
| Requires | The device's Tuya Device ID and Local Key (for local control). |
Any Tuya-based portable AC that the Smart Life / Tuya app controls is likely to work once its datapoints are mapped. If you map a device, please contribute the mapping!
Installation
Via the Homebridge UI (recommended): search for Klarstein Smart AC on the Plugins tab and install.
Via the command line:
npm install -g homebridge-klarstein-smart-acRequires Homebridge ≥ 1.8 and Node.js ≥ 20.18.
Quick start (mock mode)
Try it with no hardware first. Add this platform block to your Homebridge config.json
(or use the UI form):
{
"platforms": [
{
"platform": "KlarsteinSmartAC",
"name": "Klarstein",
"devices": [
{ "name": "Test AC", "protocol": "mock" }
]
}
]
}Restart Homebridge — a working "Test AC" Heater Cooler appears in the Home app. Toggle power, change the setpoint and fan speed; the simulated state responds (temperature drifts toward the setpoint while cooling).
Configuring a real device (Tuya Local)
You need two things from the device: its Device ID and its Local Key.
1. Obtain the Device ID and Local Key
These are not secrets the plugin can fetch for you — you obtain them once from your own Tuya account using any of the standard, well-documented tools (the plugin never scrapes credentials):
- Tuya IoT Platform developer account → Cloud → Devices → Device Details / Debug Device exposes the device id and local key.
tuya-cli:tuya-cli wizardwalks you through linking your account and lists each device'sidandkey.tinytuya(Python):python -m tinytuya wizard.- Home Assistant's LocalTuya / tuya-local document the same flow.
The Local Key changes if you remove and re-add the device in the Tuya/Smart Life app — grab a fresh key if control stops working.
2. Find the device IP
Assign the AC a static / reserved IP in your router (strongly recommended). If you leave the IP blank, the plugin will try to discover it on the LAN, but a fixed IP is far more reliable.
3. Add the device
UI: choose Tuya Local (LAN), fill in the Device ID, IP and Local Key. Or in config.json:
{
"platforms": [
{
"platform": "KlarsteinSmartAC",
"name": "Klarstein",
"devices": [
{
"name": "Living Room AC",
"protocol": "tuya-local",
"id": "REPLACE_WITH_DEVICE_ID",
"ip": "192.168.1.50",
"key": "REPLACE_WITH_LOCAL_KEY",
"version": "3.3",
"discovery": true
}
]
}
]
}Leave discovery on for the first run, check the log (see next section), map the datapoints, then
turn it off.
Datapoint (DP) discovery
Tuya portable ACs use two incompatible datapoint schemes, and you cannot tell which one your unit uses without looking. Discovery shows you.
Option A — built-in discovery mode
Set "discovery": true on the device and restart Homebridge. After it connects, the log prints
every datapoint with its id, type and current value:
[Living Room AC] ──────── Datapoint discovery ────────
[Living Room AC] Device "Living Room AC" [bf12…7f3a], protocol tuya-local.
[Living Room AC] Found 6 datapoint(s):
[Living Room AC] DP 1 type=bool value=true ← currently configured as "power"
[Living Room AC] DP 2 type=value value=22
[Living Room AC] DP 101 type=enum/string value="1"
[Living Room AC] DP 104 type=enum/string value="3"
...Operate the AC from its physical panel or the Klarstein app while watching the log — note which DP changes when you change power, temperature, mode and fan speed. (Some devices only reveal a DP once that function has been used.)
Option B — the discovery CLI
A standalone command does the same without Homebridge:
homebridge-klarstein-discover --id <DEVICE_ID> --key <LOCAL_KEY> --ip <IP> --version 3.3
# or, from a checkout: npm run build && npm run discover -- --id <ID> --key <KEY> --ip <IP>Credentials can also come from env vars: KLARSTEIN_ID, KLARSTEIN_KEY, KLARSTEIN_IP,
KLARSTEIN_VERSION. The local key is read but never printed.
Close the Tuya / Smart Life app first — a Tuya device allows only one local connection at a time, and the app will block the plugin.
Option C — Home Assistant / external tools
tuya-local and
LocalTuya also show live DPS, and
tuya-cli get --id <ID> --key <KEY> --ip <IP> --protocol-version 3.3 --all dumps the raw map.
Mapping what you find
Put the ids you discovered into dataPoints, and the raw enum strings into modeMap / fanMap:
{
"tempScale": 1, // 1 = whole degrees; use 10 if the device reports tenths
"dataPoints": {
"power": 1,
"tempSet": 2,
"tempCurrent": 3,
"mode": 101, // whatever DP changed with mode
"fanSpeed": 104, // whatever DP changed with fan speed
"swing": 0 // omit if your unit has no network swing
},
"modeMap": { "cool": "1", "dry": "3", "fan": "5" }, // raw values you observed
"fanMap": { "low": "3", "medium": "2", "high": "1" } // note: this device's fan is "inverted"
}Example datapoint maps (⚠️ UNVERIFIED — confirm with discovery)
There is no single correct map. Below are the two common schemes for portable ACs. Try one; if control does nothing, run discovery and adjust.
Scheme A — canonical Tuya kt (word enums) — plugin default
// DP 1 power (bool), 2 target °C, 3 current °C, 4 mode, 5 fan
{
"dataPoints": { "power": 1, "tempSet": 2, "tempCurrent": 3, "mode": 4, "fanSpeed": 5 },
"modeMap": { "cool": "cold", "auto": "auto", "dry": "wet", "fan": "wind" },
"fanMap": { "low": "low", "medium": "mid", "high": "high", "auto": "auto" }
}Scheme B — vendor high-DP (numeric-string enums) — closest to the known Klarstein "Iceblock"
// Mirrors make-all/tuya-local "klarstein_iceblock_airconditioner". STILL verify for your model.
// Note: mode on DP101 as "1"/"3"/"5", fan on DP104 where "1"=high, "3"=low (inverted!).
{
"dataPoints": { "power": 1, "tempSet": 2, "tempCurrent": 3, "mode": 101, "fanSpeed": 104 },
"modeMap": { "cool": "1", "dry": "3", "fan": "5" },
"fanMap": { "low": "3", "medium": "2", "high": "1" }
}The Kraftwerk Smart 12K is a different model from the Iceblock, so neither map is guaranteed — discovery is the source of truth.
How it appears in HomeKit
Pick the tile per device with presentation:
heatercooler(default) — a Heater Cooler tile: Active (on/off), a Cool/Auto control, cooling setpoint, current temperature, a fan-speed slider, and swing (if supported).thermostat— a single Thermostat: a circular temperature dial plus a mode dropdown of Off / Cool / Auto (and Heat only if you mapmodeMap.heat). HomeKit hard-locks that dropdown to Off/Heat/Cool/Auto, so Dry and Fan-only are not dropdown entries — expose them as the separate tiles below instead.
| Device mode | HomeKit |
|---|---|
| Cool | Cool |
| Auto | Auto (only if a modeMap.auto value is set) |
| Dry / Dehumidify | optional Dry switch (exposeDryModeSwitch), requires modeMap.dry |
| Fan only | covered by the optional Fan tile (exposeFanService), requires modeMap.fan |
The optional Fan tile is a 3-speed air-flow control: its on/off mirrors the AC power (it does not switch the AC off — that's the thermostat / Heater Cooler's job), and its slider sets the fan speed in any mode. Fan speed maps to RotationSpeed at Low 33 % / Medium 66 % / High 99 %. Both optional tiles are off by default — enable them per device once their mode is mapped.
Configuration reference
Each entry in devices:
| Key | Type | Default | Notes |
|---|---|---|---|
| name | string | — | Required. Display name in HomeKit. |
| protocol | mock|tuya-local|tuya-cloud | mock | tuya-cloud is not implemented yet. |
| id | string | — | Tuya device id. Required for tuya-local. |
| ip | string | (auto) | Static IP recommended. |
| key | string | — | Tuya local key. Required for tuya-local. Stored in plaintext in config.json. |
| version | string | 3.3 | Tuya protocol: 3.1/3.2/3.3/3.4/3.5. |
| pollInterval | int (s) | 30 | 5–600. |
| minTemp / maxTemp | int °C | 18 / 32 | Cooling setpoint range. |
| tempScale | int | 1 | Divide raw value by this to get °C (use 10 for tenths). |
| presentation | heatercooler|thermostat | heatercooler | HomeKit tile: a Heater Cooler, or a Thermostat dial + Off/Cool/Auto dropdown. |
| exposeFanService | bool | false | Adds a 3-speed Fan tile (air-flow; mirrors power). |
| exposeDryModeSwitch | bool | false | Adds a dry-mode switch. |
| fanControl | slider|switches|both | slider | Heater-Cooler fan UI: in-tile slider, named Low/Med/High switches, or both. |
| debug | bool | false | Verbose, device-scoped logging. |
| discovery | bool | false | Logs all datapoints at start-up. |
| dataPoints | object | canonical kt | DP id map (see discovery). |
| modeMap / fanMap | object | canonical | Raw enum value maps. |
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| Accessory shows "No Response" | Device unreachable: wrong IP, wrong/expired local key, or the device is offline. Check the log. |
| Connects then immediately disconnects | Wrong version. Try 3.4, then 3.5, then 3.1. |
| Nothing happens when you change mode/fan | Wrong DP ids or wrong enum strings — run discovery and fix dataPoints / modeMap / fanMap. |
| Fan slider feels backwards | The device uses an "inverted" fan map (1 = high). Set fanMap accordingly (Scheme B). |
| Temperature reads 10× too high/low | Set tempScale (e.g. 10 if the device reports tenths). |
| Can't connect at all / "key is incorrect" | The Tuya/Smart Life app (or another integration) holds the single local connection. Close it. Re-fetch the local key if you re-paired the device. |
| No current temperature | Some units don't expose an ambient-temperature DP; the plugin then mirrors the setpoint. |
Collecting logs safely
Enable "debug": true on the device and reproduce the issue. The plugin redacts local keys and
masks device ids in its own log lines, so its output is safe to share. Before posting a Homebridge
log or your config.json, double-check you have removed key values and full ids from any
parts not produced by this plugin.
Security notes
- The Tuya local key is a secret. The plugin never logs it; ids are masked (
bf12…7f3a). - The key is stored in plaintext in
config.json(the UI only masks the input field). Protect your Homebridge config and host accordingly. - No telemetry, no analytics, no postinstall scripts. All control stays on your LAN.
- Runtime state is kept only in Homebridge's accessory cache.
Roadmap
- Tuya Cloud control is scaffolded (
TuyaCloudClient) but not implemented — selecting it fails fast with a clear message. Usetuya-local. Cloud support may be added later behind the sameDeviceClientinterface. - Optional timer / child-lock / fault surfaces once enough devices are mapped.
Contributing a datapoint map
Mapped your device? Please open a PR or issue with:
- Device model and Tuya product id (from discovery / the Tuya IoT platform — not your device id or key),
- the working
dataPoints,modeMap,fanMap,version, andtempScale, - anything unusual (inverted fan, deci-degree temperatures, missing sensors).
This builds a community library of verified maps for Klarstein/Tuya ACs.
Developing
npm install
npm run build # compile TypeScript to dist/
npm run lint # eslint (flat config)
npm test # vitest unit tests
npm run watch # incremental compileThe architecture keeps all device transport behind a DeviceClient interface
(Mock / TuyaLocal / TuyaCloud), with pure, unit-tested mapping logic.
Disclaimer
Not affiliated with or endorsed by Klarstein or Tuya. "Klarstein", "Kraftwerk", "Tuya" and "Smart Life" are trademarks of their respective owners. Use at your own risk.
