Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

OpenAction

Welcome!

OpenAction is a platform-agnostic, language-agnostic, device-agnostic open WebSocket-based API for providing actions to an OpenAction server for execution on device events such as key presses or dial rotations.

OpenAction is cross-compatible with the Stream Deck SDK, bringing a plethora of excellent plugins to the platform.

This website contains documentation for developers of both plugins and servers.

Architecture

OpenAction is an event-driven API that communicates over WebSocket.

Plugins provide actions, which can be instantiated by users on multiple profiles across multiple devices simultaneously. Each action instance is created from the properties specified in the plugin manifest, after which its states and settings can be mutated and these changes retained.

Each action may also be accompanied by a property inspector, a user interface displayed when the action is selected, where the user may customise the behaviour of the action. The setSettings, getSettings, setGlobalSettings, and getGlobalSettings events may be used by both the plugin and property inspector.

Users may also configure "Multi Actions", where multiple actions are executed in sequence.

Events are represented in (stringified) JSON format, with a field to identify the event and an optional payload containing more information about the event, as well as an instance context if the event is instance-related in order to identify it.

For more information about a specific event, consult the clientbound events and serverbound events pages.

Manifest

Your plugin should contain a manifest.json file that supplies key information about your plugin to the OpenAction server. It should be present in the root of your plugin directory.

{
	// The human-readable name of your plugin. Required
	Name: string,
	// The user-facing author string (e.g. "ninjadev64"). Required
	Author: string,
	// The version of your plugin found in this directory. Required
	Version: string,
	// An icon to represent your plugin, relative to your plugin root. Required
	// This icon should be provided in PNG format, without the ".png" suffix. You may also provide @2x versions of this image.
	Icon: string,
	// The category for your plugin's actions to appear under.
	Category: string = "Custom",
	// The default path to your actions' property inspector.
	PropertyInspectorPath: string | null,
	// The actions provided by your plugin. Required
	Actions: [
		{
			// The name of this action. Required
			Name: string,
			// A unique identifier for this action. Required
			UUID: string,
			// A tooltip that sums up the purpose of this action.
			Tooltip: string = "",
			// An icon to represent this action, relative to your plugin root. Required if visible in action list
			// This icon should be provided in PNG format, without the ".png" suffix. You may also provide @2x versions of this image.
			Icon: string,
			// Whether or not to automatically toggle the state of this action on key up. Only applies to actions with two states.
			DisableAutomaticStates: boolean = false,
			// Whether or not this action should be visible in the action list.
			VisibleInActionsList: boolean = true,
			// Whether or not this action should be supported in Multi Actions.
			SupportedInMultiActions: boolean = true,
			// The path to this action's property inspector, if different to your plugin's default.
			PropertyInspectorPath: string = "<plugin default>",
			// The controllers this action should be supported on. Supported controllers are "Keypad" and "Encoder" (dials/sliders).
			Controllers: string[] = [ "Keypad" ],
			// The states that are part of this action. Required
			States: [
				{
					// The image of this state relative to your plugin root or "actionDefaultImage".
					Image: string = "actionDefaultImage",
					// The name of this state.
					Name: string = "",
					// The text to display on this state over the image.
					Title: string = "",
					// Whether or not to display the title over the image.
					ShowTitle: boolean = true,
					// The colour of the state title.
					TitleColor: string = "<server dependent>",
					// The vertical alignment of the state title, either "top", "middle", or "bottom".
					TitleAlignment: string = "middle",
					// The font style of the title, either "Regular", "Bold", "Italic", or "Bold Italic".
					FontStyle: string = "Regular",
					// The font size of the state title in pixels as rendered on a 72x72px state image.
					FontSize: string = "16",
					// Whether or not to underline the state title.
					FontUnderline: boolean = false
				}
			]
		}
	],
	// The operating systems your plugin is supported on. Required
	OS: [
		{
			// The platform in question. Can be "windows", "mac", or "linux". Note that "linux" is not supported by Stream Deck. Required
			Platform: string,
			// The minimum supported version of the platform in question.
			Version: string | null
		}
	],
	// The default path to your plugin executable file, relative to your plugin root.
	// HTML5 is supported if this value ends with the ".html" suffix, and Node.js if this value ends with any of ".js", ".cjs" and ".mjs".
	CodePath: string | null,
	// An override for CodePath on Windows.
	CodePathWin: string | null,
	// An override for CodePath on macOS.
	CodePathMac: string | null,
	// An override for CodePath on Linux.
	CodePathLin: string | null
}

Registration

The OpenAction server will start your plugin with arguments specifying the means of initialising the WebSocket connection. If you use a plugin SDK, such as openaction-rs, you may be able to skip these steps.

Compiled plugin registration

Your plugin will be called with the following command-line argument format.

yourplugin -port <port> -pluginUUID <uuid> -registerEvent <event> -info <info>

