@pmouli/isy-matter-server
Version:
Service to expose an ISY device as a Matter Border router
191 lines (149 loc) • 4.8 kB
text/typescript
import { Family, type Category } from '../Definitions/index.js';
import { Insteon, type ZWave } from '../Devices/index.js';
import { ISYNode } from '../ISYNode.js';
import { DeviceInfo } from '../Definitions/Global/Categories.js';
import type { DriverState } from './DriverState.js';
// #region Type aliases (1)
export type NodeInfo<T extends Family = Family> = (T extends Family.ZMatter | Family.ZigBee ? DynamicNodeInfo<T>
: T extends Family.ZWave ? ZWaveNodeInfo
: BaseNodeInfo<T>) & { state?: { [x: string]: DriverState } };
// #endregion Type aliases (1)
// #region Interfaces (7)
interface Custom {
// #region Properties (2)
flags: number | string;
val1: number | string;
// #endregion Properties (2)
}
interface TypeInfo {
t: T[];
}
interface T {
id: 'ioxType' | 'mfgCode' | 'model';
val: number | string;
}
interface Devtype {
// #region Properties (3)
cat: number;
gen: `${number}.${number}.${number}`;
mfg: string;
// #endregion Properties (3)
}
export interface DynamicNodeInfo<F extends Family.ZigBee | Family.ZMatter> extends BaseNodeInfo<F> {
typeInfo: TypeInfo;
nodeTypeId: string;
rpnode: string;
}
export interface ZWaveNodeInfo extends BaseNodeInfo<Family.ZWave> {
// #region Properties (20)
custom: Custom;
devtype: Devtype;
rpnode: string;
sgid: string;
nodeTypeId: string;
// #endregion Properties (20)
}
interface Node {
// #region Properties (15)
address: string;
dcPeriod: string;
deviceClass: string;
enabled: string;
endDelay: string;
family: string;
flag: string;
hint: string;
name: string;
nodeDefId: string;
parent: Parent;
pnode: string;
startDelay: string;
type: string;
wattage: string;
// #endregion Properties (15)
}
interface Parent {
// #region Properties (2)
_: string;
type: string;
// #endregion Properties (2)
}
interface RootObject {
// #region Properties (1)
node: Node;
// #endregion Properties (1)
}
export interface BaseNodeInfo<F extends Family> {
// #region Properties (16)
address: any;
dcPeriod: number;
deviceClass?: any;
enabled?: boolean;
endDelay: number;
family?: F extends Family.Poly ? { _: Family.Poly; instance: number } : F;
flag?: any;
hint: string;
name: string;
nodeDefId?: string;
parent?: Parent;
pnode: any;
property?: DriverState[] | DriverState;
startDelay: number;
type?: string;
wattage: number;
// #endregion Properties (16)
}
// #endregion Interfaces (7)
// #region Functions (3)
export function isFamily<T extends Family>(nodeInfo: NodeInfo<any>, family: T): nodeInfo is NodeInfo<T> {
return nodeInfo.family ?? 1 === family;
}
export function parseDeviceInfo<F extends Family>(nodeInfo: NodeInfo<F>): NodeInfo<F> extends BaseNodeInfo<Family.Insteon> ? { category: Category.Insteon; model: number; firmwareVersion: string; firmwareRevision: string } : DeviceInfo<any, any, any> {
const type = nodeInfo.type === undefined || nodeInfo.type === '0.0.0.0' ? nodeInfo.hint : nodeInfo.type;
const family = (nodeInfo.family ?? nodeInfo.family == 0) ? Family.Insteon : nodeInfo.family;
if (isFamily(nodeInfo, Family.Insteon)) {
const s = type.split('.');
return { category: Number(s[0]), model: Number(s[1]), firmwareVersion: Number(Number(s[2]).toString(16)), firmwareRevision: Number(Number(s[3]).toString(16)) } as any;
} else {
const s = type.split('.');
return { domain: Number(s[0]), category: Number(s[1]), subcategory: Number(s[1]), model: Number(s[2]) } as any;
}
}
export function cleanNodeInfo<T extends Family>(nodeInfo: NodeInfo<T>) {
if (isDynamic(nodeInfo)) {
nodeInfo.nodeTypeId = `${nodeInfo.typeInfo.t.find((p) => p.id == 'ioxType').val}`;
} else if (isZWave(nodeInfo)) {
nodeInfo.nodeTypeId = nodeInfo.sgid;
}
if (!nodeInfo.property) {
nodeInfo.property = [];
}
nodeInfo.property = Array.isArray(nodeInfo.property) ? nodeInfo.property : [nodeInfo.property];
nodeInfo.state = nodeInfo.property.reduce((acc, p) => {
if (p && p?.id) {
p.name = p.name == '' ? undefined : p.name;
acc[p.id] = p;
}
return acc;
}, {});
if (!nodeInfo.family || nodeInfo.family == -1) {
nodeInfo.family = Family.Insteon;
}
return nodeInfo;
}
export function isPlugin(nodeInfo: NodeInfo<any>): nodeInfo is NodeInfo<Family.Poly> {
if (typeof nodeInfo.family == 'object') {
return true;
}
return nodeInfo.family === Family.Poly;
}
export function isDynamic(nodeInfo: NodeInfo<any>): nodeInfo is DynamicNodeInfo<any> {
return [Family.ZMatter, Family.ZigBee].includes(nodeInfo.family);
}
export function isZWave(nodeInfo: NodeInfo<any>): nodeInfo is ZWaveNodeInfo {
return nodeInfo.family == Family.ZWave;
}
export function isStatic(nodeInfo: NodeInfo<any>): nodeInfo is BaseNodeInfo<any> {
return isDynamic(nodeInfo) || isZWave(nodeInfo) ? false : true;
}
// #endregion Functions (3)