Integration with Elgato StreamDeck.
This is a fork of erh:viam-streamdeck that adds response-driven page switching: when a key press or dial turn issues a DoCommand to another component, the Stream Deck waits for the response and, if it contains a "mode" field, automatically switches to the page named by that value. See Response-driven page switching.
{
"brightness" : 100, // 0 -> 100"keys": [
{
"text": "The",
"key": 0,
"color" : "purple",
"component": "foo",
"method": "do_command",
"args": [ {
"x ": 1
} ]
}
]
}{
"brightness" : 100, // 0 -> 100"keys": [
{
"text": "The",
"text_font": "NotoEmoji-Regular.tff"
}
]
}Currently only NotoEmoji-Regular.tff is included with the module. You can load additional fonts as an asset if desired. Note that rendering is limited to a small character set within hte font. This is a known limitation of the freetype library's DrawString() method that is used. Cahracters outside the Basic Multilingual Plane (BMP) (characters above U+FFFF) cannot be rendered. If this is needed, use images instead.
{
"brightness":100,
"assets":{
"fonts":[
"/absolute/path/to/custom-font.ttf",
"/Users/yourname/.fonts"
],
"images":[
"/absolute/path/to/custom-image.jpg",
"/Users/yourname/images"
]
},
"keys":[
{
"key":0,
"component":"my-component",
"method":"do_command",
"text":"Custom",
"text_font":"custom-font.ttf",
"image":"logo.png"
}
]
}You can add your own external fonts and images to use througout your configuration. Fonts must be in .ttf or .otf. Images can be .jpg, .jpeg, .png or .gif. Images stopsign.jpg and x.jpg is included and can also be used without an external asset.
The update_display DoCommand allows you to dynamically update the Stream Deck display at runtime. This is useful for changing key appearances, updating brightness, or modifying dial configurations without restarting the component.
{
"update_display": {
"brightness": 75
}
}Changes the Stream Deck brightness to 75% (accepts values 0-100).
You can update individual keys by specifying the key number and the properties to change. The update merges with the existing configuration, so you only need to specify the properties you want to change.
{
"update_display": {
"keys": {
"0": {
"text": "New Text",
"color": "blue"
},
"1": {
"text": "Status: OK",
"text_color": "green",
"image": "checkmark.png"
}
}
}
}Available key properties:
text- Text to display on the keytext_color- Color of the text (e.g., "red", "blue", "#FF0000")color- Background color of the keyimage- Image file to display (must be in assets)component- Component to call when key is pressedmethod- Method to call on the componentargs- Array of arguments to pass to the method
For Stream Decks with dials (like the Stream Deck+), you can update dial configurations:
{
"update_display": {
"dials": {
"0": {
"component": "my-motor",
"command": "set_power"
}
}
}
}Available dial properties:
component- Component to call when dial is turnedcommand- Command to execute on the component
{
"dials": [
{
"dial": 0,
"component": "foo",
"command": "SetPosition"
}
]
}You can update multiple aspects in a single DoCommand:
{
"update_display": {
"brightness": 80,
"keys": {
"0": {
"text": "Active",
"color": "green"
},
"2": {
"text": "Inactive",
"color": "gray"
}
},
"dials": {
"0": {
"component": "volume-control",
"command": "set_level"
}
}
}
}The DoCommand returns a map indicating what was updated:
{
"brightness": 80,
"keys": [0, 2],
"dials": [0]
}Keys can reference the Stream Deck component itself by using the component's own name. This allows keys to trigger DoCommands that update the display dynamically:
{
"keys": [
{
"key": 0,
"text": "Toggle",
"component": "my-streamdeck",
"method": "do_command",
"args": [
{
"update_display": {
"keys": {
"1": {
"text": "Updated!",
"color": "yellow"
}
}
}
}
]
}
]
}Instead of a flat list of keys, you can organize keys into named pages and switch between them at runtime using set_page. Use initial_page to set which page is displayed on startup. Keys can navigate between pages by referencing the Stream Deck component itself and calling set_page.
{
"brightness": 100,
"initial_page": "main",
"pages": {
"main": [
{
"key": 0,
"text": "Go to other",
"color": "blue",
"component": "my-streamdeck",
"method": "do_command",
"args": [{ "set_page": "other" }]
},
{
"key": 1,
"text": "Hello",
"component": "foo",
"method": "do_command",
"args": [{ "x": 1 }]
}
],
"other": [
{
"key": 0,
"text": "Back",
"color": "red",
"component": "my-streamdeck",
"method": "do_command",
"args": [{ "set_page": "main" }]
},
{
"key": 1,
"text": "Do thing",
"component": "bar",
"method": "do_command",
"args": [{ "y": 2 }]
}
]
}
}You cannot use keys and pages at the same time.
When a key (do_command) or dial (DoCommand) sends a command to another component, the Stream Deck waits for the response and inspects it for a "mode" field. If present and a non-empty string, the deck switches to the page of that name — exactly as if set_page had been called on itself.
This lets a separate module own the navigation logic: the deck sends it a command, the module decides what should be shown next, and replies with the page to display.
{
"brightness": 100,
"initial_page": "menu",
"pages": {
"menu": [
{
"key": 0,
"text": "Play",
"component": "chess-logic",
"method": "do_command",
"args": [{ "action": "start_game" }]
}
],
"board": [
{
"key": 0,
"text": "Resign",
"component": "chess-logic",
"method": "do_command",
"args": [{ "action": "resign" }]
}
]
}
}In the example above, pressing Play sends {"action": "start_game"} to the chess-logic component. If chess-logic replies with {"mode": "board"}, the deck automatically switches to the board page.
Behavior notes:
- The check is automatic for every
do_commandkey and dial — no extra config flag. - If the response has no
"mode"field (or it is not a non-empty string), nothing changes. - If
"mode"names a page that does not exist, or the config uses flatkeysinstead ofpages, a warning is logged and the button press is still considered successful.
This is a simple streamdeck app for picking things up
{
"brightness" : 100, // optional, 0 -> 100"arm" : "...",
"gripper" : "...",
"finder" : "...", // vision service that supports GetObjectPointClouds"motion" : "...", // motion service, could be 'builtin'"watch_pose" : "...", // an arm-saver position from where to watch
}