@uncaught/gpio-shutter-bridge 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,7 +45,7 @@ Just to give you an insight, you can pobably use this project with any other har
45
45
  - 1 Schellenberg shutter motor in my balcony door
46
46
  - 1 Schellenberg remote control
47
47
  - Which I opened up and soldered contacts to all three buttons (up/stop/down) as well as the power supply.
48
- - This way I can supply power directly via the 3V GPIO output of the raspberry pi without needing batteries.
48
+ - This way I can supply power directly via the 3V output pin of the raspberry pi without needing batteries.
49
49
  - I'm trusting you with this [definitely professional piece of art](docs/schellenberg.png).
50
50
  - 3 Velux covers/shutters on my roof windows
51
51
  - Velux KLF 150 gateway
@@ -69,7 +69,7 @@ Just to give you an insight, you can pobably use this project with any other har
69
69
 
70
70
  ![Relay boards](docs/relay-boards.png)
71
71
 
72
- - Connect all **VCC** pins of the relays to a 3V GPIO pin of the Raspberry Pi.
72
+ - Connect all **VCC** pins of the relays to a 3V pin of the Raspberry Pi.
73
73
  - I have daisy chained them together. Only the most left relay is connected to the Pi.
74
74
  - Connect all **GND** pins of the relays to a GND pin of the Raspberry Pi.
75
75
  - Again daisy chained.
@@ -95,21 +95,59 @@ This is for the default configuration as described in the Velux KLF 150 manual.
95
95
 
96
96
  # Software
97
97
 
98
- - Create a javascript file, require my library and call it with your shutter-pin-layout:
98
+ - Make sure you have either `raspi-gpio` or `pinctrl` (newer) installed. Check with `raspi-gpio get` or `pinctrl get`.
99
+ - 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.
100
+ - `pinctrl` is newer, but requires permissions. So you either need to be root, or make sure you have access to all `/dev/gpio*` devices:
101
+ - E.g. use the `gpio` group:
102
+ - Check `ll /dev/gpio*` and see that every device is owned by the `gpio` group and has `g+rw` permissions.
103
+ - If not, use `sudo chgrp gpio /dev/gpio*` and/or `sudo chmod g+rw /dev/gpio*`.
104
+ - You can add yourself to the `gpio` group with `sudo usermod -a -G gpio $USER`.
105
+ - Verify with `pinctrl get` that you can use the tool without further permissions.
106
+ - Go into a folder where you wish to install this project.
107
+ - Install the library with `npm install @uncaught/gpio-shutter-bridge`
108
+ - Create a javascript file (e.g. `run.js`), require my library and call it with your shutter-pin-layout:
99
109
 
100
110
  ```js
101
111
  import {createVeluxShutters, initRuntime, initMqtt} from '@uncaught/gpio-shutter-bridge';
102
112
 
103
113
  const {onDispose} = initRuntime();
104
114
 
105
- onDispose(initMqtt(createVeluxShutters([
115
+ initMqtt(createVeluxShutters([
106
116
  {ident: 'Velux_A', up: 2, down: 3, input: 14},
107
117
  {ident: 'Velux_B', up: 4, down: 17, input: 15},
108
118
  {ident: 'Velux_C', up: 27, down: 22, input: 18},
109
119
  {ident: 'Velux_D', up: 10, down: 9, input: 23},
110
120
  {ident: 'Velux_E', up: 11, down: 8, input: 24}, //same row!
111
- ], onDispose), {url: 'mqtt://your-mqtt-or-home-assistant'}));
121
+ ], onDispose), onDispose, {url: 'mqtt://your-mqtt-or-home-assistant'});
112
122
  ```
113
123
 
114
124
  - The ident should match `/[a-zA-Z][a-zA-Z0-9_-]*/`.
115
125
  - See [my personal example](./example.ts) for a few more details.
126
+
127
+ ## Dockerizing
128
+
129
+ 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.
130
+
131
+ If you find a way to get it working, please let me know, I'll add it as an example.
132
+
133
+ <details>
134
+ <summary>My attempts</summary>
135
+
136
+ I tried based off of this:
137
+
138
+ ```Dockerfile
139
+ FROM node:25.0.0-trixie-slim
140
+
141
+ RUN apt update && apt install -y git build-essential cmake \
142
+ && git clone https://github.com/raspberrypi/utils.git \
143
+ && cd utils/pinctrl \
144
+ && cmake . \
145
+ && make \
146
+ && make install
147
+
148
+ ENTRYPOINT ["bash"]
149
+ ```
150
+
151
+ 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`
152
+
153
+ </details>
package/dist/example.js CHANGED
@@ -30,4 +30,4 @@ const shutters = [
30
30
  ...createVeluxShutters(veluxKlf150CDE, onDispose),
31
31
  createThreeButtonShutter('Balkon', 10, 9, 11, onDispose),
32
32
  ];
33
- onDispose(initMqtt(shutters, { url: 'mqtts://mosquitto.local.correnz.net', rejectUnauthorized: false }));
33
+ initMqtt(shutters, onDispose, { url: 'mqtts://mosquitto.local.correnz.net', rejectUnauthorized: false });
package/dist/src/Gpio.js CHANGED
@@ -20,13 +20,23 @@ export function mkInput(pin, onDispose) {
20
20
  //Setting to pull-up - the `onoff`-library doesn't do that.
21
21
  // I'm doing this because the inputs were floating high without any pull, so I just stick with it.
22
22
  // We assume the input pin is closed to ground, causing it to change to low.
23
- execSync(`raspi-gpio set ${pin} pu`);
23
+ try {
24
+ execSync(`raspi-gpio set ${pin} pu`);
25
+ }
26
+ catch {
27
+ try {
28
+ execSync(`pinctrl set ${pin} pu`); //newer tool, replacing raspi-gpio, might need root though
29
+ }
30
+ catch {
31
+ console.error('Unable to set pull-up on GPIO input');
32
+ }
33
+ }
24
34
  const gpio = new Gpio(pin, 'in', 'both');
25
35
  onDispose(() => gpio.unexport());
26
36
  //Double check that the input is high:
27
37
  const value = gpio.readSync();
28
38
  if (value !== Gpio.HIGH) {
29
- console.error(`Expected GPIO ${pin} to be high, but it was ${value}`);
39
+ console.error(`Expected GPIO ${pin} to be high (3V), but it was low (0V)`);
30
40
  }
31
41
  return gpio;
32
42
  }
@@ -1,5 +1,6 @@
1
1
  import { type IClientOptions } from 'mqtt';
2
2
  import { ShutterInterface } from '../Shutter/Shutter.js';
3
- export declare function initMqtt(shutters: readonly ShutterInterface[], { url, ...mqttOpts }: {
3
+ import type { OnDispose } from '../runtime.js';
4
+ export declare function initMqtt(shutters: readonly ShutterInterface[], onDispose: OnDispose, { url, ...mqttOpts }: {
4
5
  url: string;
5
- } & IClientOptions, namespace?: string): () => Promise<void>;
6
+ } & IClientOptions, namespace?: string): void;
@@ -9,7 +9,7 @@ function validateNamespacePart(str) {
9
9
  throw new Error(`Invalid string for namespace: ${str}`);
10
10
  }
11
11
  }
12
- export function initMqtt(shutters, { url, ...mqttOpts }, namespace = 'shutter') {
12
+ export function initMqtt(shutters, onDispose, { url, ...mqttOpts }, namespace = 'shutter') {
13
13
  const shuttersById = new Map(shutters.map((s) => [s.ident, s]));
14
14
  validateNamespacePart(namespace);
15
15
  const ns1 = namespace;
@@ -66,7 +66,7 @@ export function initMqtt(shutters, { url, ...mqttOpts }, namespace = 'shutter')
66
66
  },
67
67
  origin: {
68
68
  name: ns0,
69
- sw_version: '1.0.0',
69
+ sw_version: '1.1.0',
70
70
  support_url: 'https://github.com/uncaught/gpio-shutter-bridge',
71
71
  },
72
72
  payload_available: 'online',
@@ -127,8 +127,8 @@ export function initMqtt(shutters, { url, ...mqttOpts }, namespace = 'shutter')
127
127
  publish(`homeassistant/device/${deviceId}/config`, JSON.stringify(autoDiscoveryPayload), { retain: true });
128
128
  publish(deviceAvailabilityTopic, 'online', { retain: true });
129
129
  });
130
- return async () => {
130
+ onDispose(async () => {
131
131
  publish(deviceAvailabilityTopic, 'offline', { retain: true });
132
132
  await client.endAsync();
133
- };
133
+ });
134
134
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uncaught/gpio-shutter-bridge",
3
3
  "author": "uncaught <uncaught42@gmail.com>",
4
4
  "license": "MIT",
5
- "version": "1.0.0",
5
+ "version": "1.1.0",
6
6
  "description": "MQTT shutter bridge for home assistant with Velux KLF 150 support",
7
7
  "repository": {
8
8
  "type": "git",