Add native camera and media service integrations

This commit is contained in:
2026-05-05 17:13:54 +00:00
parent 489d9d5243
commit e7441844c9
112 changed files with 18608 additions and 327 deletions
+32
View File
@@ -0,0 +1,32 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { createMpdDiscoveryDescriptor } from '../../ts/integrations/mpd/index.js';
tap.test('matches MPD mDNS records', async () => {
const descriptor = createMpdDiscoveryDescriptor();
const matcher = descriptor.getMatchers()[0];
const result = await matcher.matches({
name: 'Living Room MPD',
type: '_mpd._tcp.local.',
host: 'mpd.local',
port: 6600,
}, {});
expect(result.matched).toBeTrue();
expect(result.candidate?.integrationDomain).toEqual('mpd');
expect(result.candidate?.port).toEqual(6600);
expect(result.metadata?.mdnsType).toEqual('_mpd._tcp');
});
tap.test('matches and validates manual MPD entries', async () => {
const descriptor = createMpdDiscoveryDescriptor();
const matcher = descriptor.getMatchers()[1];
const result = await matcher.matches({ host: '192.168.1.50', name: 'Kitchen MPD' }, {});
expect(result.matched).toBeTrue();
expect(result.candidate?.port).toEqual(6600);
const validator = descriptor.getValidators()[0];
const validation = await validator.validate(result.candidate!, {});
expect(validation.matched).toBeTrue();
expect(validation.normalizedDeviceId).toEqual('192.168.1.50:6600');
});
export default tap.start();
+79
View File
@@ -0,0 +1,79 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { MpdMapper, type IMpdSnapshot } from '../../ts/integrations/mpd/index.js';
const snapshot: IMpdSnapshot = {
server: {
id: 'mpd-living-room',
host: '192.168.1.50',
port: 6600,
name: 'Living Room MPD',
protocolVersion: '0.24.0',
},
status: {
volume: '42',
repeat: '1',
single: '0',
random: '1',
playlist: '12',
playlistlength: '7',
state: 'play',
songid: '23',
elapsed: '31.2',
duration: '180.5',
audio: '44100:16:2',
bitrate: '320',
lastloadedplaylist: 'Favorites',
},
currentSong: {
file: 'artist/album/example.flac',
artist: ['Example Artist', 'Guest Artist'],
album: 'Example Album',
title: 'Example Track',
time: '180',
id: '23',
},
outputs: [{
outputid: 0,
outputname: 'Main ALSA',
plugin: 'alsa',
outputenabled: true,
attributes: { dop: '0' },
}, {
outputid: 1,
outputname: 'Headphones',
plugin: 'pulse',
outputenabled: false,
}],
commands: ['status', 'currentsong', 'play', 'pause', 'setvol', 'outputs'],
playlists: [{ playlist: 'Favorites' }, { playlist: 'Radio' }],
stats: { songs: '2000', uptime: '3600' },
online: true,
updatedAt: '2026-01-01T00:00:00.000Z',
source: 'manual',
};
tap.test('maps MPD server and outputs to canonical devices', async () => {
const devices = MpdMapper.toDevices(snapshot);
expect(devices.some((deviceArg) => deviceArg.id === 'mpd.server.mpd_living_room')).toBeTrue();
expect(devices.some((deviceArg) => deviceArg.id === 'mpd.output.mpd_living_room.0')).toBeTrue();
});
tap.test('maps MPD status current song and outputs to entities', async () => {
const entities = MpdMapper.toEntities(snapshot);
const player = entities.find((entityArg) => entityArg.id === 'media_player.living_room_mpd');
const status = entities.find((entityArg) => entityArg.id === 'sensor.living_room_mpd_mpd_status');
const output = entities.find((entityArg) => entityArg.id === 'switch.living_room_mpd_main_alsa_mpd_output');
expect(player?.platform).toEqual('media_player');
expect(player?.state).toEqual('playing');
expect(player?.attributes?.volumeLevel).toEqual(0.42);
expect(player?.attributes?.mediaTitle).toEqual('Example Track');
expect(player?.attributes?.mediaArtist).toEqual('Example Artist, Guest Artist');
expect(player?.attributes?.sourceList).toEqual(['Favorites', 'Radio']);
expect(status?.state).toEqual('play');
expect(output?.platform).toEqual('switch');
expect(output?.state).toEqual('on');
expect(output?.attributes?.mpdOutputId).toEqual(0);
});
export default tap.start();