@pmouli/isy-matter-server
Version:
Service to expose an ISY device as a Matter Border router
131 lines (110 loc) • 4.08 kB
text/typescript
import { Family } from './Definitions/index.js';
import { NodeFactory } from './Devices/NodeFactory.js';
import type { CompositeDevice } from './ISY.js';
import { ISYDevice, ISYDeviceInfo } from './ISYDevice.js';
import { ISYNode } from './ISYNode.js';
import type { Factory, StringKeys } from './Utils.js';
export class Registry<K extends keyof any, T> {
Global: { [x in K]?: T } = {};
FamilyLevel: { [x in StringKeys<typeof Family>]?: { [y in K]?: T } } = {};
DeviceLevel: { [x: string]: { [y in K]?: T } } = {};
NodeDefLevel: { [x: string]: { [y in K]?: T } } = {};
ClassLevel: {[x: string]: { [y in K]?: T } } = {};
registerGlobal(key: K, value: T): void {
this.Global[key] = value;
}
registerFamilyLevel<F extends Family>(family: F & number, key: K, value: T): void {
this.FamilyLevel[Family[family] as string] = this.FamilyLevel[Family[family] as string] ?? {};
this.FamilyLevel[Family[family] as string]![key] = value;
}
registerDeviceLevel(device: string, key: K, value: T): void {
this.DeviceLevel[device] = this.DeviceLevel[device] ?? {};
this.DeviceLevel[device]![key] = value;
}
registerNodeDefLevel(nodeDefId: string, key: K, value: T): void {
this.NodeDefLevel[nodeDefId] = this.NodeDefLevel[nodeDefId] ?? {};
this.NodeDefLevel[nodeDefId]![key] = value;
}
registerClassLevel(className: string, key: K, value: T): void {
this.ClassLevel[className] = this.ClassLevel[className] ?? {};
this.ClassLevel[className]![key] = value;
}
register(key: K, value: T): void;
register(key: K, value: T, deviceType: string): void;
register(key: K, value: T, factory: ISYDevice.Factory<any, any, any, any,any>): void;
register(key: K, value: T, discriminant?: string | Family | ISYDevice.Factory<any,any, any,any,any>): void {
if (discriminant === undefined) {
this.registerGlobal(key, value);
return;
} else if (typeof discriminant === 'string') {
this.registerDeviceLevel(discriminant, key, value);
return;
}
else if (typeof discriminant === 'number')
{
if (discriminant in Family) {
this.registerFamilyLevel(discriminant as Family, key, value);
return;
}
}
else if (ISYDevice.isNode(discriminant)) {
this.registerNodeDefLevel(discriminant.Class.prototype.nodeDefId, key, value);
for (const nodeDefId in NodeFactory.getImplements(discriminant)) {
this.registerNodeDefLevel(nodeDefId, key, value);
}
this.registerClassLevel(discriminant.Class.name, key, value)
this.registerFamilyLevel((discriminant.Class as unknown as typeof ISYNode).family, key, value);
return;
}
else if(ISYDevice.isComposite(discriminant))
{
this.registerClassLevel(discriminant.Class.name, key, value);
return;
}
/*else if(ISYDevice.isComposite(discriminant))
{
this.registerFamilyLevel(discriminant.types, key, value);
return;
}*/ //TODO: Implement Composite Device
}
getGlobal(key: K): T | undefined {
return this.Global[key];
}
getFamilyLevel<F extends Family>(family: F & number, key: K): T | undefined {
return this.FamilyLevel[Family[family] as string]?.[key];
}
getDeviceLevel(device: string, key: K): T | undefined {
return this.DeviceLevel[device]?.[key];
}
getNodeLevel(nodeDefId: string, key: K): T | undefined {
return this.NodeDefLevel[nodeDefId]?.[key];
}
getClassLevel(className: string, key: K): T | undefined {
return this.ClassLevel[className]?.[key];
}
get(device: ISYDevice.Any, key: K): T | undefined {
if (device.type) {
let d = this.getDeviceLevel(device.type, key);
if (d) return d;
}
if (ISYDevice.isNode(device)) {
let d = this.getNodeLevel(device.nodeDefId, key);
if (d) {
return d;
} else {
for (const nodeDefId in NodeFactory.getImplements(device)) {
let d = this.getNodeLevel(nodeDefId, key);
if (d) return d;
}
}
}
if(ISYDevice.isComposite(device))
{
let d = this.getClassLevel(device.constructor.name, key);
if(d) return d;
}
let f = this.getFamilyLevel(device.family, key);
if (f) return f;
return this.getGlobal(key);
}
}