Your plugin should initiate a WebSocket connection to the WebSocket server running on the specified port and send a registration event containing the supplied registration event and plugin UUID, similar to the procedure outlined for HTML5 plugins described below.

HTML5 plugin registration

Your plugin should provide a function similar to the below to register the plugin with the OpenAction server. This function will be called automatically by the OpenAction server.

function connectOpenActionSocket(port, pluginUUID, registerEvent, info) {
	const websocket = new WebSocket("ws://localhost:" + port);

	websocket.onopen = () => {
		websocket.send(JSON.stringify({
			"event": registerEvent,
			"uuid": pluginUUID
		}));
	};

	websocket.onmessage = (event) => {
		// Handle inbound events from the OpenAction server here
	};
}

// For Stream Deck compatibility
const connectElgatoStreamDeckSocket = connectOpenActionSocket;

Property inspector registration

Your property inspectors should provide functions similar to the below to register themselves with the OpenAction server. These functions will be called automatically by the OpenAction server.

function connectOpenActionSocket(port, propertyInspectorUUID, registerEvent, info) {
	const websocket = new WebSocket("ws://localhost:" + port);

	websocket.onopen = () => {
		websocket.send(JSON.stringify({
			"event": registerEvent,
			"uuid": propertyInspectorUUID
		}));
	};

	websocket.onmessage = (event) => {
		// Handle inbound events from the OpenAction server here
	};
}

// For Stream Deck compatibility
const connectElgatoStreamDeckSocket = connectOpenActionSocket;

Info parameter

The info parameter supplied to both plugins and property inspectors is in the below format.

{
	application: {
		font: string,
		language: string, // e.g. "en"
		platform: string, // e.g. "mac"
		platformVersion: string, // e.g. "11.6.2"
		version: string // e.g. "OpenDeck 2.0.0"
	},
	plugin: {
		uuid: string, // e.g. "com.amansprojects.starterpack"
		version: string // e.g. "1.0.0"
	},
	devices: [
		{
			id: string,
			name: string,
			size: {
				rows: number,
				columns: number
			}
		}
	]
}

The Stream Deck software supplies additional fields in this parameter, such as an integer to designate the model of Stream Deck in use.

Clientbound events

This chapter describes the events that can be sent by the OpenAction server to either plugins or property inspectors.

Devices

deviceDidConnect

Fired when a device is connected.

The Stream Deck software supplies an additional field, an integer to designate the model of Stream Deck in use.

Received by: Plugin

{
	event: string = "deviceDidConnect",
	device: string,
	deviceInfo: {
		name: string,
		size: {
			rows: number,
			columns: number
		}
	}
}

deviceDidDisconnect

Fired when a device is disconnected.

The Stream Deck software supplies an additional field, an integer to designate the model of Stream Deck in use.

Received by: Plugin

{
	event: string = "deviceDidDisconnect",
	device: string
}

Encoder

dialRotate

Fired on encoder dial rotate or encoder slider move.

Received by: Plugin

{
	event: string = "dialRotate",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		controller: string,
		// For a dial, positive value signifies clockwise rotation, and a negative value signifies anticlockwise rotation.
		// The lowest position is set as 0, and highest position is set as 192.
		ticks: number,
		pressed: boolean
	}
}

dialDown

Fired on encoder dial down.

Received by: Plugin

{
	event: string = "dialDown",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		controller: string
	}
}

dialUp

Fired on encoder dial up.

Received by: Plugin

{
	event: string = "dialUp",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		controller: string
	}
}

Keypad

keyDown

Fired on keypad key down.

Received by: Plugin

{
	event: string = "keyDown",
	// The action UUID supplied in the plugin manifest.
	// Utilise to determine which action was triggered.
	action: string,
	// A unique value to identify the instance.
	context: string,
	// A unique value to identify the device.
	device: string,
	payload: {
		// Instance settings as set using the `setSettings` event.
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		// The currently active state of this instance.
		state: number,
		// Whether or not this event was triggered as part of a Multi Action.
		isInMultiAction: boolean
	}
}

keyUp

Fired on keypad key up.

Received by: Plugin

{
	event: string = "keyUp",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		state: number,
		isInMultiAction: boolean
	}
}

Property inspector

sendToPlugin

Fired when the property inspector uses the sendToPlugin event.

Received by: Plugin

{
	event: string = "sendToPlugin",
	action: string,
	context: string,
	payload: any
}

sendToPropertyInspector

Fired when the plugin uses the sendToPropertyInspector event.

Received by: Property inspector

{
	event: string = "sendToPropertyInspector",
	action: string,
	context: string,
	payload: any
}

propertyInspectorDidAppear

Fired when an action is selected and its property inspector appears.

Received by: Plugin

{
	event: string = "propertyInspectorDidAppear",
	action: string,
	context: string,
	device: string
}

propertyInspectorDidDisappear

