PepperDash.Essentials.Plugins.OptiSigns.GraphQL
1.0.0
dotnet add package PepperDash.Essentials.Plugins.OptiSigns.GraphQL --version 1.0.0
NuGet\Install-Package PepperDash.Essentials.Plugins.OptiSigns.GraphQL -Version 1.0.0
<PackageReference Include="PepperDash.Essentials.Plugins.OptiSigns.GraphQL" Version="1.0.0" />
<PackageVersion Include="PepperDash.Essentials.Plugins.OptiSigns.GraphQL" Version="1.0.0" />
<PackageReference Include="PepperDash.Essentials.Plugins.OptiSigns.GraphQL" />
paket add PepperDash.Essentials.Plugins.OptiSigns.GraphQL --version 1.0.0
#r "nuget: PepperDash.Essentials.Plugins.OptiSigns.GraphQL, 1.0.0"
#:package PepperDash.Essentials.Plugins.OptiSigns.GraphQL@1.0.0
#addin nuget:?package=PepperDash.Essentials.Plugins.OptiSigns.GraphQL&version=1.0.0
#tool nuget:?package=PepperDash.Essentials.Plugins.OptiSigns.GraphQL&version=1.0.0
OptiSigns GraphQL Plugin
Overview
This plugin integrates PepperDash Essentials with the OptiSigns digital signage platform via its GraphQL API. It targets PepperDash Essentials 2.x (net472, Crestron 4-Series) and provides control panel-style operations mapped to the OptiSigns cloud API.
The plugin uses a server/player architecture:
- Server: Manages the shared API connection, device discovery, and creates player devices
- Players: Individual screen controllers, each independently bridgeable
API Details
| Item | Value |
|---|---|
| Type | GraphQL |
| Endpoint | https://graphql-gateway.optisigns.com/graphql |
| Authentication | Authorization: Bearer {apiKey} |
| Format | HTTP POST, application/json |
Feature Mapping
| Control Surface Operation | OptiSigns API Action |
|---|---|
| Playlist select | pushToScreens — pushes selected playlist immediately (type: "NOW") |
| Poll device status | devices query — refreshes currentType, status, lastHeartBeat |
| Poll playlist list | playlists query — refreshes labels for input selection |
| Device discovery | devices query — lists all devices in the OptiSigns account |
Note:
pushToScreensand theplaylistslist query are Phase 2 features in the official OptiSigns TypeScript SDK. This plugin calls those GraphQL mutations and queries directly. Ifplaylistsis not yet live on the backend, the plugin silently falls back to the staticplaylistslist in the device config.
Essentials Device Configuration
The plugin uses a server/player model. Configure one server device with an array of players. Each player targets a specific OptiSigns screen.
The deviceId is the MongoDB _id of the OptiSigns screen. Obtain it by calling listAllDevices in the OptiSigns SDK, using device discovery via the server bridge, or from the OptiSigns web app device settings. The teamId and apiKey are found in your OptiSigns account settings at https://app.optisigns.com/account-setting.
{
"key": "optisignServer",
"name": "OptiSigns Server",
"type": "optiSigns",
"group": "signage",
"uid": 1,
"properties": {
"apiKey": "YOUR_OPTISIGNS_API_KEY_HERE",
"pollIntervalMs": 30000,
"playlistPollIntervalMs": 300000,
"players": [
{
"key": "player1",
"name": "Lobby Display",
"deviceId": "YOUR_OPTISIGNS_SCREEN_DEVICE_ID_HERE",
"teamId": "YOUR_TEAM_ID_HERE",
"playlists": [
{ "id": "PLAYLIST_ID_1", "name": "Welcome Loop" },
{ "id": "PLAYLIST_ID_2", "name": "Event Content" },
{ "id": "PLAYLIST_ID_3", "name": "Emergency Messaging" }
]
},
{
"key": "player2",
"name": "Conference Room Display",
"deviceId": "ANOTHER_DEVICE_ID",
"teamId": "YOUR_TEAM_ID_HERE"
}
]
}
}
Server Properties Reference
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey |
string | Yes | — | OptiSigns API key (Bearer token), shared across all players |
pollIntervalMs |
int | No | 30000 |
Device status poll interval in ms, applied to all players |
playlistPollIntervalMs |
int | No | 300000 |
Playlist list refresh interval in ms, applied to all players |
players |
array | Yes | — | Array of player configurations (at least one required) |
Player Properties Reference
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
key |
string | Yes | — | Unique key for this player (combined with server key to form device key) |
name |
string | No | — | Display name for the player (falls back to API name, then device key) |
deviceId |
string | Yes | — | MongoDB _id of the target OptiSigns screen |
teamId |
string | Yes | — | OptiSigns team ID, required in all mutations |
playlists |
array | No | [] |
Static fallback playlist list; used when the API playlists query is unavailable |
Essentials Bridging
The server and each player are independently bridgeable. Player device keys are formed as {serverKey}-{playerKey}.
{
"key": "devices-io-bridge",
"name": "Devices IO Bridge",
"type": "eiscApiAdvanced",
"group": "api",
"uid": 2,
"properties": {
"control": {
"method": "ipidTcp",
"ipid": "A7",
"tcpSshProperties": {
"address": "127.0.0.2",
"port": 0
}
},
"devices": [
{ "deviceKey": "optisignServer", "joinStart": 401 },
{ "deviceKey": "optisignServer-player1", "joinStart": 451 },
{ "deviceKey": "optisignServer-player2", "joinStart": 501 }
]
}
}
Server Bridge Join Map
Join numbers below are relative to joinStart.
Digitals
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Is Online fb | |
| Fetch Devices (pulse) | 2 | Is Fetching fb |
| Page First (pulse) | 3 | |
| Page Next (pulse) | 4 | |
| Page Previous (pulse) | 5 |
Analogs
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Configured Player Count fb | |
| 2 | Discovered Device Count fb |
Serials
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Server Name fb | |
| 11 | Discovered Device[1] fb (JSON: {"id":"...","name":"...","status":"..."}) |
|
| 12 | Discovered Device[2] fb | |
| … | … | |
| 40 | Discovered Device[30] fb |
Server Join Notes
- D2 FetchDevices — Pulse to trigger device discovery from the OptiSigns API. Results populate S11–S40.
- D3–D5 Pagination — Navigate through discovered devices when there are more than 30. Page First returns to the beginning; Page Next/Previous advance or retreat by 30 devices.
- A2 DiscoveredDeviceCount — Total number of devices discovered (not limited to 30).
- S11–S40 DiscoveredDevice[N] — JSON object for each discovered device containing
id,name,status,uuid,pairingCode,currentType, andcurrentPlaylistId.
Player Bridge Join Map
Join numbers below are relative to joinStart.
Digitals
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Is Online fb | |
| Poll Now (pulse) | 2 | Is Polling fb |
| Page First (pulse) | 3 | |
| Page Next (pulse) | 4 | |
| Page Previous (pulse) | 5 | |
| Playlist Item As JSON (toggle) | 6 |
Analogs
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Device Status fb (0=Unknown, 1=ONLINE, 2=SLEEP, 3=OFFLINE) | |
| 5 | Playlist Count fb (total count) | |
| Select Playlist by Absolute Index (1-based) | 6 | Current Playlist Absolute Index fb |
| Select Playlist by Relative Index (1-based) | 7 | Current Playlist Relative Index fb (on page) |
Serials
| Input (From SIMPL) | Join | Output (To SIMPL) |
|---|---|---|
| 1 | Device Name fb | |
| 2 | Last HeartBeat fb (ISO 8601) | |
| Select Playlist by ID | 6 | Current Playlist Name fb |
| 11 | Playlist Item[1] fb (JSON or name only, see D6) | |
| 12 | Playlist Item[2] fb | |
| … | … | |
| 40 | Playlist Item[30] fb |
Player Digital Join Notes
- D2 PollNow — Pulse to trigger an immediate device status and playlist poll.
- D3–D5 Pagination — Navigate through playlists when there are more than 30. Page First returns to the beginning.
- D6 PlaylistItemAsJsonObject — Controls the format of playlist items on S11–S40:
- High (default): JSON format
{"id":"...","name":"..."} - Low: Name only
- High (default): JSON format
Player Analog Join Notes
- A1 DeviceStatus — Maps the raw OptiSigns API status string to an analog value:
0= Unknown,1= ONLINE,2= SLEEP,3= OFFLINE. - A5 PlaylistCount — Total number of playlists available (not limited to 30).
- A6 SelectPlaylistByAbsoluteIndex — 1-based index into the entire playlist list, ignoring pagination. Send from SIMPL to select; feedback reflects the current active playlist's absolute position.
0= no playlist active or unknown. - A7 SelectPlaylistByRelativeIndex — 1-based index relative to the current page. On page 2 (offset 30), sending
5selects playlist 35. Feedback shows the current playlist's position on the visible page, or0if the current playlist is not on this page.
Player Serial Join Notes
S1 DeviceName — Priority: API device name → config
nameproperty → device key.S6 SelectPlaylistById / CurrentPlaylistName — Shared join: send a raw OptiSigns playlist
_idstring from SIMPL to select it immediately without needing to resolve its index. Feedback returns the name of the currently active playlist. Useful for config-driven or event-triggered room logic.S11–S40 PlaylistItem[N] — Playlist data for each slot. Format controlled by D6:
- JSON:
{"id":"PGTWJ42a3rw7yN8YR","name":"Main Lobby"} - Pipe:
1|PGTWJ42a3rw7yN8YR|Main Lobby
Slots beyond the current page are sent as empty strings.
- JSON:
Polling Behavior
Two independent timers run after Initialize() for each player:
| Timer | Default Interval | What It Does |
|---|---|---|
| Status poll | 30s (pollIntervalMs) |
Queries device currentType, status, lastHeartBeat |
| Playlist poll | 5min (playlistPollIntervalMs) |
Refreshes the available playlist list and updates S11–S40, A5, A6, and A7 feedback |
The status poll starts 2 seconds after initialization to let the playlist poll complete first. After a playlist select command, a one-shot confirmation poll fires 2 seconds later to reconcile optimistic UI state with the actual API response.
The device is marked offline after 3 consecutive status poll failures. It comes back online on the next successful poll.
DEVJSON Commands
Update programIndex and deviceKey to match your environment. Player device keys are {serverKey}-{playerKey}.
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SelectPlaylistByAbsoluteIndex", "params":[1]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SelectPlaylistByAbsoluteIndex", "params":[5]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SelectPlaylistByRelativeIndex", "params":[1]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SelectPlaylistByRelativeIndex", "params":[3]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SelectPlaylistById", "params":["YOUR_PLAYLIST_ID_HERE"]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"PollNow", "params":[]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SetPlaylistItemJsonFormat", "params":[true]}
devjson:1 {"deviceKey":"optisignServer-player1", "methodName":"SetPlaylistItemJsonFormat", "params":[false]}
devjson:1 {"deviceKey":"optisignServer", "methodName":"FetchDevices", "params":[]}
Build
Requires .NET SDK 6.0 or later (for SDK-style project support on the build host; the output targets net472).
dotnet build src/epi-optisigns-graphql.4Series.csproj
The post-build target zips the output to:
output/epi-optisigns-graphql.4Series.{version}.cplz
Deploy the .cplz to the Crestron 4-Series processor using the Crestron Toolbox Send to Processor tool or progload via SSH.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net472 is compatible. net48 was computed. net481 was computed. |
-
.NETFramework 4.7.2
- PepperDashEssentials (>= 2.24.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 32 | 9/21/2026 |
| 1.0.0-release-full-release.2 | 26 | 9/21/2026 |
| 1.0.0-release-full-release.1 | 29 | 9/21/2026 |
| 1.0.0-initial-development.31 | 79 | 5/19/2026 |
| 1.0.0-initial-development.30 | 69 | 5/19/2026 |
| 1.0.0-initial-development.29 | 71 | 5/1/2026 |
| 1.0.0-initial-development.28 | 74 | 4/16/2026 |
| 1.0.0-initial-development.27 | 77 | 4/16/2026 |
| 1.0.0-initial-development.26 | 78 | 4/16/2026 |
| 1.0.0-initial-development.25 | 68 | 4/16/2026 |
| 1.0.0-initial-development.24 | 76 | 4/16/2026 |
| 1.0.0-initial-development.23 | 72 | 4/16/2026 |
| 1.0.0-initial-development.22 | 82 | 3/14/2026 |
| 1.0.0-initial-development.21 | 79 | 3/14/2026 |
| 1.0.0-initial-development.20 | 71 | 3/13/2026 |
| 1.0.0-initial-development.19 | 70 | 3/13/2026 |
| 1.0.0-initial-development.18 | 67 | 3/13/2026 |
| 1.0.0-initial-development.17 | 72 | 3/13/2026 |
| 1.0.0-initial-development.16 | 71 | 3/13/2026 |
| 1.0.0-initial-development.15 | 69 | 3/13/2026 |