SkillAgentSearch skills...

Kiwi

Pimoroni Keybow based, WiFi-enabled Macro Pad (a.k.a. poor-man's Elgato Stream Deck)

Install / Use

/learn @mrusme/Kiwi

README

Kiwi

<img src="https://xn--gckvb8fzb.com/images/chatroom.png" width="275">

Kiwi – Keyboard Interface for Wireless Interaction – is a Nerves-based firmware for Pimoroni Keybow that transforms the device into a powerful wireless (WiFi) controller for Philips Hue, IFTTT, OBS and everything else that has an HTTP API!

With Kiwi, you can turn your Pimoroni Keybow into a poor-man's Elgato Stream Deck!

Kiwi

Requirements

Installation

  • Download the latest firmware (kiwi.tar.gz) from the releases page and unpack it it: tar -xzf kiwi.tar.gz
  • Insert the microSD card into the card reader of your computer
  • Raw-copy the firmware to your microSD card, e.g. using dd: sudo dd bs=1m if=./kiwi.fw of=/dev/SDCARD_DEVICE (where SDCARD_DEVICE is your microSD card, e.g. /dev/rdisk3)
  • If your computer did not automatically mount a partition (BOOT-A) from the microSD card after the copy has finished, eject the card and plug it back in
  • Open the folder of your mounted partition (BOOT-A) and create a file named kiwi.txt (small caps, no spaces) with the following content.
  • Adjust the SSID, the PSK (and the KEY_MGMT) values according to your WiFi configuration
  • If you want to control OBS from Kiwi, fill NERVES_NETWORK_OBS_SOCKET with the URL to the OBS web-socket, otherwise remove the whole line
  • Save the file and unmount the partition
  • Insert the microSD card into your Keybow and connect it to a power source
  • Check your WiFi access point's web-interface to find out the IP address that was assigned to your Keybow

Configuration

As soon as you found the IP you can start configuring the device via its API.

API

The Kiwi API is accessible via http://10.10.10.10:8080/ (where 10.10.10.10 is the IP address of the Keybow on your WiFi). Check out the full OpenAPI 3 specification!

Note: All example API calls in this documentation are being performed using curl, as it's available for the majority of platforms.

Endpoint: Settings

The Kiwi API provides a /settings endpoint for configuring each individual key.

GET /settings

Retrieve a list of all currently configured settings (e.g. for backing up your current configuration).

curl "http://10.10.10.10:8080/settings" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{}'

POST /settings

Bulk upsert endpoint, allows upserting a list of settings (e.g. for recovery of a backup). This endpoint can be used for importing a backed-up configuration.

curl -X "POST" "http://10.10.10.10:8080/settings" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
          "settings": [
            {
              "id": "key_1_in_row_1",
              "object": {
                "keydown": {
                  "http": [

                    ...

                  ]
                }
              }
            },
            {
              "id": "animation_main",
              "object": {
                "frames": [

                    ...

                ]
              }
            }
          ]
        }'

GET /settings/keys

Retrieve a list of all currently configured keys.

curl "http://10.10.10.10:8080/settings/keys" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{}'

GET /settings/keys/:key

Retrieve the current configuration for a specific key.

curl "http://10.10.10.10:8080/settings/keys/key_1_in_row_1" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{}'

POST /settings/keys/:key

:key can be one of the following values:

  • key_1_in_row_1
  • key_2_in_row_1
  • key_3_in_row_1
  • key_1_in_row_2
  • key_2_in_row_2
  • key_3_in_row_2
  • key_1_in_row_3
  • key_2_in_row_3
  • key_3_in_row_3
  • key_1_in_row_4
  • key_2_in_row_4
  • key_3_in_row_4

The key names relate to the position of the key on the Keybow when the device is in front of you with the Keybow label in the top right corner and the pimoroni.com/keybow url on the bottom right:

                                             Keybow