Fired when an action is deselected and its property inspector disappears.

Received by: Plugin

{
	event: string = "propertyInspectorDidDisappear",
	action: string,
	context: string,
	device: string
}

Settings

didReceiveSettings

Fired in response to the getSettings event. Additionally fired to the plugin when the property inspector uses setSettings, and vice versa.

Received by: Plugin, Property inspector

{
	event: string = "didReceiveSettings",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		isInMultiAction: boolean
	}
}

didReceiveGlobalSettings

Fired in response to the getGlobalSettings event. Additionally fired to the plugin when the property inspector uses setGlobalSettings, and vice versa.

Received by: Plugin, Property inspector

{
	event: string = "didReceiveGlobalSettings",
	payload: {
		settings: any
	}
}

States

titleParametersDidChange

Fired when the user changes the title parameters of an action.

{
	event: string = "titleParametersDidChange",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		state: number,
		title: string,
		titleParameters: {
			fontFamily: string,
			fontSize: number,
			fontStyle: string,
			fontUnderline: boolean,
			showTitle: boolean,
			titleAlignment: string,
			titleColor: string
		}
	}
}

Will appear

willAppear

Fired when the user switches to a profile containing this action, or a new instance of this action is created.

Received by: Plugin

{
	event: string = "willAppear",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		controller: string,
		state: number,
		isInMultiAction: boolean
	}
}

willDisappear

Fired when the user switches from a profile containing this action, or an instance of this action is removed.

Received by: Plugin

{
	event: string = "willDisappear",
	action: string,
	context: string,
	device: string,
	payload: {
		settings: any,
		coordinates: {
			row: number,
			column: number
		},
		controller: string,
		state: number,
		isInMultiAction: boolean
	}
}

Serverbound events

This chapter describes the events that can be sent by either plugins or property inspectors to the OpenAction server.

Miscellaneous

openUrl

Used to open a fully-qualified URL in the user's default browser.

Sent by: Plugin, Property inspector

{
	event: string = "openUrl",
	payload: {
		url: string // e.g. "https://example.com/"
	}
}

logMessage

Used to log a debug message to a log file. It is more strongly advised for plugin developers to handle logging on their own.

Sent by: Plugin

{
	event: string = "logMessage",
	payload: {
		message: string
	}
}

showAlert

Used to show a temporary alert indicator on the instance.

Sent by: Plugin

{
	event: string = "showAlert",
	context: string
}

showOk

Used to show a temporary checkmark indicator on the instance.

Sent by: Plugin

{
	event: string = "showOk",
	context: string
}

Property inspector

sendToPlugin

Fired by a property inspector to send a message to the plugin.

Sent by: Property inspector

{
	event: string = "sendToPlugin",
	action: string,
	context: string,
	payload: any
}

sendToPropertyInspector

Fired by the plugin to send a message to a property inspector.

Sent by: Plugin

{
	event: string = "sendToPropertyInspector",
	action: string,
	context: string,
	payload: any
}

Settings

setSettings

Used to set the settings value of an instance. When used by the plugin, the property inspector will receive a didReceiveSettings event, and vice versa.

Sent by: Plugin, Property inspector

{
	event: string = "setSettings",
	// A unique value to identify the instance.
	context: string,
	payload: any
}

getSettings

Used to get the settings value of an instance. When used, the OpenAction server will respond with a didReceiveSettings event.

Sent by: Plugin, Property inspector

{
	event: string = "getSettings",
	context: string
}

setGlobalSettings

Used to set the plugin-wide global settings value. When used by the plugin, all property inspectors will receive a didReceiveSettings event, and vice versa.

Sent by: Plugin, Property inspector

{
	event: string = "setGlobalSettings",
	payload: any
}

getGlobalSettings

Used to get the plugin-wide global settings value. When used, the OpenAction server will respond with a didReceiveSettings event.

Sent by: Plugin, Property inspector

{
	event: string = "getGlobalSettings"
}

States

setTitle

Used to set the title of an instance.

Sent by: Plugin

{
	event: string = "setTitle",
	context: string,
	payload: {
		title: string,
		// 0: Both hardware and software, 1: Hardware only, 2: Software only
		target: number = 0,
		// 0-based index specifying the state to be modified.
		// If not set, the title will be applied to all states.
		state: number | null
	}
}

setImage

Used to set the image of an instance.

Sent by: Plugin

{
	event: string = "setImage",
	context: string,
	payload: {
		// A base-64 data URL encoded image.
		image: string,
		// 0: Both hardware and software, 1: Hardware only, 2: Software only
		target: number = 0,
		// 0-based index specifying the state to be modified.
		// If not set, the image will be applied to all states.
		state: number | null
	}
}

setState

Used to switch an action to a state.

Sent by: Plugin

{
	event: string = "logMessage",
	payload: {
		// 0-based index specifying the state to be switched to.
		state: number
	}
}