matterbridge-webhooks
Version:
Matterbridge webhooks plugin
81 lines (80 loc) • 4.5 kB
JavaScript
import { bridgedNode, MatterbridgeDynamicPlatform, MatterbridgeEndpoint, onOffLight, onOffOutlet, onOffSwitch } from 'matterbridge';
import { fetch } from './fetch.js';
export class Platform extends MatterbridgeDynamicPlatform {
webhooks;
bridgedDevices = new Map();
constructor(matterbridge, log, config) {
super(matterbridge, log, config);
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('2.2.5')) {
throw new Error(`This plugin requires Matterbridge version >= "2.2.5". Please update Matterbridge to the latest version in the frontend.`);
}
this.log.info('Initializing platform:', this.config.name);
this.webhooks = this.config.webhooks;
this.log.info('Finished initializing platform:', this.config.name);
}
async onStart(reason) {
this.log.info('onStart called with reason:', reason ?? 'none');
await this.ready;
await this.clearSelect();
let i = 1;
for (const webhookName in this.webhooks) {
if (Object.prototype.hasOwnProperty.call(this.webhooks, webhookName)) {
const webhook = this.webhooks[webhookName];
this.setSelectDevice('webhook' + i, webhookName, webhook.httpUrl, 'webhook');
if (!this.validateDevice(['webhook' + i, webhookName]))
return;
this.log.info(`Registering device: ${webhookName}`, webhook.method, webhook.httpUrl);
const device = new MatterbridgeEndpoint([this.config.deviceType === 'Outlet' ? onOffOutlet : this.config.deviceType === 'Light' ? onOffLight : onOffSwitch, bridgedNode], { uniqueStorageKey: webhookName }, this.config.debug)
.createDefaultBridgedDeviceBasicInformationClusterServer(webhookName, 'webhook' + i++, this.matterbridge.aggregatorVendorId, 'Matterbridge', 'Matterbridge Webhook', 0, this.config.version)
.createOnOffClusterServer(false)
.addRequiredClusterServers()
.addCommandHandler('on', async () => {
this.log.info(`Webhook ${webhookName} triggered.`);
await device.setAttribute('onOff', 'onOff', false, device.log);
fetch(webhook.httpUrl, webhook.method)
.then(() => this.log.notice(`Webhook ${webhookName} successful!`))
.catch((err) => {
this.log.error(`Webhook ${webhookName} failed: ${err instanceof Error ? err.message : err}`);
});
});
await this.registerDevice(device);
this.bridgedDevices.set(webhookName, device);
}
}
}
async onConfigure() {
await super.onConfigure();
this.log.info('onConfigure called');
this.bridgedDevices.forEach(async (device) => {
this.log.info(`Configuring device: ${device.deviceName}`);
await device.setAttribute('onOff', 'onOff', false, device.log);
});
}
async onAction(action, value, id) {
this.log.info('onAction called with action:', action, 'and value:', value ?? 'none', 'and id:', id ?? 'none');
if (action === 'test') {
for (const webhookName in this.webhooks) {
if (Object.prototype.hasOwnProperty.call(this.webhooks, webhookName)) {
const webhook = this.webhooks[webhookName];
if (id?.includes(webhookName)) {
this.log.info(`Testing webhook ${webhookName} method ${webhook.method} url ${webhook.httpUrl}`);
fetch(webhook.httpUrl, webhook.method)
.then(() => {
this.log.notice(`Webhook test ${webhookName} successful!`);
})
.catch((err) => {
this.log.error(`Webhook test ${webhookName} failed: ${err instanceof Error ? err.message : err}`);
});
}
}
}
}
}
async onShutdown(reason) {
await super.onShutdown(reason);
this.log.info('onShutdown called with reason:', reason ?? 'none');
if (this.config.unregisterOnShutdown === true)
await this.unregisterAllDevices();
this.bridgedDevices.clear();
}
}