╔════════════════╦════════════════╦════════════════╗
║                ║                ║                ║
║                ║                ║                ║
║ key_1_in_row_1 ║ key_2_in_row_1 ║ key_3_in_row_1 ║
║                ║                ║                ║
║                ║                ║                ║
╠════════════════╬════════════════╬════════════════╣
║                ║                ║                ║
║                ║                ║                ║
║ key_1_in_row_2 ║ key_2_in_row_2 ║ key_3_in_row_2 ║
║                ║                ║                ║
║                ║                ║                ║
╠════════════════╬════════════════╬════════════════╣
║                ║                ║                ║
║                ║                ║                ║
║ key_1_in_row_3 ║ key_2_in_row_3 ║ key_3_in_row_3 ║
║                ║                ║                ║
║                ║                ║                ║
╠════════════════╬════════════════╬════════════════╣
║                ║                ║                ║
║                ║                ║                ║
║ key_1_in_row_4 ║ key_2_in_row_4 ║ key_3_in_row_4 ║
║                ║                ║                ║
║                ║                ║                ║
╚════════════════╩════════════════╩════════════════╝
                                pimoroni.com/keybow
HTTP actions

HTTP actions allow you to run arbitrary HTTP requests (GET, PUT, POST, DELETE) in order to control basically everything that provides a more or less sane HTTP API, like IoT devices or web services.

Let's have a look at an example:

In order to configure the first key of the first row to perform a HTTP post to IFTTT's Maker Webhooks (click Documentation on that site) when it's pressed (down), run the following command:

curl -X POST "http://10.10.10.10:8080/settings/keys/key_1_in_row_1" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d $'{
          "object": {
            "keydown": {
              "http": [
                {
                  "body": "{}",
                  "method": "post",
                  "headers": {
                    "content-type": "application/json"
                  },
                  "url": "https://maker.ifttt.com/trigger/key_1_in_row_1/with/key/your-ifttt-key-here"
                }
              ]
            }
          }
        }'

As soon as the curl command returns with HTTP status code 200 OK the key was set up and its configuration stored to the Keybow's internal storage (which is the microSD card, of course). You can now press the key (the first one on the top left) to run the HTTP call.

However, you might have noticed, that the http property is not simply an object but rather an array containing objects. This allows you to define multiple HTTP actions to run with the press of a single button. In order to do so, simply add another HTTP request object to the http array:

curl -X POST "http://10.10.10.10:8080/settings/keys/key_1_in_row_1" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d $'{
          "object": {
            "keydown": {
              "http": [
                {
                  "body": "{}",
                  "method": "post",
                  "headers": {
                    "content-type": "application/json"
                  },
                  "url": "https://maker.ifttt.com/trigger/turn_lights_off/with/key/your-ifttt-key-here"
                },
                {
                  "body": "{}",
                  "method": "post",
                  "headers": {
                    "content-type": "application/json"
                  },
                  "url": "https://maker.ifttt.com/trigger/power_on_television/with/key/your-ifttt-key-here"
                }
              ]
            }
          }
        }'

The HTTP requests defined within the http array are being run one after another (in the order defined within the array, from top to bottom) and not in parallel. This means that the second request waits for the first one to complete until it executes. Also keep in mind that, as of right now, subsequent requests don't care about their prior request's return status and will run no matter what.

Scripted HTTP actions (advanced topic)

Now that we've learned how HTTP requests work and that we can have multiple requests running one after another, we can dive deeper into how HTTP requests can be scripted.

Let's assume, you would like one button to trigger an API that turns a lightbulb on or off. The API accepts a boolean value as the lightbulb's state, with true being on, false being off. Now, in order to program a single button to trigger the lightbulb on and off with each keypress, you need to have a dynamic value within your request's body, that changes, depending on the current state of the lightbulb. This state could be retrieved inside a separate HTTP GET request that runs prior to the one updating the lightbulb's status.

Kiwi allows you to do just this. Let's have a look on how such a http definition could look like for a Philips Hue connected lightbulb:

curl -X "POST" "http://10.10.10.10:8080/settings/keys/key_1_in_row_1" \
     -H 'Content-Type: application/json; charset=utf-8' \
     
View on GitHub
GitHub Stars66
CategoryDevelopment
Updated3mo ago
Forks6

Languages

Elixir

Security Score

97/100

Audited on Dec 24, 2025

No findings