Kiwi
Pimoroni Keybow based, WiFi-enabled Macro Pad (a.k.a. poor-man's Elgato Stream Deck)
Install / Use
/learn @mrusme/KiwiREADME
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!

Requirements
- 2.4 GHz WiFi
- Pimoroni Keybow
- microSD card
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(whereSDCARD_DEVICEis 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 namedkiwi.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_SOCKETwith 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_1key_2_in_row_1key_3_in_row_1key_1_in_row_2key_2_in_row_2key_3_in_row_2key_1_in_row_3key_2_in_row_3key_3_in_row_3key_1_in_row_4key_2_in_row_4key_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' \
