Skip to content

Commit 9263173

Browse files
committed
Add suppport for MQTT message matching via RegExp
1 parent dfbf2cb commit 9263173

2 files changed

Lines changed: 67 additions & 18 deletions

File tree

src/configTypes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ export type VideoConfig = {
5454
export type MqttCameraConfig = {
5555
motionTopic?: string;
5656
motionMessage?: string;
57+
motionMessageRegExp?: string;
5758
motionResetTopic?: string;
5859
motionResetMessage?: string;
60+
motionResetMessageRegExp?: string;
5961
doorbellTopic?: string;
6062
doorbellMessage?: string;
63+
doorbellMessageRegExp?: string;
6164
};

src/index.ts

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import {
1111
PlatformAccessoryEvent,
1212
PlatformConfig
1313
} from 'homebridge';
14-
import http from 'http';
15-
import mqtt from 'mqtt';
16-
import { AutomationReturn } from './autoTypes';
1714
import { CameraConfig, FfmpegPlatformConfig } from './configTypes';
15+
16+
import { AutomationReturn } from './autoTypes';
1817
import { Logger } from './logger';
1918
import { StreamingDelegate } from './streamingDelegate';
19+
import http from 'http';
20+
import mqtt from 'mqtt';
21+
2022
const version = require('../package.json').version; // eslint-disable-line @typescript-eslint/no-var-requires
2123

2224
let hap: HAP;
@@ -40,7 +42,10 @@ class FfmpegPlatform implements DynamicPlatformPlugin {
4042
private readonly accessories: Array<PlatformAccessory> = [];
4143
private readonly motionTimers: Map<string, NodeJS.Timeout> = new Map();
4244
private readonly doorbellTimers: Map<string, NodeJS.Timeout> = new Map();
43-
private readonly mqttActions: Map<string, Map<string, Array<MqttAction>>> = new Map();
45+
private readonly mqttActions: Map<string, {
46+
messageMap: Map<string, Array<MqttAction>> | undefined,
47+
reMap: Map<RegExp, Array<MqttAction>> | undefined,
48+
}> = new Map();
4449

4550
constructor(log: Logging, config: PlatformConfig, api: API) {
4651
this.log = new Logger(log);
@@ -92,12 +97,22 @@ class FfmpegPlatform implements DynamicPlatformPlugin {
9297
api.on(APIEvent.DID_FINISH_LAUNCHING, this.didFinishLaunching.bind(this));
9398
}
9499

95-
addMqttAction(topic: string, message: string, details: MqttAction): void {
96-
const messageMap = this.mqttActions.get(topic) || new Map();
97-
const actionArray = messageMap.get(message) || [];
98-
actionArray.push(details);
99-
messageMap.set(message, actionArray);
100-
this.mqttActions.set(topic, messageMap);
100+
addMqttAction(topic: string, message: string | RegExp, details: MqttAction): void {
101+
let { messageMap, reMap } = this.mqttActions.get(topic) || { messageMap: undefined, reMap: undefined };
102+
let actionArray
103+
104+
if (typeof message === 'string') {
105+
actionArray = messageMap?.get(message) || []
106+
messageMap = messageMap || new Map()
107+
actionArray.push(details);
108+
messageMap.set(message, actionArray);
109+
} else { // RegExp
110+
actionArray = reMap?.get(message) || []
111+
reMap = reMap || new Map()
112+
actionArray.push(details);
113+
reMap.set(message, actionArray)
114+
}
115+
this.mqttActions.set(topic, {messageMap, reMap});
101116
}
102117

103118
setupAccessory(accessory: PlatformAccessory, cameraConfig: CameraConfig): void {
@@ -171,16 +186,34 @@ class FfmpegPlatform implements DynamicPlatformPlugin {
171186
if (this.config.mqtt) {
172187
if (cameraConfig.mqtt) {
173188
if (cameraConfig.mqtt.motionTopic) {
174-
this.addMqttAction(cameraConfig.mqtt.motionTopic, cameraConfig.mqtt.motionMessage || cameraConfig.name!,
175-
{accessory: accessory, active: true, doorbell: false});
189+
if (cameraConfig.mqtt.motionMessage) {
190+
this.addMqttAction(cameraConfig.mqtt.motionTopic, cameraConfig.mqtt.motionMessage || cameraConfig.name!,
191+
{accessory: accessory, active: true, doorbell: false});
192+
}
193+
if (cameraConfig.mqtt.motionMessageRegExp) {
194+
this.addMqttAction(cameraConfig.mqtt.motionTopic, new RegExp(cameraConfig.mqtt.motionMessageRegExp) || cameraConfig.name!,
195+
{accessory: accessory, active: true, doorbell: false});
196+
}
176197
}
177198
if (cameraConfig.mqtt.motionResetTopic) {
178-
this.addMqttAction(cameraConfig.mqtt.motionResetTopic, cameraConfig.mqtt.motionResetMessage || cameraConfig.name!,
179-
{accessory: accessory, active: false, doorbell: false});
199+
if (cameraConfig.mqtt.motionResetMessage) {
200+
this.addMqttAction(cameraConfig.mqtt.motionResetTopic, cameraConfig.mqtt.motionResetMessage || cameraConfig.name!,
201+
{accessory: accessory, active: false, doorbell: false});
202+
}
203+
if (cameraConfig.mqtt.motionResetMessageRegExp) {
204+
this.addMqttAction(cameraConfig.mqtt.motionResetTopic, new RegExp(cameraConfig.mqtt.motionResetMessageRegExp) || cameraConfig.name!,
205+
{accessory: accessory, active: false, doorbell: false});
206+
}
180207
}
181208
if (cameraConfig.mqtt.doorbellTopic) {
182-
this.addMqttAction(cameraConfig.mqtt.doorbellTopic, cameraConfig.mqtt.doorbellMessage || cameraConfig.name!,
183-
{accessory: accessory, active: true, doorbell: true});
209+
if (cameraConfig.mqtt.doorbellMessage) {
210+
this.addMqttAction(cameraConfig.mqtt.doorbellTopic, cameraConfig.mqtt.doorbellMessage || cameraConfig.name!,
211+
{accessory: accessory, active: true, doorbell: true});
212+
}
213+
if (cameraConfig.mqtt.doorbellMessageRegExp) {
214+
this.addMqttAction(cameraConfig.mqtt.doorbellTopic, new RegExp(cameraConfig.mqtt.doorbellMessageRegExp) || cameraConfig.name!,
215+
{accessory: accessory, active: true, doorbell: true});
216+
}
184217
}
185218
}
186219
}
@@ -367,7 +400,7 @@ class FfmpegPlatform implements DynamicPlatformPlugin {
367400
}
368401
});
369402
client.on('message', (topic: string, message: Buffer) => {
370-
const messageMap = this.mqttActions.get(topic);
403+
const { messageMap, reMap } = this.mqttActions.get(topic) ?? { messageMap: undefined, reMap: undefined };
371404
if (messageMap) {
372405
const actionArray = messageMap.get(message.toString());
373406
if (actionArray) {
@@ -380,6 +413,19 @@ class FfmpegPlatform implements DynamicPlatformPlugin {
380413
}
381414
}
382415
}
416+
if (reMap) {
417+
for (const [re, actionArray] of reMap) {
418+
if (re.test(message.toString())) {
419+
for (const action of actionArray) {
420+
if (action.doorbell) {
421+
this.doorbellHandler(action.accessory, action.active);
422+
} else {
423+
this.motionHandler(action.accessory, action.active);
424+
}
425+
}
426+
}
427+
}
428+
}
383429
});
384430
}
385431
if (this.config.porthttp) {
@@ -421,4 +467,4 @@ export = (api: API): void => {
421467
Accessory = api.platformAccessory;
422468

423469
api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, FfmpegPlatform);
424-
};
470+
};

0 commit comments

Comments
 (0)