ne-room-digital-signage-contracts 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # signage-contracts
2
+
3
+ Single source of truth for the Digital Signage platform contracts:
4
+
5
+ - **REST**: OpenAPI (`openapi/admin-api.yaml`)
6
+ - **Device MQTT** (AWS IoT Core): AsyncAPI (`asyncapi/device-mqtt.yaml`)
7
+ - **Admin WebSocket events**: AsyncAPI (`asyncapi/admin-ws.yaml`)
8
+ - **JSON Schemas** for message validation (`schemas/**`)
9
+ - TypeScript exports (`src/**`)
10
+
11
+ ## MQTT topic conventions
12
+
13
+ - Commands to device: `t/{tenantId}/d/{deviceId}/cmd`
14
+ - Acks from device: `t/{tenantId}/d/{deviceId}/ack`
15
+ - Telemetry from device: `t/{tenantId}/d/{deviceId}/telemetry`
16
+
17
+ ## Envelope rules (mandatory)
18
+
19
+ - Every command has `commandId` (UUID), `type`, `issuedAt`, optional `expiresAt`, optional `desiredVersion`
20
+ - Every ack references `commandId` and includes `status` + timestamp
21
+ - Telemetry must be lightweight; large payloads go over HTTPS (manifests/assets)
22
+
23
+ ## Next steps
24
+
25
+ - Add CI validation (OpenAPI lint, AsyncAPI lint, JSON Schema validation)
26
+ - Add codegen (TS types from JSON Schemas/OpenAPI) using your preferred toolchain
@@ -0,0 +1,24 @@
1
+ asyncapi: 2.6.0
2
+ info:
3
+ title: Admin WebSocket Events
4
+ version: 0.1.0
5
+ description: Server-to-admin events over WebSockets for live operations dashboards.
6
+ servers:
7
+ wsServer:
8
+ url: wss://ws.example.com
9
+ protocol: wss
10
+ channels:
11
+ tenant/{tenantId}/events:
12
+ parameters:
13
+ tenantId: { schema: { type: string } }
14
+ subscribe:
15
+ summary: Tenant-scoped event stream
16
+ message:
17
+ $ref: "#/components/messages/AdminWsEvent"
18
+
19
+ components:
20
+ messages:
21
+ AdminWsEvent:
22
+ name: AdminWsEvent
23
+ payload:
24
+ $ref: "../schemas/admin/ws_events.json"
@@ -0,0 +1,53 @@
1
+ asyncapi: 2.6.0
2
+ info:
3
+ title: Device MQTT Protocol (AWS IoT Core)
4
+ version: 0.1.0
5
+ description: >
6
+ Devices connect to AWS IoT Core. Commands are published to devices; devices publish telemetry and acknowledgements.
7
+ servers:
8
+ awsIot:
9
+ url: your-iot-endpoint.amazonaws.com
10
+ protocol: mqtt
11
+ description: AWS IoT Core MQTT endpoint
12
+ channels:
13
+ t/{tenantId}/d/{deviceId}/cmd:
14
+ parameters:
15
+ tenantId: { schema: { type: string } }
16
+ deviceId: { schema: { type: string } }
17
+ publish:
18
+ summary: Command to device
19
+ message:
20
+ $ref: "#/components/messages/DeviceCommand"
21
+
22
+ t/{tenantId}/d/{deviceId}/ack:
23
+ parameters:
24
+ tenantId: { schema: { type: string } }
25
+ deviceId: { schema: { type: string } }
26
+ subscribe:
27
+ summary: Ack from device
28
+ message:
29
+ $ref: "#/components/messages/DeviceCommandAck"
30
+
31
+ t/{tenantId}/d/{deviceId}/telemetry:
32
+ parameters:
33
+ tenantId: { schema: { type: string } }
34
+ deviceId: { schema: { type: string } }
35
+ subscribe:
36
+ summary: Telemetry from device
37
+ message:
38
+ $ref: "#/components/messages/DeviceTelemetry"
39
+
40
+ components:
41
+ messages:
42
+ DeviceCommand:
43
+ name: DeviceCommand
44
+ payload:
45
+ $ref: "../schemas/device/command.json"
46
+ DeviceCommandAck:
47
+ name: DeviceCommandAck
48
+ payload:
49
+ $ref: "../schemas/device/ack.json"
50
+ DeviceTelemetry:
51
+ name: DeviceTelemetry
52
+ payload:
53
+ $ref: "../schemas/device/telemetry.json"
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "AdminWsEvent",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "type",
9
+ "timestamp",
10
+ "payload"
11
+ ],
12
+ "properties": {
13
+ "tenantId": {
14
+ "type": "string"
15
+ },
16
+ "type": {
17
+ "type": "string",
18
+ "enum": [
19
+ "DEVICE_ONLINE_CHANGED",
20
+ "DEVICE_TELEMETRY_UPDATED",
21
+ "ALERT_RAISED",
22
+ "ALERT_RESOLVED",
23
+ "PUBLISH_PROGRESS",
24
+ "PUBLISH_COMPLETED"
25
+ ]
26
+ },
27
+ "timestamp": {
28
+ "type": "string",
29
+ "format": "date-time"
30
+ },
31
+ "payload": {
32
+ "type": "object"
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DeviceCommandAck",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "deviceId",
9
+ "commandId",
10
+ "status",
11
+ "timestamp"
12
+ ],
13
+ "properties": {
14
+ "tenantId": {
15
+ "type": "string",
16
+ "minLength": 1
17
+ },
18
+ "deviceId": {
19
+ "type": "string",
20
+ "minLength": 1
21
+ },
22
+ "commandId": {
23
+ "type": "string",
24
+ "minLength": 16
25
+ },
26
+ "status": {
27
+ "type": "string",
28
+ "enum": [
29
+ "ACCEPTED",
30
+ "COMPLETED",
31
+ "FAILED",
32
+ "REJECTED",
33
+ "EXPIRED"
34
+ ]
35
+ },
36
+ "timestamp": {
37
+ "type": "string",
38
+ "format": "date-time"
39
+ },
40
+ "message": {
41
+ "type": "string"
42
+ },
43
+ "details": {
44
+ "type": "object"
45
+ },
46
+ "deviceAppVersion": {
47
+ "type": "string"
48
+ },
49
+ "deviceOsVersion": {
50
+ "type": "string"
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DeviceCommand",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "deviceId",
9
+ "commandId",
10
+ "type",
11
+ "issuedAt"
12
+ ],
13
+ "properties": {
14
+ "tenantId": {
15
+ "type": "string",
16
+ "minLength": 1
17
+ },
18
+ "deviceId": {
19
+ "type": "string",
20
+ "minLength": 1
21
+ },
22
+ "commandId": {
23
+ "type": "string",
24
+ "minLength": 16
25
+ },
26
+ "type": {
27
+ "type": "string",
28
+ "enum": [
29
+ "RELOAD_MANIFEST",
30
+ "REBOOT_APP",
31
+ "REBOOT_DEVICE",
32
+ "CLEAR_CACHE",
33
+ "SET_VOLUME",
34
+ "SET_BRIGHTNESS",
35
+ "CAPTURE_SCREENSHOT",
36
+ "PING"
37
+ ]
38
+ },
39
+ "issuedAt": {
40
+ "type": "string",
41
+ "format": "date-time"
42
+ },
43
+ "expiresAt": {
44
+ "type": "string",
45
+ "format": "date-time"
46
+ },
47
+ "desiredVersion": {
48
+ "type": "string"
49
+ },
50
+ "payload": {
51
+ "type": "object"
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DeviceManifestPointer",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "deviceId",
9
+ "manifestVersion",
10
+ "manifestUrl",
11
+ "generatedAt"
12
+ ],
13
+ "properties": {
14
+ "tenantId": {
15
+ "type": "string"
16
+ },
17
+ "deviceId": {
18
+ "type": "string"
19
+ },
20
+ "manifestVersion": {
21
+ "type": "string"
22
+ },
23
+ "manifestUrl": {
24
+ "type": "string",
25
+ "format": "uri"
26
+ },
27
+ "generatedAt": {
28
+ "type": "string",
29
+ "format": "date-time"
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "ProofOfPlayEvent",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "deviceId",
9
+ "eventId",
10
+ "assetId",
11
+ "startedAt",
12
+ "outcome"
13
+ ],
14
+ "properties": {
15
+ "tenantId": {
16
+ "type": "string"
17
+ },
18
+ "deviceId": {
19
+ "type": "string"
20
+ },
21
+ "eventId": {
22
+ "type": "string",
23
+ "minLength": 16
24
+ },
25
+ "assetId": {
26
+ "type": "string"
27
+ },
28
+ "playlistId": {
29
+ "type": "string"
30
+ },
31
+ "scheduleId": {
32
+ "type": "string"
33
+ },
34
+ "startedAt": {
35
+ "type": "string",
36
+ "format": "date-time"
37
+ },
38
+ "endedAt": {
39
+ "type": "string",
40
+ "format": "date-time"
41
+ },
42
+ "durationMs": {
43
+ "type": "integer",
44
+ "minimum": 0
45
+ },
46
+ "outcome": {
47
+ "type": "string",
48
+ "enum": [
49
+ "PLAYED",
50
+ "SKIPPED",
51
+ "FAILED"
52
+ ]
53
+ },
54
+ "failureReason": {
55
+ "type": "string"
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,138 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DeviceTelemetry",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "tenantId",
8
+ "deviceId",
9
+ "timestamp",
10
+ "online",
11
+ "health"
12
+ ],
13
+ "properties": {
14
+ "tenantId": {
15
+ "type": "string",
16
+ "minLength": 1
17
+ },
18
+ "deviceId": {
19
+ "type": "string",
20
+ "minLength": 1
21
+ },
22
+ "timestamp": {
23
+ "type": "string",
24
+ "format": "date-time"
25
+ },
26
+ "online": {
27
+ "type": "boolean"
28
+ },
29
+ "health": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "properties": {
33
+ "cpuPct": {
34
+ "type": "number",
35
+ "minimum": 0,
36
+ "maximum": 100
37
+ },
38
+ "memPct": {
39
+ "type": "number",
40
+ "minimum": 0,
41
+ "maximum": 100
42
+ },
43
+ "diskFreeBytes": {
44
+ "type": "integer",
45
+ "minimum": 0
46
+ },
47
+ "diskTotalBytes": {
48
+ "type": "integer",
49
+ "minimum": 0
50
+ },
51
+ "tempC": {
52
+ "type": "number"
53
+ }
54
+ }
55
+ },
56
+ "playback": {
57
+ "type": "object",
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "state": {
61
+ "type": "string",
62
+ "enum": [
63
+ "PLAYING",
64
+ "IDLE",
65
+ "ERROR"
66
+ ]
67
+ },
68
+ "currentAssetId": {
69
+ "type": "string"
70
+ },
71
+ "currentPlaylistId": {
72
+ "type": "string"
73
+ },
74
+ "currentScheduleId": {
75
+ "type": "string"
76
+ }
77
+ }
78
+ },
79
+ "network": {
80
+ "type": "object",
81
+ "additionalProperties": false,
82
+ "properties": {
83
+ "type": {
84
+ "type": "string",
85
+ "enum": [
86
+ "WIFI",
87
+ "ETHERNET",
88
+ "CELLULAR",
89
+ "UNKNOWN"
90
+ ]
91
+ },
92
+ "rssi": {
93
+ "type": "integer"
94
+ }
95
+ }
96
+ },
97
+ "app": {
98
+ "type": "object",
99
+ "additionalProperties": false,
100
+ "properties": {
101
+ "version": {
102
+ "type": "string"
103
+ },
104
+ "build": {
105
+ "type": "string"
106
+ }
107
+ }
108
+ },
109
+ "errors": {
110
+ "type": "array",
111
+ "items": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "required": [
115
+ "code",
116
+ "message",
117
+ "severity"
118
+ ],
119
+ "properties": {
120
+ "code": {
121
+ "type": "string"
122
+ },
123
+ "message": {
124
+ "type": "string"
125
+ },
126
+ "severity": {
127
+ "type": "string",
128
+ "enum": [
129
+ "INFO",
130
+ "WARN",
131
+ "ERROR"
132
+ ]
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }