isy-nodejs
Version:
Node.js wrapper for ISY interface including websockets for change notifications. Fork of isy-js by Rod Toll. Designed to be used in a node.js application.
200 lines (158 loc) • 4.72 kB
text/typescript
import { DeviceInfo } from '../Definitions/Global/Categories.js';
import { Family, type Category } from '../Definitions/index.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)