91 lines
3.3 KiB
TypeScript
91 lines
3.3 KiB
TypeScript
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||
|
|
import { MatterMapper } from '../../ts/integrations/matter/index.js';
|
||
|
|
import type { IMatterSnapshot } from '../../ts/integrations/matter/index.js';
|
||
|
|
|
||
|
|
const snapshot: IMatterSnapshot = {
|
||
|
|
connected: true,
|
||
|
|
events: [],
|
||
|
|
serverInfo: {
|
||
|
|
fabric_id: 1,
|
||
|
|
compressed_fabric_id: 2,
|
||
|
|
schema_version: 11,
|
||
|
|
min_supported_schema_version: 6,
|
||
|
|
sdk_version: '1.4.2',
|
||
|
|
wifi_credentials_set: true,
|
||
|
|
thread_credentials_set: false,
|
||
|
|
bluetooth_enabled: false,
|
||
|
|
},
|
||
|
|
nodes: [{
|
||
|
|
node_id: 1234,
|
||
|
|
available: true,
|
||
|
|
attributes: {
|
||
|
|
'0/29/0': [{ deviceType: 0x0016, revision: 1 }],
|
||
|
|
'0/29/1': [29, 40],
|
||
|
|
'0/40/1': 'Acme',
|
||
|
|
'0/40/2': 123,
|
||
|
|
'0/40/3': 'Matter Test Device',
|
||
|
|
'0/40/4': 456,
|
||
|
|
'0/40/5': 'Test Node',
|
||
|
|
'0/40/15': 'serial-1',
|
||
|
|
'1/29/0': [{ deviceType: 0x0101, revision: 2 }],
|
||
|
|
'1/29/1': [29, 6, 8],
|
||
|
|
'1/6/0': true,
|
||
|
|
'1/8/0': 128,
|
||
|
|
'1/8/2': 1,
|
||
|
|
'1/8/3': 254,
|
||
|
|
'2/29/0': [{ deviceType: 0x0015, revision: 1 }],
|
||
|
|
'2/29/1': [29, 69],
|
||
|
|
'2/69/0': false,
|
||
|
|
'3/29/0': [{ deviceType: 0x0202, revision: 1 }],
|
||
|
|
'3/29/1': [29, 258],
|
||
|
|
'3/258/10': 0,
|
||
|
|
'3/258/14': 2500,
|
||
|
|
'4/29/0': [{ deviceType: 0x000a, revision: 1 }],
|
||
|
|
'4/29/1': [29, 257],
|
||
|
|
'4/257/0': 1,
|
||
|
|
'5/29/0': [{ deviceType: 0x0301, revision: 1 }],
|
||
|
|
'5/29/1': [29, 513],
|
||
|
|
'5/513/0': 2150,
|
||
|
|
'5/513/18': 2000,
|
||
|
|
'5/513/28': 4,
|
||
|
|
},
|
||
|
|
}],
|
||
|
|
};
|
||
|
|
|
||
|
|
tap.test('maps Matter nodes to canonical devices and entities', async () => {
|
||
|
|
const devices = MatterMapper.toDevices(snapshot);
|
||
|
|
const entities = MatterMapper.toEntities(snapshot);
|
||
|
|
|
||
|
|
expect(devices.some((deviceArg) => deviceArg.id === 'matter.node.1234.endpoint.1')).toBeTrue();
|
||
|
|
expect(entities.some((entityArg) => entityArg.platform === 'light' && entityArg.state === 'on')).toBeTrue();
|
||
|
|
expect(entities.some((entityArg) => entityArg.platform === 'binary_sensor' && entityArg.attributes?.deviceClass === 'door')).toBeTrue();
|
||
|
|
expect(entities.some((entityArg) => entityArg.platform === 'cover' && entityArg.attributes?.position === 75)).toBeTrue();
|
||
|
|
expect(entities.some((entityArg) => String(entityArg.platform) === 'lock' && entityArg.state === 'locked')).toBeTrue();
|
||
|
|
expect(entities.some((entityArg) => entityArg.platform === 'climate' && entityArg.state === 'heat')).toBeTrue();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('maps entity services to Matter server commands', async () => {
|
||
|
|
const light = MatterMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'light');
|
||
|
|
const cover = MatterMapper.toEntities(snapshot).find((entityArg) => entityArg.platform === 'cover');
|
||
|
|
|
||
|
|
const turnOff = MatterMapper.commandForService(snapshot, {
|
||
|
|
domain: 'light',
|
||
|
|
service: 'turn_off',
|
||
|
|
target: { entityId: light?.id },
|
||
|
|
});
|
||
|
|
const setPosition = MatterMapper.commandForService(snapshot, {
|
||
|
|
domain: 'cover',
|
||
|
|
service: 'set_position',
|
||
|
|
target: { entityId: cover?.id },
|
||
|
|
data: { position: 42 },
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(turnOff?.command).toEqual('device_command');
|
||
|
|
expect(turnOff?.args?.cluster_id).toEqual(6);
|
||
|
|
expect(turnOff?.args?.command_name).toEqual('Off');
|
||
|
|
expect(setPosition?.args?.cluster_id).toEqual(258);
|
||
|
|
expect(setPosition?.args?.payload).toEqual({ liftPercent100thsValue: 5800 });
|
||
|
|
});
|
||
|
|
|
||
|
|
export default tap.start();
|