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

@uncaught/gpio-shutter-bridge

v1.1.1

Published

MQTT shutter bridge for home assistant with Velux KLF 150 support

Downloads

21

Readme

MQTT shutter bridge for home assistant or alike

This is an implementation of a bridge between shutter controls and home assistant.

In particular I have connected one Velux KLF 150 gateway and one Schellenberg shutter remote to my Raspberry Pi using the GPIO pins.

But you can use this for Velux only, of course. You will need 3 GPIO pins for each Velux shutter and you can use up to 5 shutters with the KLF 150 in this setup.

No soldering required if you stick with Velux only - everything is just screws.

Features

  • Supports Velux KLF 150 or any 3-button remote control
  • MQTT interface with auto-discovery for home assistant
  • Positioning of the Velux shutters (time-based)

Flow chart

flowchart LR
    HA[Home Assistant/MQTT] <--> Bridge[THIS LIBRARY]
    Bridge <--> GPIO[Raspberry Pi GPIOs]
    GPIO --> Relays[Relay Modules]
    Relays --> KLF[Velux KLF 150]
    Relays --> Remote[Schellenberg Remote]
    KLF <--> Velux[Velux Shutters]
    KLF --> GPIO
    Remote --> Balcony[Balcony Shutter]

    style Bridge fill:#ff9900,stroke:#333,stroke-width:2px,color:#fff

Hardware

Before unboxing

This is how everything looks before "unboxing" it into a more permanent shape:

finished cabling

My hardware

Just to give you an insight, you can pobably use this project with any other hardware. It could make sense to buy a complete ESP32 GPIO board instead of using a Raspberry Pi.

  • 1 Schellenberg shutter motor in my balcony door
  • 1 Schellenberg remote control
    • Which I opened up and soldered contacts to all three buttons (up/stop/down) as well as the power supply.
    • This way I can supply power directly via the 3V output pin of the raspberry pi without needing batteries.
    • I'm trusting you with this definitely professional piece of art.
  • 3 Velux covers/shutters on my roof windows
  • Velux KLF 150 gateway
    • See https://www.velux.com/klf150
    • Before buying this, I also tried soldering contacts to the Velux remotes (model 3UR B01 WW), but I broke the first...
  • 9 relay modules
    • If you use a Raspberry PI, you need relays that work with 3V and it helps if they already have a pull-up resistor because the GPIO pins can have a floating voltage when the PI boots and they are not yet assigned as outputs, triggering the relay when it shouldn't.
    • I bought this 10 pack on amazon
    • You will need 2 relays per Velux shutter, so for my three windows I needed 6 relays.
    • Additionally I needed 3 relays for my Schellenberg remote control.
    • If you find a board with multiple 3V relays on it, go ahead. I just screwed mine together on a wooden board.
  • Raspberry Pi Model B
    • Yes, the first version of the Raspberry Pi with the single armv6 CPU!
    • Still had this lying around, so why waste it.
    • I got node 21 running on it for this project.
  • One USB power supply for the Raspberry Pi
    • I used one of my many 2A supplies, not the 1.4A one that comes with the Velux KLF 150.
    • The Pi then powers the relays, the KLF 150 and the Schellenberg remote.

Wiring GPIOs to the relays

Relay boards

  • Connect all VCC pins of the relays to a 3V pin of the Raspberry Pi.
    • I have daisy chained them together. Only the most left relay is connected to the Pi.
  • Connect all GND pins of the relays to a GND pin of the Raspberry Pi.
    • Again daisy chained.
  • Connect each IN pin of the relays to one GPIO pin of the Raspberry Pi.

Wiring the Velux KLF 150 to the rest

Velux KLF 150 sockets

This is for the default configuration as described in the Velux KLF 150 manual. Meaning: You have 2 output pins and 4 input pins per shutter (A, B, C, D, E). For each shutter, the first input pin makes the shutter open, the second input pin makes it close, and both together make the shutter stop. The output pins for each shutter should close on success (also the default behavior).

Outputs

  • Connect all 5 bottom pins of the output (A-E) together and to GND.
  • Connect all 5 top pins of the output (A-E) to any GPIO pin.

Inputs

  • The bottom line of all input pins are for GND. However, since the cabling comes in pairs anyway and you need to connect them each to one of the relays, I just used all the existing cables.
  • So connect all 10 inputs to the 10 relays, the top one to NO (normally open) and the bottom one to COM (common).

Software

  • Make sure you have either raspi-gpio or pinctrl (newer) installed. Check with raspi-gpio get or pinctrl get.
    • Either one is used to set the GPIO input pins to the "pull up" mode. This is not handled in the onoff-library I'm using.
    • pinctrl is newer, but requires permissions. So you either need to be root, or make sure you have access to all /dev/gpio* devices:
      • E.g. use the gpio group:
        • Check ll /dev/gpio* and see that every device is owned by the gpio group and has g+rw permissions.
        • If not, use sudo chgrp gpio /dev/gpio* and/or sudo chmod g+rw /dev/gpio*.
        • You can add yourself to the gpio group with sudo usermod -a -G gpio $USER.
        • Verify with pinctrl get that you can use the tool without further permissions.
  • Go into a folder where you wish to install this project.
  • Install the library with npm install @uncaught/gpio-shutter-bridge
  • Create a javascript file (e.g. run.js), require my library and call it with your shutter-pin-layout:
import {createVeluxShutters, initRuntime, initMqtt} from '@uncaught/gpio-shutter-bridge';

const {onDispose} = initRuntime();

initMqtt(createVeluxShutters([
  {ident: 'Velux_A', up: 2, down: 3, input: 14},
  {ident: 'Velux_B', up: 4, down: 17, input: 15},
  {ident: 'Velux_C', up: 27, down: 22, input: 18},
  {ident: 'Velux_D', up: 10, down: 9, input: 23},
  {ident: 'Velux_E', up: 11, down: 8, input: 24}, //same row!
], onDispose), onDispose, {url: 'mqtt://your-mqtt-or-home-assistant'});
  • The ident should match /[a-zA-Z][a-zA-Z0-9_-]*/.
  • See my personal example for a few more details.

Dockerizing

I tried to dockerize this project, but I was not able to get it to work with only specific mapped devices. The pinctrl kept saying "No GPIO chips found". I've only managed to get it working with the --privileged flag, which for me, kind of defeats the purpose of running this inside docker.

If you find a way to get it working, please let me know, I'll add it as an example.

I tried based off of this:

FROM node:25.0.0-trixie-slim

RUN apt update && apt install -y git build-essential cmake \
    && git clone https://github.com/raspberrypi/utils.git \
    && cd utils/pinctrl \
    && cmake . \
    && make \
    && make install

ENTRYPOINT ["bash"]

Building with docker build -t gpio . and running with docker run --rm -it --device /dev/gpiochip0 --device /dev/gpiochip1 --device /dev/gpiochip2 --device /dev/gpiomem --cap-add SYS_RAWIO gpio