Velux KLF200
Driver for the Velux KLF200 interface gateway — the small white box that bridges Velux (and other io-homecontrol) motorized products onto your LAN so GEM can operate them. Through one KLF200 you reach every io-homecontrol node it has been paired with:
- Electric / solar skylights and roof windows (open / close / position).
- Interior blinds, blackout blinds, roller shutters, awning blinds, and venetian blinds.
- Awnings and external shutters on the same radio family.
GEM talks to the gateway over an encrypted TLS socket on TCP port 51200 using the KLF200 interface protocol. The gateway's self-signed certificate is accepted automatically — there is nothing to import. Because the KLF200 is a controller (one box addressing many products), you add it once as a device and then create one zone per Velux product you want to control.
The KLF200 speaks the io-homecontrol radio protocol used by Velux and Somfy gear. Despite what one command label reads, it is not a KNX gateway.
Prerequisites
- Pair your Velux products to the gateway first, in the Velux ecosystem — not
in GEM. Use the KLF200's own setup page (join its
KLF200_…Wi-Fi and browse to its configuration URL), a Velux remote (KLR 200 / KLR 300), or the Velux app to copy each product's key into the gateway. GEM controls only products the gateway already knows about; it does not enroll new hardware. - Program your scenes on the gateway. Scene activation is the most reliable way to move Velux products from a third-party controller, so build the scenes you want ("Skylights open", "Bedroom blind closed", "Blinds 50 %") in the KLF200's setup page or the Velux app before you wire up GEM.
- Put the gateway in interface (API) mode via its setup page. This is the mode that exposes the control socket on port 51200.
- Find the interface password. It is printed on the label on the back / underside of the gateway. It can be up to 32 characters; anything longer is truncated.
- Network: give the KLF200 a static IP or DHCP reservation and make sure TCP 51200 is reachable from the GEM host. The gateway drops idle connections after roughly 15 minutes, so a stable path matters.
Setup — add the gateway
- Go to System → Devices → Add Device and set:
- Driver → Velux KLF200.
- Gateway IP Address → the KLF200's LAN IP.
- KLF200 Password → the interface password from the device label. This field is stored encrypted.
- TLS Port → leave at 51200 unless you have re-mapped the port.
- Enable the device. On connect, GEM opens the TLS socket, sends the password, reads the gateway's firmware version, and starts a keep-alive ping every 10 minutes so the gateway doesn't time the socket out. If the password is wrong the gateway refuses the session and GEM closes and retries the connection — a device that keeps flapping between connected and disconnected almost always means a bad password.
- Advanced (optional). Two extra fields are available if you need them:
Reconnect Timeout (ms) (default
5000) and Keep-Alive Ping Interval (ms) (default600000= 10 minutes). Leave the ping interval below the gateway's ~15-minute idle timeout.
Unlike some controllers, the KLF200 driver does not build zones for you. You create one zone per Velux product by hand and set its Address to that product's node id (see below).
Two ways to control Velux from GEM
The gateway exposes exactly two control paths, and they suit different jobs.
Scenes — the recommended path
Scenes you programmed on the gateway carry everything the API can't express on its own: grouped products, direction, intermediate positions, and speed. From GEM you simply trigger a scene by its id.
- Run
get_scenesagainst the device to confirm the gateway answers with its scene list. - Run
activate_scenewith ascene_idto recall a scene. Wire this into a macro or a UI button — e.g. an "Open skylights" button that runsactivate_scenewith the id of your "Skylights open" scene.
Because each scene is a fixed, pre-tested outcome, this is the most predictable way to move Velux products and the right default for most installs.
Direct node control — node_command
To move a single product without a scene, use node_command with a
node_id and a level (0–100):
levelmaps linearly across the product's travel.0and100are the two ends of travel — but which end is "open" and which is "closed" depends on the product type (a roof window and a roller shutter move in opposite senses for the same number). Test one node and note which value opens it before you wire the rest.- There is no mid-travel stop on this path —
levelonly ever commands a target position. Use a scene if you need a "stop" or a partial-open preset.
Making the on-screen open / close buttons work
A Velux zone's standard Open / Close / Stop buttons do nothing on their own:
the driver only understands the five commands in the reference below, so a plain
open or close verb is rejected. To make those buttons operate a product, add
a per-verb command override on the zone that redirects the verb to
node_command (see Command Overrides on
the Zones page).
On the zone, add these attributes (values are JSON; replace <gateway device id>
with the KLF200 device's id and <node> with the product's node id):
-
open_action{"command": "node_command", "device_id": 12, "args": {"node_id": 3, "level": 0}} -
close_action{"command": "node_command", "device_id": 12, "args": {"node_id": 3, "level": 100}}
Swap the 0 / 100 if your product opens on 100 (see the direction note
above). Leave stop_action unset — the driver has no true stop, so the
control correctly hides the Stop button. If you want a stop, point
stop_action at a scene ({"command": "activate_scene", "device_id": 12, "args": {"scene_id": <id>}}) or a macro instead.
An override dispatches exactly the arguments written in it. The runtime value
from a dimmer/shade slider (the set_level position) is not passed
through, and neither is the zone's own address. That's why open_action /
close_action above hardcode both the node id and a fixed level. To hit
arbitrary positions, use a Velux scene per position, or call
node_command directly from a macro/button with the level you want.
Finding node ids and scene ids
Node ids (integers 0–199) and scene ids are assigned by the gateway in the
order you paired the products and created the scenes. The gateway's
get_nodes / get_scenes commands trigger a response, but this driver reports it
in raw form rather than a tidy on-screen list — so read the actual ids from where
you programmed them:
- Node ids — the product order on the KLF200 setup page (and in the Velux
app) is the node order. The first product you added is node
0, the next1, and so on. - Scene ids — the scene order in the KLF200 setup page / Velux app.
Put the node id in the zone's Address field; pass the scene id as the
scene_id argument to activate_scene.
Zones — one per Velux product
- Open the KLF200 device's Zones tab (or System → Zones → Add) and add a zone for each product.
- GEM pre-selects the Shades subsystem for you. Set Control to Shade so the zone renders the shade control in UIs.
- Set Address to the product's node id (
0–199). - To make the Open / Close buttons work, add the
open_action/close_actionoverrides shown above — or drive the zone entirely from scene buttons/macros.
Device attributes
| Attribute | Set by | Purpose |
|---|---|---|
ip (Gateway IP Address) | You | LAN IP of the KLF200. Use a static IP or DHCP reservation. |
password (KLF200 Password) | You | The interface password from the device's back label (up to 32 characters). Stored encrypted. |
port (TLS Port) | Optional | Control port. Default 51200 — leave as-is unless remapped. |
reconnect_timeout (Reconnect Timeout (ms)) | Optional | Delay before retrying a dropped connection. Default 5000. |
ping_interval (Keep-Alive Ping Interval (ms)) | Optional | How often GEM pings the gateway to hold the socket open. Default 600000 (10 min); keep below the gateway's ~15-min idle timeout. |
Zone attributes
| Attribute | Purpose |
|---|---|
| Address | The product's io-homecontrol node id (0–199). Required — this is how a zone's commands reach the right product. |
open_action / close_action | Optional per-verb overrides that redirect the zone's Open / Close buttons to node_command (see above). |
stop_action | Optional override for the Stop button — point it at a scene or macro, since the driver has no native stop. |
Command reference
Run these from the device's Commands tab (the command tester) or from
macros and UI buttons. getCommands() on the driver
declares exactly these five:
| Command | Arguments | Action |
|---|---|---|
discover | — | Tell the gateway to re-scan its io-homecontrol radio for paired products. Run after adding a new Velux product to the gateway. |
get_nodes | — | Ask the gateway for its node information. Useful to confirm the gateway is answering; read the actual node ids from the Velux configuration (see above). |
get_scenes | — | Ask the gateway for its stored scene list. Same as get_nodes — confirms the response; read the scene ids from the Velux configuration. |
activate_scene | scene_id | Recall a scene stored on the gateway by its id. The primary way to move Velux products from GEM. |
node_command | node_id, level | Move a single product to a target position. level 0–100 maps across the product's travel; 0 and 100 are the two ends (direction depends on the product — test it). No mid-travel stop. |
What GEM tracks — and what it doesn't
The KLF200 integration is open-loop: GEM sends scene and position commands to
the gateway, but this driver does not currently read the live position of a
product back onto its zone. A shade zone will not automatically reflect the real
skylight position or update if someone moves it with a physical Velux remote. If
you need a zone to show a known state, drive it exclusively through GEM (scenes or
node_command) so GEM's last command is the source of truth, and avoid mixing in
manual remote operation for those products.
Troubleshooting
| Symptom | Check |
|---|---|
| Device flaps between connected and disconnected | Almost always a wrong KLF200 Password. Re-enter the password from the device label (not any Wi-Fi/app password you set). |
| Never connects at all | Confirm the gateway is in interface (API) mode, has a reachable static IP, and that TCP 51200 is open from the GEM host. |
| Open / Close buttons do nothing | The zone has no open_action / close_action override. A bare Open / Close verb is rejected by this driver — add the overrides shown above, or drive the zone from scene buttons. |
| A product moves the wrong way | The product opens on the other end of travel — swap the level values (0 ↔ 100) in open_action / close_action, or use a scene. |
| Stop button doesn't stop mid-travel | Expected — there is no native stop. Point stop_action at a scene/macro, or leave it unset to hide the button. |
get_nodes / get_scenes don't list anything readable | Expected — the driver confirms the gateway responded but doesn't render the full list. Read node/scene ids from the KLF200 setup page or the Velux app. |
| Nothing responds after pairing a new product | Run discover so the gateway re-scans its radio, then confirm the new product's node id and create/point a zone at it. |
| Device drops offline every ~15 minutes | The keep-alive isn't holding the socket. Confirm nothing on the network is closing idle TCP sessions, and leave Keep-Alive Ping Interval at its default (10 min) or lower. |
Related documentation
- Devices — add the KLF200 controller and manage its connection settings.
- Zones — create one zone per Velux product; see Command Overrides for the
open_action/close_actionpattern. - Commands — where
discover,get_scenes,activate_scene, andnode_commandappear and can be tested. - Subsystems — the Shades subsystem these zones land in.
- Macros — trigger
activate_sceneornode_commandfrom automations and UI buttons.