Open Stream Deck

Протокол

Сообщения между плагином и приложением: события хоста, команды плагина и жесты.

Сообщения в обе стороны это JSON-объекты с полем type. Неизвестные поля и типы игнорируются, поэтому протокол расширяется без смены версии. Каждое событие от хоста содержит now: монотонное время с запуска плагина в миллисекундах.

context это непрозрачный идентификатор экземпляра действия на конкретной кнопке. Он стабилен, пока действие стоит на этой кнопке этого профиля.

События хоста

ТипПоляКогда
initplugin { id, version }, app { version, os, language }, device, globalsПервое событие после запуска
devicedeviceУстройство подключили, отключили или сменили
languagelanguageПользователь сменил язык интерфейса
appearcontext, action, controller, position { column, row }, settings, stateДействие появилось на видимой странице
disappearcontext, actionДействие ушло со страницы или его удалили
keyDown, keyUpcontext, action, settings, stateНажатие и отпускание кнопки
tapто жеОтпускание без долгого нажатия и удержания, см. жесты
longPressто жеДолгое нажатие
holdStart, holdRepeat, holdEndто же, count или durationУдержание
settingscontext, action, settingsНастройки экземпляра изменил пользователь
globalssettingsОбщие настройки плагина изменились вне плагина
inspectorOpen, inspectorClosecontext, actionОткрыта или закрыта страница настроек кнопки
inspectorMessagecontext, action, payloadСообщение со страницы настроек кнопки
settingsPageOpen, settingsPageCloseнетОткрыто или закрыто окно настроек плагина
settingsPageMessagepayloadСообщение из окна настроек плагина
timeridСработал таймер setTimer
httpResponseid, status, headers, body или errorОтвет на http
wsOpen, wsMessage, wsCloseid, data или reasonСобытия сокета wsOpen
appStatusid, installed, processes [{ pid, args }]Ответ на appStatus
doneid, errorРезультат appLaunch, appQuit, clipboard
deniedid, messageОперация запрещена: нет разрешения или согласия

device:

{
  "id": "OSD153R00001",
  "name": "AJAZZ AKP153R",
  "connected": true,
  "keys": { "columns": 5, "rows": 3, "width": 103, "height": 103 },
  "side": { "slots": 3, "width": 85, "height": 103 }
}

Команды плагина

ТипПоляДействие
setTitlecontext, title, styleПодпись. null возвращает подпись из манифеста. style как у title в манифесте
setImagecontext, imageКартинка: путь внутри пакета или data:image/(png|jpeg|webp|svg+xml);base64,…. null возвращает картинку из манифеста
setStatecontext, stateНомер состояния
flashcontext, kindКороткая отметка ok или alert поверх кнопки
setSettingscontext, settingsСохранить настройки экземпляра
setGlobalssettingsСохранить общие настройки плагина
toInspectorcontext, payloadСообщение странице настроек кнопки, если она открыта
toSettingsPagepayloadСообщение окну настроек плагина, если оно открыто
loglevel, messageЗапись в журнал плагина: debug, info, warn, error
openUrlurlОткрыть ссылку https:// в браузере. Работает в течение 3 секунд после действия пользователя с этим плагином
setTimerid, ms, repeatТаймер для WASM. Повторный id заменяет таймер
clearTimeridОтменить таймер
httpid, url, method, headers, body, timeoutHTTP-запрос, см. разрешения
wsOpenid, urlОткрыть WebSocket
wsSendid, dataОтправить текст
wsCloseidЗакрыть сокет
appStatusid, appУстановлено ли приложение и запущено ли
appLaunchid, app, argsЗапустить приложение. args это числа для шаблонов {0}..{9}
appQuitid, appВежливо закрыть приложение
clipboardid, textЗаписать текст в буфер обмена

Команда с чужим или исчезнувшим context отбрасывается без ошибки: это обычная гонка между disappear и обновлением кнопки.

Жесты

Хост считает жесты сам. keyDown и keyUp приходят всегда, tap приходит при отпускании любой кнопки. longPress и удержание работают для действий, которые объявили gestures.

ПараметрЧто делает
long_pressЧерез столько миллисекунд удержания приходит longPress, кнопка ещё нажата
holdЧерез столько миллисекунд приходит holdStart, при отпускании holdEnd с duration
repeatПока идёт удержание, каждые столько миллисекунд приходит holdRepeat с count от 1. Требует hold, не меньше 50

tap приходит при отпускании, если до этого не было ни longPress, ни holdStart. Так кнопка с удержанием никогда не получает лишний tap после перемотки. Если исчезает действие или устройство, удержание завершается holdEnd без tap.

Версии

  • sdk в манифесте меняется только при несовместимых изменениях протокола.
  • format_version в индексе меняется при несовместимых изменениях формата пакета.
  • opensd_abi() меняется при несовместимых изменениях ABI.

Новые события, команды и поля добавляются без смены этих номеров.