@pmouli/isy-matter-server
Version:
Service to expose an ISY device as a Matter Border router
143 lines (134 loc) • 4.08 kB
text/typescript
import type { Command } from '../Definitions/Global/Commands.js';
import type { Driver } from '../Definitions/Global/Drivers.js';
import { Family } from '../Definitions/Global/Families.js';
import { Insteon } from '../Devices/index.js';
import type { ISY } from '../ISY.js';
import { ISYDevice } from '../ISYDevice.js';
import { ISYNode } from '../ISYNode.js';
import { LinkType } from '../LinkType.js';
import type { BaseNodeInfo, NodeInfo } from '../Model/NodeInfo.js';
interface SceneInfo extends BaseNodeInfo<Family.Scene> {
members?: {
link: any;
};
flag?: any;
nodeDefId?: 'InsteonDimmer';
address: string;
name: string;
family?: Family.Scene;
parent?: any;
enabled: boolean;
startDelay: number;
}
export class ISYScene extends ISYNode<Family.Scene, Driver.Signatures<'ST'>, Command.Signatures<'DON' | 'DOF' | 'QUERY'>> {
public connectionType: string;
public batteryOperated: boolean;
public deviceType: any;
public deviceFriendlyName: string;
public members: ISYNode<any, any, any, any>[];
public typeCode: string;
constructor(isy: ISY, scene: SceneInfo) {
super(isy, scene as NodeInfo);
// this.logger(JSON.stringify(scene));
this.typeCode = '';
this.connectionType = 'Insteon Wired';
this.batteryOperated = false;
this.deviceFriendlyName = 'ISY Scene';
this.members = [];
this.isDimmable = false;
if (Array.isArray(scene.members?.link)) {
for (const node of scene.members.link) {
if ('_' in node) {
// childDevices.push(node._);
// childDevices.push(object)
const s = node._;
const d = isy.getNode(s);
if (d !== null && d !== undefined) {
//d.addLink(this);
}
if (d instanceof Insteon.DimmerLamp.Node && node.type !== LinkType.Controller) {
this.isDimmable = true;
}
this.members.push(d);
}
}
} else if (scene.members?.link) {
if ('_' in scene.members.link) {
const node = scene.members.link._;
this.logger(JSON.stringify(node));
// childDevices.push(node._);
// childDevices.push(object)
const s = scene.members.link._;
const d = isy.getNode(s);
if (d) {
//d.addLink(this);
// tslint:disable-next-line: triple-equals
if ((d.isDimmable && node.type != LinkType.Controller) || this.isDimmable) {
this.isDimmable = true;
}
this.members.push(d);
}
}
}
// check dimmability this.dimmable = Array.apply(p => p.dimmable);
this.recalculateState();
}
// Get the current light state
get isOn() {
for (const device of this.members) {
let d = device as unknown as ISYNode;
/*if (Insteon.RelayLamp.isImplementedBy(d)) {
if (d.status > 0) {
return true;
}
}*/
}
return false;
}
get brightnessLevel() {
let lightDeviceCount = 0;
let blevel = 0;
for (const device of this.members) {
if (device instanceof Insteon.DimmerSwitch.Node) {
lightDeviceCount++;
//blevel += device.brightnessLevel;
} else if (device instanceof Insteon.RelayLampSwitch.Node) {
lightDeviceCount++;
blevel += device.drivers.ST ? 100 : 0;
}
}
if (lightDeviceCount > 0) {
return Math.floor(blevel / lightDeviceCount);
} else {
return 0;
}
}
// Current light dim state is always calculated
public recalculateState() {
this.markAsChanged();
return true;
}
public markAsChanged() {
this.lastChanged = new Date();
this.emit('propertyChanged', 'isOn', this.isOn, this.isOn, this.isOn ? 'on' : 'off');
if (this.isDimmable) {
this.emit('propertyChanged', 'brightnesslevel', this.brightnessLevel, this.brightnessLevel, this.brightnessLevel + '%');
}
}
public async updateIsOn(lightState: boolean) {
return this.isy.sendNodeCommand(this, lightState ? 'DON' : 'DOF');
}
public async updateBrightnessLevel(level) {
return this.isy.sendNodeCommand(this, level > 0 ? 'DON' : 'DOF', level);
}
public getAreAllLightsInSpecifiedState(state) {
for (const device of this.members) {
if (device instanceof Insteon.RelayLampSwitch.Node) {
if (device.drivers.ST !== state) {
return false;
}
}
}
return true;
}
}