diff --git a/edge-apps/edge-apps-library/README.md b/edge-apps/edge-apps-library/README.md index 3618f6311..96f9e9ff3 100644 --- a/edge-apps/edge-apps-library/README.md +++ b/edge-apps/edge-apps-library/README.md @@ -59,7 +59,8 @@ signalReady() ### Metadata - `getMetadata()` - Get all screen metadata -- `getScreenName()`, `getHostname()`, `getLocation()`, `getHardware()`, `getScreenlyVersion()`, `getTags()`, `hasTag(tag)`, `getFormattedCoordinates()` +- `getScreenName()`, `getHostname()`, `getLocation()`, `getScreenlyVersion()`, `getTags()`, `hasTag(tag)`, `getFormattedCoordinates()` +- `getHardware()` - Get hardware type as `Hardware` enum (`Anywhere`, `RaspberryPi`, or `ScreenlyPlayerMax`) ### Location & Localization @@ -125,6 +126,7 @@ afterEach(() => { ```typescript import type { + Hardware, ScreenlyMetadata, ScreenlySettings, ScreenlyObject, diff --git a/edge-apps/edge-apps-library/src/types/index.ts b/edge-apps/edge-apps-library/src/types/index.ts index 272340e9e..831bc123f 100644 --- a/edge-apps/edge-apps-library/src/types/index.ts +++ b/edge-apps/edge-apps-library/src/types/index.ts @@ -1,3 +1,12 @@ +/** + * Hardware types for Screenly devices + */ +export enum Hardware { + Anywhere = 'Anywhere', + RaspberryPi = 'RaspberryPi', + ScreenlyPlayerMax = 'ScreenlyPlayerMax', +} + /** * Screenly metadata provided by the Edge Apps runtime */ @@ -5,7 +14,7 @@ export interface ScreenlyMetadata { /** GPS coordinates [latitude, longitude] */ coordinates: [number, number] /** Hardware identifier */ - hardware: string + hardware: string | undefined /** Device hostname */ hostname: string /** Physical location description */ diff --git a/edge-apps/edge-apps-library/src/utils/metadata.test.ts b/edge-apps/edge-apps-library/src/utils/metadata.test.ts index c570d8cab..0b2880076 100644 --- a/edge-apps/edge-apps-library/src/utils/metadata.test.ts +++ b/edge-apps/edge-apps-library/src/utils/metadata.test.ts @@ -10,6 +10,7 @@ import { getTags, hasTag, } from './metadata' +import { Hardware } from '../types/index.js' import { setupScreenlyMock, resetScreenlyMock } from '../test/mock' describe('metadata utilities', () => { @@ -18,7 +19,7 @@ describe('metadata utilities', () => { coordinates: [37.3861, -122.0839], hostname: 'test-host', location: 'Test Location', - hardware: 'Raspberry Pi 4', + hardware: 'Raspberry Pi', screenly_version: '1.2.3', screen_name: 'Main Screen', tags: ['lobby', 'reception', 'main'], @@ -36,7 +37,7 @@ describe('metadata utilities', () => { coordinates: [37.3861, -122.0839], hostname: 'test-host', location: 'Test Location', - hardware: 'Raspberry Pi 4', + hardware: 'Raspberry Pi', screenly_version: '1.2.3', screen_name: 'Main Screen', tags: ['lobby', 'reception', 'main'], @@ -70,8 +71,49 @@ describe('metadata utilities', () => { }) describe('getHardware', () => { - test('should return hardware', () => { - expect(getHardware()).toBe('Raspberry Pi 4') + test('should return RaspberryPi enum value', () => { + expect(getHardware()).toBe(Hardware.RaspberryPi) + }) + + test('should return Anywhere enum value when hardware is undefined', () => { + setupScreenlyMock({ + coordinates: [37.3861, -122.0839], + hostname: 'test-host', + location: 'Test Location', + hardware: undefined, + screenly_version: '1.2.3', + screen_name: 'Main Screen', + tags: [], + }) + expect(getHardware()).toBe(Hardware.Anywhere) + }) + + test('should return ScreenlyPlayerMax enum value for Screenly Player Max hardware', () => { + setupScreenlyMock({ + coordinates: [37.3861, -122.0839], + hostname: 'test-host', + location: 'Test Location', + hardware: 'Screenly Player Max', + screenly_version: '1.2.3', + screen_name: 'Main Screen', + tags: [], + }) + expect(getHardware()).toBe(Hardware.ScreenlyPlayerMax) + }) + + test('should throw error for unknown hardware type', () => { + setupScreenlyMock({ + coordinates: [37.3861, -122.0839], + hostname: 'test-host', + location: 'Test Location', + hardware: 'Unknown Hardware', + screenly_version: '1.2.3', + screen_name: 'Main Screen', + tags: [], + }) + expect(() => getHardware()).toThrow( + 'Unknown hardware type: Unknown Hardware', + ) }) }) diff --git a/edge-apps/edge-apps-library/src/utils/metadata.ts b/edge-apps/edge-apps-library/src/utils/metadata.ts index 79317f3ad..09480dbbb 100644 --- a/edge-apps/edge-apps-library/src/utils/metadata.ts +++ b/edge-apps/edge-apps-library/src/utils/metadata.ts @@ -1,4 +1,5 @@ import type { ScreenlyMetadata } from '../types/index.js' +import { Hardware } from '../types/index.js' import { formatCoordinates } from './locale.js' /** @@ -37,10 +38,24 @@ export function getLocation(): string { } /** - * Get the hardware identifier + * Get the hardware type */ -export function getHardware(): string { - return screenly.metadata.hardware +export function getHardware(): Hardware { + const hardware = screenly.metadata.hardware + + if (hardware === undefined) { + return Hardware.Anywhere + } + + if (hardware === 'Raspberry Pi') { + return Hardware.RaspberryPi + } + + if (hardware === 'Screenly Player Max') { + return Hardware.ScreenlyPlayerMax + } + + throw new Error(`Unknown hardware type: ${hardware}`) } /** diff --git a/edge-apps/menu-board/src/main.ts b/edge-apps/menu-board/src/main.ts index 132d06187..832eabeb5 100644 --- a/edge-apps/menu-board/src/main.ts +++ b/edge-apps/menu-board/src/main.ts @@ -3,6 +3,7 @@ import { getSettingWithDefault, signalReady, } from '@screenly/edge-apps' +import { Hardware } from '@screenly/edge-apps' import { escapeHtml, calculateItemsPerPage, @@ -55,9 +56,9 @@ function renderPage( fragment.appendChild(itemElement) }) - // Disable transitions if hardware is undefined (running in an Anywhere screen) + // Disable transitions if hardware is Anywhere screen const hardware = getHardware() - if (!hardware) { + if (hardware === Hardware.Anywhere) { menuGrid.innerHTML = '' menuGrid.appendChild(fragment) } else {