hb-rpi-tools 0.0.2 → 0.0.3

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.
@@ -650,12 +650,17 @@ class PigpioClient extends GpioClient {
650
650
  await this.command(this.commands.WDOG, gpio, timeout)
651
651
  }
652
652
 
653
- async dhtPoll (gpio) {
653
+ async dhtRead (gpio) {
654
654
  await this.write(gpio, 0)
655
655
  await timeout(18)
656
656
  await this.setInput(gpio, this.pudValues.up)
657
657
  }
658
658
 
659
+ async read (gpio) {
660
+ const response = await this.command(this.commands.READ, gpio)
661
+ return response.status !== 0
662
+ }
663
+
659
664
  async write (gpio, value) {
660
665
  await this.command(this.commands.WRITE, gpio, (value ? 1 : 0))
661
666
  }
@@ -380,12 +380,20 @@ class RgpioClient extends GpioClient {
380
380
  await this.command(commands.PASSW, { string: hash.digest('hex') })
381
381
  this.emit('message', `user ${this._params.user} logged in`)
382
382
 
383
- this.gpioChipHandle = (await (this.command(commands.GO, { longs: [0] }))).status
384
- if (this.gpioChipHandle !== 0) {
385
- this.emit('warning', new Error(`got GPIO chip handle ${this.gpioChipHandle}`))
383
+ await this.command(commands.SHARE, { longs: [42] })
384
+ this.gpioChipHandle = 0
385
+ try {
386
+ const result = await this.command(commands.GIC, { longs: [this.gpioChipHandle] })
387
+ this.emit('message', `${result.name}: ${result.label}`)
388
+ } catch (error) {
389
+ this.emit('message', `warning: ${error.message}`)
390
+ this.gpioChipHandle = (await (this.command(commands.GO, { longs: [0] }))).status
391
+ if (this.gpioChipHandle !== 0) {
392
+ this.emit('warning', new Error(`got GPIO chip handle ${this.gpioChipHandle}`))
393
+ }
394
+ const result = await this.command(commands.GIC, { longs: [this.gpioChipHandle] })
395
+ this.emit('message', `${result.name}: ${result.label}`)
386
396
  }
387
- const result = await this.command(commands.GIC, { longs: [this.gpioChipHandle] })
388
- this.emit('message', `${result.name}: ${result.label}`)
389
397
  }
390
398
 
391
399
  /** Subscribe to notifications for changed GPIO values.
@@ -405,9 +413,9 @@ class RgpioClient extends GpioClient {
405
413
 
406
414
  await super.listen()
407
415
 
408
- if (this.dataHandle !== 0) {
409
- this.emit('warning', new Error(`got data handle ${this.dataHandle}`))
410
- }
416
+ // if (this.dataHandle !== 0) {
417
+ // this.emit('warning', new Error(`got data handle ${this.dataHandle}`))
418
+ // }
411
419
 
412
420
  const { tick, date } = await this.command(commands.TICK)
413
421
  this.emit('message', `tick: ${tick} (${date})`)
@@ -450,7 +458,7 @@ class RgpioClient extends GpioClient {
450
458
  }
451
459
  delete this.fileHandle
452
460
  }
453
- if (this.gpioChipHandle != null) {
461
+ if (this.gpioChipHandle != null && this.gpioChipHandle !== 0) {
454
462
  try {
455
463
  await this.command(commands.GC, { longs: [this.gpioChipHandle] })
456
464
  } catch (error) {
@@ -644,9 +652,10 @@ class RgpioClient extends GpioClient {
644
652
  value = (await this.command(this.commands.GR, { longs: [this.gpioChipHandle, gpio] })).status
645
653
  }
646
654
  await this.command(this.commands.GSOX, { longs: [this.gpioChipHandle, gpioModes.none, gpio, value] })
655
+ // this.mask |= (1 << gpio)
647
656
  }
648
657
 
649
- async dhtPoll (gpio) {
658
+ async dhtRead (gpio) {
650
659
  await this.setOutput(gpio, 0)
651
660
  await timeout(18)
652
661
  await this.command(this.commands.GSAX, {
@@ -655,6 +664,11 @@ class RgpioClient extends GpioClient {
655
664
  })
656
665
  }
657
666
 
667
+ async read (gpio) {
668
+ const result = await this.command(this.commands.GR, { longs: [this.gpioChipHandle, gpio] })
669
+ return result.status === 1
670
+ }
671
+
658
672
  async write (gpio, value) {
659
673
  await this.command(this.commands.GW, { longs: [this.gpioChipHandle, gpio, value ? 1 : 0] })
660
674
  this.emit('gpio' + gpio, { value, tick: 0 })
@@ -666,7 +680,7 @@ class RgpioClient extends GpioClient {
666
680
 
667
681
  async writePwm (gpio, dutyCycle) {
668
682
  await this.command(this.commands.PX, {
669
- longs: [this.gpioChipHandle, gpio, 1024000, dutyCycle * 1000, 0, 0]
683
+ longs: [this.gpioChipHandle, gpio, dutyCycle === 0 ? 0 : 10000000, dutyCycle * 100, 0, 0]
670
684
  })
671
685
  }
672
686
 
@@ -715,9 +729,9 @@ class RgpioClient extends GpioClient {
715
729
  delete this.fileHandle
716
730
  }
717
731
  this.fileHandle = (await this.command(commands.FO, { longs: [1], string: filename })).status
718
- if (this.fileHandle !== 1) {
719
- this.emit('warning', new Error(`got file handle ${this.fileHandle}`))
720
- }
732
+ // if (this.fileHandle !== 1) {
733
+ // this.emit('warning', new Error(`got file handle ${this.fileHandle}`))
734
+ // }
721
735
  let s = ''
722
736
  let result
723
737
  do {
@@ -746,9 +760,9 @@ class RgpioClient extends GpioClient {
746
760
  delete this.fileHandle
747
761
  }
748
762
  this.fileHandle = (await this.command(commands.FO, { longs: [2], string: filename })).status
749
- if (this.fileHandle !== 1) {
750
- this.emit('warning', new Error(`got file handle ${this.fileHandle}`))
751
- }
763
+ // if (this.fileHandle !== 1) {
764
+ // this.emit('warning', new Error(`got file handle ${this.fileHandle}`))
765
+ // }
752
766
  await this.command(commands.FW, { longs: [this.fileHandle], string: text })
753
767
  await this.command(commands.FC, { longs: [this.fileHandle] })
754
768
  delete this.fileHandle
@@ -0,0 +1,91 @@
1
+ // hb-rpi-tools/lib/GpioDhtClient.js
2
+ // Copyright © 2019-2026 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge RPi Tools.
5
+
6
+ import { EventEmitter, once } from 'node:events'
7
+
8
+ /** Class to read a DHTxx sensor connected to a GPIO pin.
9
+ *
10
+ * @extends EventEmitter
11
+ */
12
+ class GpioDhtClient extends EventEmitter {
13
+ constructor (parent, pi, gpio) {
14
+ super()
15
+ this.debug = parent.debug.bind(parent)
16
+ this.vdebug = parent.vdebug.bind(parent)
17
+ this.pi = pi
18
+ this.gpio = gpio
19
+
20
+ this.pi.on('gpio' + this.gpio, (payload) => {
21
+ if (payload.value) {
22
+ const duration = payload.tick - (this._previousTick ?? 0)
23
+ this._previousTick = payload.tick
24
+ this.#update(duration)
25
+ }
26
+ })
27
+ }
28
+
29
+ async read () {
30
+ const timeout = setTimeout(() => {
31
+ this.emit('error', new Error(`gpio ${this.gpio}: timeout`))
32
+ }, this.pi._params.timeout * 1000)
33
+ this.pi.dhtRead(this.gpio)
34
+ const a = await once(this, 'dht')
35
+ clearTimeout(timeout)
36
+ return a[0]
37
+ }
38
+
39
+ #update (duration) {
40
+ this.vdebug('gpio %d: rise after %d µs', this.gpio, duration)
41
+ if (duration > 10000) {
42
+ this.receiving = true
43
+ this.bit = this.pi.port === 8888 ? -2 : 0
44
+ this.data = 0n
45
+ } else if (this.receiving) {
46
+ if (++this.bit >= 1) {
47
+ this.data <<= 1n
48
+ if (duration >= 60 && duration <= 100) {
49
+ // 0 bit
50
+ this.vdebug('gpio %d: bit %d: 0', this.gpio, this.bit)
51
+ } else if (duration > 100 && duration <= 160) {
52
+ this.data += 1n // 1 bit
53
+ this.vdebug('gpio %d: bit %d: 1', this.gpio, this.bit)
54
+ } else {
55
+ this.receiving = false // invalid
56
+ this.debug('gpio %d: invalid signal', this.gpio)
57
+ }
58
+ if (this.receiving && this.bit === 40) {
59
+ const buf = Buffer.alloc(8)
60
+ buf.writeBigUint64LE(this.data)
61
+ if (((buf[1] + buf[2] + buf[3] + buf[4]) & 0xFF) !== buf[0]) {
62
+ this.debug('gpio %d: bad checksum', this.gpio)
63
+ return
64
+ }
65
+ let ok = false
66
+ let sensor = 'DHTxx'
67
+ let temperature = buf.readInt16LE(1) / 10
68
+ let humidity = buf.readUint16LE(3) / 10
69
+ ok = temperature >= -40 && temperature <= 125 && humidity <= 100
70
+ if (!ok) {
71
+ sensor = 'DHT11'
72
+ temperature = buf[2]
73
+ humidity = buf[4]
74
+ ok = temperature <= 50 && humidity >= 20 && humidity <= 80
75
+ }
76
+ if (!ok) {
77
+ this.debug('gpio %d: invalid data', this.gpio)
78
+ return
79
+ }
80
+ this.debug(
81
+ 'gpio %d: %s: temperature: %d, humidity: %d',
82
+ this.gpio, sensor, temperature, humidity
83
+ )
84
+ this.emit('dht', { temperature, humidity })
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ export { GpioDhtClient }
@@ -31,10 +31,14 @@ class GpioLedChain extends EventEmitter {
31
31
  this._nLeds = params.nLeds ?? 8
32
32
 
33
33
  this._leds = []
34
+ this._bri = 0xFF
34
35
 
35
36
  this._initWordBuffer()
36
37
  }
37
38
 
39
+ get bri () { return this._bri }
40
+ set bri (value) { this._bri = value & 0xFF }
41
+
38
42
  /** Initialise GPIO pins and update all LEDs.
39
43
  * @param {boolean} [turnOff=false] - Turn LEDs off.
40
44
  */
@@ -177,7 +181,7 @@ class GpioLedChain extends EventEmitter {
177
181
  await once(this, 'stopped')
178
182
  }
179
183
 
180
- async colorloop (bri = 0xFF) {
184
+ async colorloop () {
181
185
  let r = 0
182
186
  let g = 1
183
187
  let b = 255
@@ -196,14 +200,14 @@ class GpioLedChain extends EventEmitter {
196
200
  } else if (r === 0 && g > 0 && b === 255) {
197
201
  g--
198
202
  }
199
- this.setAllLeds(bri, r, g, b)
203
+ this.setAllLeds(this._bri, r, g, b)
200
204
  await this.update()
201
205
  }
202
206
  this.emit('stopped')
203
207
  }
204
208
 
205
209
  // Inspired by: https://github.com/pimoroni/blinkt/blob/master/examples/larson.py
206
- async cylon (bri = 0xFF) {
210
+ async cylon () {
207
211
  let eye = -2 // eye centre goes from -2 to nLeds + 1
208
212
  let up = true
209
213
 
@@ -219,25 +223,25 @@ class GpioLedChain extends EventEmitter {
219
223
  this._continue = true
220
224
  while (this._continue) {
221
225
  if (eye - 3 >= 0) {
222
- this.setLed(eye - 3, bri, 0, 0, 0)
226
+ this.setLed(eye - 3, this._bri, 0, 0, 0)
223
227
  }
224
228
  if (eye - 2 >= 0) {
225
- this.setLed(eye - 2, bri, 16, 0, 0)
229
+ this.setLed(eye - 2, this._bri, 16, 0, 0)
226
230
  }
227
231
  if (eye - 1 >= 0) {
228
- this.setLed(eye - 1, bri, 64, 0, 0)
232
+ this.setLed(eye - 1, this._bri, 64, 0, 0)
229
233
  }
230
234
  if (eye >= 0 && eye < this._nLeds) {
231
- this.setLed(eye, bri, 255, 0, 0)
235
+ this.setLed(eye, this._bri, 255, 0, 0)
232
236
  }
233
237
  if (eye + 1 < this._nLeds) {
234
- this.setLed(eye + 1, bri, 64, 0, 0)
238
+ this.setLed(eye + 1, this._bri, 64, 0, 0)
235
239
  }
236
240
  if (eye + 2 < this._nLeds) {
237
- this.setLed(eye + 2, bri, 16, 0, 0)
241
+ this.setLed(eye + 2, this._bri, 16, 0, 0)
238
242
  }
239
243
  if (eye + 3 < this._nLeds) {
240
- this.setLed(eye + 3, bri, 0, 0, 0)
244
+ this.setLed(eye + 3, this._bri, 0, 0, 0)
241
245
  }
242
246
  await this.update()
243
247
  const delay = (eye <= 2)
package/lib/RpiInfo.js CHANGED
@@ -21,9 +21,8 @@ const fansPwm = [
21
21
  * - Retrieve the state through spawning `vcgencmd`.
22
22
  *
23
23
  * For remote Rapsberry Pi computers:
24
- * - Parse the contents of `/proc/cpuinfo` as returned through PigpioClient.
25
- * - Parse the state as returned by the `getState` script, called through
26
- * the PigpioClient.
24
+ * - Parse the contents of `/proc/cpuinfo`.
25
+ * - Parse the state as returned by the `getState` script.
27
26
  *
28
27
  * @extends EventEmitter
29
28
  * @see https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
package/lib/RpiTool.js CHANGED
@@ -21,7 +21,11 @@ const usage = {
21
21
  test: `${b('test')} [${b('-hns')}]`,
22
22
  led: `${b('led')} [${b('-h')}] [${b('on')}|${b('off')}]`,
23
23
  eventlog: `${b('eventlog')} [${b('-h')}] [${u('gpio')}...]`,
24
- ledchain: `${b('ledchain')} [${b('-h')}] [${b('-B')}|${b('-P')}] [${b('-c')} ${u('gpio')} ${b('-d')} ${u('gpio')} ${b('-n')} ${u('nLeds')}] [${b('-b')} ${u('brightness')}] [${u('mode')}]`
24
+ gpio: `${b('gpio')} [${b('-h')}] ${u('gpio')} [${b('high')}|${b('low')}]`,
25
+ dht: `${b('dht')} [${b('-h')}] ${u('gpio')}`,
26
+ ledchain: `${b('ledchain')} [${b('-h')}] [${b('-B')}|${b('-P')}] [${b('-c')} ${u('gpio')} ${b('-d')} ${u('gpio')} ${b('-n')} ${u('nLeds')}] [${b('-b')} ${u('brightness')}] [${u('mode')}]`,
27
+ pwm: `${b('pwm')} [${b('-h')}] ${u('gpio')} [${u('dutyCycle')}]`,
28
+ servo: `${b('servo')} [${b('-h')}] ${u('gpio')} [${u('pulseWidth')}]`
25
29
  }
26
30
 
27
31
  const description = {
@@ -29,8 +33,12 @@ const description = {
29
33
  info: 'Get Raspberry Pi properties.',
30
34
  state: 'Get Raspberry Pi state.',
31
35
  test: 'Repeatedly get Raspberry Pi state.',
32
- led: 'Get/set/clear power LED state.',
36
+ led: 'Read/write power LED state.',
33
37
  eventlog: 'Monitor GPIO state changes.',
38
+ gpio: 'Read/write GPIO state.',
39
+ pwm: 'Read/write PWM duty cycle.',
40
+ servo: 'Read/write servo pulse width.',
41
+ dht: 'Read DHTxx temperature/humidity sensor.',
34
42
  ledchain: 'Control Blinkt! or P9813 LED chain.'
35
43
  }
36
44
 
@@ -66,7 +74,7 @@ Parameters:
66
74
  ${b('-P')} ${u('password')}, ${b('--password=')}${u('password')}
67
75
  Authenticate to the ${b('rgpio')} daemon with ${u('password')}.
68
76
  Default is ${b('')} (empty).
69
- The password can also be set tgrough the environment variable ${b('LG_PASS')}.
77
+ The password can also be set through the environment variable ${b('LG_PASS')}.
70
78
 
71
79
  Commands:
72
80
  ${usage.info}
@@ -84,6 +92,18 @@ Commands:
84
92
  ${usage.eventlog}
85
93
  ${description.eventlog}
86
94
 
95
+ ${usage.gpio}
96
+ ${description.gpio}
97
+
98
+ ${usage.pwm}
99
+ ${description.pwm}
100
+
101
+ ${usage.servo}
102
+ ${description.servo}
103
+
104
+ ${usage.dht}
105
+ ${description.dht}
106
+
87
107
  ${usage.ledchain}
88
108
  ${description.ledchain}
89
109
 
@@ -128,6 +148,8 @@ Parameters:
128
148
  ${b('-s')}, ${b('--sortKeys')}
129
149
  Sort object key/value pairs alphabetically on key.`,
130
150
  led: `${description.led}
151
+ Note that this command only works on Raspberry Pi models
152
+ that support controlling the power LED, as reported by ${b('rpi info')}.
131
153
 
132
154
  Usage: ${b('rpi')} ${usage.led}
133
155
 
@@ -139,7 +161,10 @@ Parameters:
139
161
  Turn power LED on.
140
162
 
141
163
  ${b('off')}
142
- Turn power LED off.`,
164
+ Turn power LED off.
165
+
166
+ When neither ${b('on')} nor ${b('off')} is specified,
167
+ the current state of the power LED is reported.`,
143
168
  eventlog: `${description.eventlog}
144
169
 
145
170
  Usage: ${b('rpi')} ${usage.eventlog}
@@ -150,7 +175,69 @@ Paramerers:
150
175
 
151
176
  ${u('gpio')}
152
177
  Log events for GPIO ${u('gpio')}.
153
- Default: all user GPIOs on the Rapberry Pi model.`,
178
+ Default: all user GPIOs on the Rapberry Pi model.
179
+ Note that ${b('rgpio')} only report state changes to input GPIOs.`,
180
+ gpio: `${description.gpio}
181
+
182
+ Usage: ${b('rpi')} ${usage.gpio}
183
+
184
+ Paramerers:
185
+ ${b('-h')}, ${b('--help')}
186
+ Print this help and exit.
187
+
188
+ ${u('gpio')}
189
+ Read or control GPIO ${u('gpio')}.
190
+
191
+ ${b('high')}
192
+ Set GPIO high.
193
+
194
+ ${b('low')}
195
+ Set GPIO low.
196
+
197
+ When neither ${b('high')} nor ${b('low')} is specified,
198
+ the current state of the GPIO is reported.`,
199
+ pwm: `${description.pwm}
200
+
201
+ Usage: ${b('rpi')} ${usage.pwm}
202
+
203
+ Paramerers:
204
+ ${b('-h')}, ${b('--help')}
205
+ Print this help and exit.
206
+
207
+ ${u('gpio')}
208
+ Read or control GPIO ${u('gpio')}.
209
+
210
+ ${u('dutyCycle')}
211
+ Set PWM duty cycle to ${u('dutyCycle')} (between 0% and 100%).
212
+
213
+ When no duty cycle is specified, the current duty clycle of the GPIO is reported.
214
+ Note that ${b('rgpio')} doesn't support reading the duty cycle.`,
215
+ servo: `${description.servo}
216
+
217
+ Usage: ${b('rpi')} ${usage.servo}
218
+
219
+ Paramerers:
220
+ ${b('-h')}, ${b('--help')}
221
+ Print this help and exit.
222
+
223
+ ${u('gpio')}
224
+ Read or control GPIO ${u('gpio')}.
225
+
226
+ ${u('pulseWidth')}
227
+ Set servo pulse width to ${u('pulseWidth')} (between 500 and 2500, or 0 for off).
228
+
229
+ When no pulse width is specified, the current pulse width of the GPIO is reported.
230
+ Note that ${b('rgpio')} doesn't support reading the pulse width.`,
231
+ dht: `${description.dht}
232
+
233
+ Usage: ${b('rpi')} ${usage.dht}
234
+
235
+ Paramerers:
236
+ ${b('-h')}, ${b('--help')}
237
+ Print this help and exit.
238
+
239
+ ${u('gpio')}
240
+ GPIO pin for DHTxx sensor.`,
154
241
  ledchain: `${description.ledchain}
155
242
 
156
243
  Usage: ${b('rpi')} ${usage.ledchain}
@@ -455,10 +542,143 @@ class RpiTool extends CommandLineTool {
455
542
  )
456
543
  })
457
544
  }
458
- await this.pi.listen(mask === 0 ? gpioMask : mask)
545
+ this.pi.mask = mask === 0 ? gpioMask : mask
546
+ await this.pi.listen()
459
547
  await new Promise(() => {})
460
548
  }
461
549
 
550
+ async gpio (...args) {
551
+ const clargs = {}
552
+ const parser = new CommandLineParser(this.pkgJson)
553
+ parser
554
+ .help('h', 'help', this.help)
555
+ .parameter('gpio', (value) => {
556
+ clargs.gpio = OptionParser.toInt('gpio', value)
557
+ })
558
+ .remaining((value) => {
559
+ if (value.length > 1) {
560
+ throw new UsageError('too many parameters')
561
+ }
562
+ if (value.length === 1) {
563
+ if (value[0] !== 'high' && value[0] !== 'low') {
564
+ throw new UsageError(`${value[0]}: unknown state`)
565
+ }
566
+ clargs.value = value[0] === 'high' ? 1 : 0
567
+ }
568
+ })
569
+ .parse(...args)
570
+ const { gpioMask, model } = await this._getInfo()
571
+ const bit = 1 << clargs.gpio
572
+ if ((bit & gpioMask) === 0) {
573
+ throw new UsageError(`gpio: GPIO ${clargs.gpio}: not available on Raspberry Pi ${model}`)
574
+ }
575
+ if (clargs.value != null) {
576
+ await this.pi.write(clargs.gpio, clargs.value)
577
+ }
578
+ const value = await this.pi.read(clargs.gpio)
579
+ this.print(value ? 'high' : 'low')
580
+ }
581
+
582
+ async pwm (...args) {
583
+ const clargs = {}
584
+ const parser = new CommandLineParser(this.pkgJson)
585
+ parser
586
+ .help('h', 'help', this.help)
587
+ .parameter('gpio', (value) => {
588
+ clargs.gpio = OptionParser.toInt('gpio', value)
589
+ })
590
+ .remaining((value) => {
591
+ if (value.length > 1) {
592
+ throw new UsageError('too many parameters')
593
+ }
594
+ if (value.length === 1) {
595
+ clargs.value = OptionParser.toInt('dutyCycle', value[0], 0, 100)
596
+ }
597
+ })
598
+ .parse(...args)
599
+ const { gpioMask, model } = await this._getInfo()
600
+ const bit = 1 << clargs.gpio
601
+ if ((bit & gpioMask) === 0) {
602
+ throw new UsageError(`gpio: GPIO ${clargs.gpio}: not available on Raspberry Pi ${model}`)
603
+ }
604
+ if (clargs.value != null) {
605
+ await this.pi.writePwm(clargs.gpio, clargs.value)
606
+ }
607
+ if (this.pi.port === 8888) {
608
+ const value = Math.round((await this.pi.command(
609
+ this.pi.commands.GDC, clargs.gpio
610
+ )).status / 2.55)
611
+ this.print(value)
612
+ } else if (clargs.value == null) {
613
+ this.warn('reading of duty cycle not supported by rgpio')
614
+ } else {
615
+ this.print(clargs.value)
616
+ }
617
+ }
618
+
619
+ async servo (...args) {
620
+ const clargs = {}
621
+ const parser = new CommandLineParser(this.pkgJson)
622
+ parser
623
+ .help('h', 'help', this.help)
624
+ .parameter('gpio', (value) => {
625
+ clargs.gpio = OptionParser.toInt('gpio', value)
626
+ })
627
+ .remaining((value) => {
628
+ if (value.length > 1) {
629
+ throw new UsageError('too many parameters')
630
+ }
631
+ if (value.length === 1) {
632
+ clargs.value = OptionParser.toInt('pulseWidth', value[0], 0)
633
+ if (clargs.value !== 0) {
634
+ clargs.value = OptionParser.toInt('pulseWidth', value[0], 500, 2500)
635
+ }
636
+ }
637
+ })
638
+ .parse(...args)
639
+ const { gpioMask, model } = await this._getInfo()
640
+ const bit = 1 << clargs.gpio
641
+ if ((bit & gpioMask) === 0) {
642
+ throw new UsageError(`gpio: GPIO ${clargs.gpio}: not available on Raspberry Pi ${model}`)
643
+ }
644
+ if (clargs.value != null) {
645
+ await this.pi.writeServo(clargs.gpio, clargs.value)
646
+ }
647
+ if (this.pi.port === 8888) {
648
+ const value = (await this.pi.command(this.pi.commands.GPW, clargs.gpio)).status
649
+ this.print(value)
650
+ } else if (clargs.value == null) {
651
+ this.warn('reading of pulse width not supported by rgpio')
652
+ } else {
653
+ this.print(clargs.value)
654
+ }
655
+ }
656
+
657
+ async dht (...args) {
658
+ const clargs = {}
659
+ const parser = new CommandLineParser(this.pkgJson)
660
+ parser
661
+ .help('h', 'help', this.help)
662
+ .parameter('gpio', (value) => {
663
+ clargs.gpio = OptionParser.toInt('gpio', value)
664
+ })
665
+ .parse(...args)
666
+ const { gpioMask, model } = await this._getInfo()
667
+ const bit = 1 << clargs.gpio
668
+ if ((bit & gpioMask) === 0) {
669
+ throw new UsageError(`gpio: GPIO ${clargs.gpio}: not available on Raspberry Pi ${model}`)
670
+ }
671
+ this.pi
672
+ .on('listen', (mask) => { this.debug('listening for %s', this.pi.vmap(mask)) })
673
+ const { GpioDhtClient } = await import('../lib/GpioDhtClient.js')
674
+ const dht = new GpioDhtClient(this, this.pi, clargs.gpio)
675
+ this.pi.mask = 1 << clargs.gpio
676
+ await this.pi.listen()
677
+ const { temperature, humidity } = await dht.read()
678
+ this.print('temperature: %dº', temperature)
679
+ this.print('humidity: %d%%', humidity)
680
+ }
681
+
462
682
  async ledchain (...args) {
463
683
  const clargs = {
464
684
  mode: 'cylon',
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "hb-rpi-tools",
3
3
  "description": "Homebridge RPi Tools",
4
4
  "license": "Apache-2.0",
5
- "version": "0.0.2",
5
+ "version": "0.0.3",
6
6
  "keywords": [
7
7
  "raspberrypi",
8
8
  "raspberry",