8

I need to listen to the raw commands/keypresses that a bluetooth keyboard sends to my device and if possible, prevent them from 'propagating' to the rest of the system.

Basically, I've written something with Node.js and coffee-script that receives keypresses from stdin and controls my Philips Hue lightbulbs. It looks something like this:

keypress = require 'keypress'

# Setup keypress events
keypress process.stdin

process.stdin.on 'keypress', (character, key) ->

    switch character
        when 'l' then hue.decreaseTemp()
        when 'r' then hue.increaseTemp()
        when 'u' then hue.increaseBri()
        when 'd' then hue.decreaseBri()
        when 'b' then hue.turnOff()

    # Exit on ctrl-c
    if key?.ctrl and key.name is 'c'
        process.stdin.pause()

It's functionality works, but it's not very useful as it receives input from stdin, preventing it from running in the background.

What could I do to make this receive input without the window having focus?

My preference is for something in Node.js or Python to run on my Mac, but I'm willing to switch languages or run on my Raspberry Pi if need be

Community
  • 1
  • 1
Josh Hunt
  • 14,225
  • 26
  • 79
  • 98
  • 1
    How exactly are you listening to the keypress events? You need to explain what you're actually using and provide some code – Ian Aug 31 '14 at 06:46
  • 1
    @ian I'm listening to input from stdin using [keypress](https://www.npmjs.org/package/keypress), which fails to receive input (obviously) once the terminal window the script looses focus. – Josh Hunt Aug 31 '14 at 08:58
  • What do you mean by running in background. You will have to focus on the window to direct input to it, it works like any other program. – user568109 Sep 03 '14 at 04:44
  • I mean I don't want the window to have focus for the program to receive input. I understand I can't receive stdin input unless it has focus, so that can change, but I just need to find something else to make it work. – Josh Hunt Sep 03 '14 at 10:17
  • What you're saying, essentially, is that you're connecting your keyboard via bluetooth, and then when you type (assuming your program is running and in focus) it executes the command to control something - and what you want, is to be able to use the keyboard to control it without having to have the terminal in focus, right? – Etai Sep 04 '14 at 18:42
  • Correct. Sorry for being unclear. It would be awesome if nothing could be in focus, and I could listen to key presses from just that one particular bluetooth device, but I understand that probably isn't possible. – Josh Hunt Sep 04 '14 at 22:54
  • Maybe the easiest way to explain this is by looking at something similar: there are plenty of media-player-applications around that can sit in the background but still react to the Play/FFwd/Volume+/etc.. keys that are on the keyboard. How do they do that without having focus? (I've been wondering myself =) As such, maybe http://stackoverflow.com/search?q=listen+to+media-keys can shed some light to the issue... (although it seems most questions are unanswered. – deroby Sep 09 '14 at 07:55

2 Answers2

5

keypress only listens to the standard input stream, not the keyboard itself. This input stream is handled by operating system and its hardware drivers. Usually the OS would not want applications to listen to keyboard directly and rather direct the keyboard events to the program it has on focus.

You would have to handle the device directly, otherwise OS will redirect those inputs to the other program in focus. You should try node-hid for this. It can access attached Human Interface devices like keyboard/mouse. Description says it works for USB devices, but it should work for bluetooth(HID) devices.

Secondly since you are listening to hardware, most likely you won't recieve keypress value directly, but a bunch of raw-input data/signals which need to be interpreted. You are using your keyboard as a remote control, be prepared to use it like a low-level device.

user568109
  • 47,225
  • 17
  • 99
  • 123
  • Yup - I expect that I won't get fancy things like characters coming through, but only raw values. I have about 5 buttons I press, so I'm fine with that. – Josh Hunt Sep 05 '14 at 07:08
  • Hmmm I gave node-hid a try and I could only get it to steal the trackpad on my mac - it wouldn't connect/listen to the bluetooth remote. It put me on the right track though – Josh Hunt Sep 09 '14 at 04:37
  • 1
    @DavidPearce Looks like bluetooth won't work for node-hid. If you have a Bluetooth Low Energy (BLE)/Bluetooth 4.0 keyboard, you can try https://github.com/sandeepmistry/noble. You would also need a service LightBlue to access your device. See more about it [here](https://github.com/sandeepmistry/noble/issues/15) – user568109 Sep 09 '14 at 05:31
1

One way to solve this problem (control the hue without needing the program to be in the foreground) would be to split the hue control and keyboard shortcuts to different apps:

I would simply write a command line tool eg. with node, which takes as an argument the command to run. Then I would create OS level keyboard shortcuts for the command.

Eg. I would configure Command-Shift-+ to call huecontrol increasebri. Huecontrol would do is thing and exit.

OlliM
  • 7,023
  • 1
  • 36
  • 47
  • I believe the point was to change the colors as he's typing on purpose. (Sounds like it would look awesome...) – gabeio Sep 08 '14 at 17:52
  • 1
    Yes - Ideally I was to listen to the raw data from a bluetooth keyboard. I'm using a Roku remote which is like a Bluetooth keyboard http://7554xysb4c4dxy7u.zippykid.netdna-cdn.com/wp-content/uploads/2011/07/roku-bluetooth-remote-448x600.jpg e.g. the up button types the letter 'u'. I would like to read input directly from the keyboard, rather than `stdin` – Josh Hunt Sep 09 '14 at 04:39
  • Ok if the point is to change colors as you type, you have to actually listen to the keyboard, hotkeys won't work. I just wanted to point out one way to work around the problem. – OlliM Sep 09 '14 at 08:00
  • Read you comment more carefully and now I get it. You could still use hotkeys and a command line script if you use something like [Autohotkey](http://www.autohotkey.com) or one of the [OS X alternatives](http://alternativeto.net/software/autohotkey/?platform=mac) to map the simple letter 'u' from the Roku keyboard to the desired action. A little hacky, but you're not trying to write commercial software, just solve your own problem. – OlliM Sep 09 '14 at 08:09