mirror of
https://github.com/koush/scrypted.git
synced 2026-02-12 10:02:04 +00:00
mqtt: frigate api
This commit is contained in:
4
plugins/mqtt/package-lock.json
generated
4
plugins/mqtt/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/mqtt",
|
||||
"version": "0.0.14",
|
||||
"version": "0.0.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/mqtt",
|
||||
"version": "0.0.14",
|
||||
"version": "0.0.17",
|
||||
"dependencies": {
|
||||
"@types/node": "^16.6.1",
|
||||
"aedes": "^0.46.1",
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
"devDependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk"
|
||||
},
|
||||
"version": "0.0.14"
|
||||
"version": "0.0.17"
|
||||
}
|
||||
|
||||
108
plugins/mqtt/src/api/frigate.ts
Normal file
108
plugins/mqtt/src/api/frigate.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import type { ScryptedDeviceBase } from "@scrypted/sdk";
|
||||
import type { MqttClient, MqttSubscriptions } from "./mqtt-client";
|
||||
|
||||
declare const mqtt: MqttClient;
|
||||
declare const device: ScryptedDeviceBase;
|
||||
|
||||
|
||||
export type FrigateObjectType =
|
||||
'person' |
|
||||
'bicycle' |
|
||||
'car' |
|
||||
'motorcycle' |
|
||||
'airplane' |
|
||||
'bus' |
|
||||
'train' |
|
||||
'car' |
|
||||
'boat' |
|
||||
'traffic light' |
|
||||
'fire hydrant' |
|
||||
'stop sign' |
|
||||
'parking meter' |
|
||||
'bench' |
|
||||
'bird' |
|
||||
'cat' |
|
||||
'dog' |
|
||||
'horse' |
|
||||
'sheep' |
|
||||
'cow' |
|
||||
'elephant' |
|
||||
'bear' |
|
||||
'zebra' |
|
||||
'giraffe' |
|
||||
'backpack' |
|
||||
'umbrella' |
|
||||
'handbag' |
|
||||
'tie' |
|
||||
'suitcase' |
|
||||
'frisbee' |
|
||||
'skis' |
|
||||
'snowboard' |
|
||||
'sports ball' |
|
||||
'kite' |
|
||||
'baseball bat' |
|
||||
'baseball glove' |
|
||||
'skateboard' |
|
||||
'surfboard' |
|
||||
'tennis racket' |
|
||||
'bottle' |
|
||||
'wine glass' |
|
||||
'cup' |
|
||||
'fork' |
|
||||
'knife' |
|
||||
'spoon' |
|
||||
'bowl' |
|
||||
'banana' |
|
||||
'apple' |
|
||||
'sandwich' |
|
||||
'orange' |
|
||||
'broccoli' |
|
||||
'carrot' |
|
||||
'hot dog' |
|
||||
'pizza' |
|
||||
'donut' |
|
||||
'cake' |
|
||||
'chair' |
|
||||
'couch' |
|
||||
'potted plant' |
|
||||
'bed' |
|
||||
'dining table' |
|
||||
'toilet' |
|
||||
'tv' |
|
||||
'laptop' |
|
||||
'mouse' |
|
||||
'remote' |
|
||||
'keyboard' |
|
||||
'cell phone' |
|
||||
'microwave' |
|
||||
'oven' |
|
||||
'toaster' |
|
||||
'sink' |
|
||||
'refrigerator' |
|
||||
'book' |
|
||||
'clock' |
|
||||
'vase' |
|
||||
'scissors' |
|
||||
'teddy bear' |
|
||||
'hair drier' |
|
||||
'toothbrush';
|
||||
|
||||
export interface FrigateZoneWatcher {
|
||||
zone: string,
|
||||
objects: FrigateObjectType[];
|
||||
}
|
||||
|
||||
export function frigateMotionSensor(zoneWatcher: FrigateZoneWatcher, ...zoneWatchers: FrigateZoneWatcher[]) {
|
||||
const subs: MqttSubscriptions = {};
|
||||
const counts: { [type: string]: number } = {};
|
||||
for (const z of [zoneWatcher, ...zoneWatchers]) {
|
||||
for (const o of z.objects) {
|
||||
subs[`/${z.zone}/${o}`] = message => {
|
||||
counts[z.zone] = message.json;
|
||||
device.motionDetected = Object.values(counts).reduce((a, b) => a + b, 0) !== 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
mqtt.subscribe(subs);
|
||||
mqtt.handle({}, "MotionSensor");
|
||||
}
|
||||
@@ -16,6 +16,6 @@ export interface MqttHandler {
|
||||
|
||||
export interface MqttClient {
|
||||
subscribe(subscriptions: MqttSubscriptions, options?: any): void;
|
||||
handle<T>(handler?: T, ...interfaces: ScryptedInterface[]): void;
|
||||
handle<T>(handler?: T, ...interfaces: string[]): void;
|
||||
publish(topic: string, value: any): Promise<void>;
|
||||
}
|
||||
@@ -6,14 +6,14 @@ import { Settings, Setting, DeviceProvider, OnOff, ScryptedDeviceBase, ScryptedI
|
||||
import sdk from '@scrypted/sdk';
|
||||
import { monacoEvalDefaults } from './monaco';
|
||||
import { scryptedEval } from './scrypted-eval';
|
||||
import { MqttClient, MqttSubscriptions } from './mqtt-client';
|
||||
import { MqttClient, MqttSubscriptions } from './api/mqtt-client';
|
||||
import { connect, Client, IClientSubscribeOptions, ClientSubscribeCallback } from 'mqtt';
|
||||
import aedes from 'aedes';
|
||||
import net from 'net';
|
||||
import ws from 'websocket-stream';
|
||||
import http from 'http';
|
||||
|
||||
const loopbackLight = require("!!raw-loader!./loopback-light.ts");
|
||||
const loopbackLight = require("!!raw-loader!./examples/loopback-light.ts");
|
||||
|
||||
const methodInterfaces: { [method: string]: string } = {};
|
||||
for (const desc of Object.values(ScryptedInterfaceDescriptors)) {
|
||||
@@ -77,8 +77,7 @@ class MqttDevice extends ScryptedDeviceBase implements Scriptable, Settings {
|
||||
this.client?.end();
|
||||
this.client = undefined;
|
||||
const url = new URL(this.storage.getItem('url'));
|
||||
const { pathname } = url;
|
||||
this.pathname = pathname;
|
||||
this.pathname = url.pathname.substring(1);
|
||||
const urlWithoutPath = new URL(this.storage.getItem('url'));
|
||||
urlWithoutPath.pathname = '';
|
||||
|
||||
@@ -100,7 +99,7 @@ class MqttDevice extends ScryptedDeviceBase implements Scriptable, Settings {
|
||||
const mqtt: MqttClient = {
|
||||
subscribe: (subscriptions: MqttSubscriptions, options?: any) => {
|
||||
for (const topic of Object.keys(subscriptions)) {
|
||||
const fullTopic = pathname + topic;
|
||||
const fullTopic = this.pathname + topic;
|
||||
const cb = subscriptions[topic];
|
||||
if (options) {
|
||||
client.subscribe(fullTopic, options)
|
||||
@@ -109,7 +108,7 @@ class MqttDevice extends ScryptedDeviceBase implements Scriptable, Settings {
|
||||
client.subscribe(fullTopic)
|
||||
}
|
||||
client.on('message', (messageTopic, message) => {
|
||||
if (fullTopic !== messageTopic)
|
||||
if (fullTopic !== messageTopic && fullTopic !== '/' + messageTopic)
|
||||
return;
|
||||
this.console.log('mqtt message', topic, message.toString());
|
||||
cb({
|
||||
@@ -139,7 +138,7 @@ class MqttDevice extends ScryptedDeviceBase implements Scriptable, Settings {
|
||||
value = JSON.stringify(value);
|
||||
if (value.constructor.name !== Buffer.name)
|
||||
value = value.toString();
|
||||
client.publish(pathname + topic, value);
|
||||
client.publish(this.pathname + topic, value);
|
||||
}
|
||||
}
|
||||
await scryptedEval(this, script, {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
const types = require("!!raw-loader!@scrypted/sdk/types.d.ts");
|
||||
const sdk = require("!!raw-loader!@scrypted/sdk/index.d.ts");
|
||||
const client = require("!!raw-loader!./mqtt-client.ts");
|
||||
const libs = {
|
||||
types: require("!!raw-loader!@scrypted/sdk/types.d.ts"),
|
||||
sdk: require("!!raw-loader!@scrypted/sdk/index.d.ts"),
|
||||
client: require("!!raw-loader!./api/mqtt-client.ts"),
|
||||
frigate: require("!!raw-loader!./api/frigate.ts"),
|
||||
};
|
||||
|
||||
function monacoEvalDefaultsFunction(monaco, types, sdk, client) {
|
||||
function monacoEvalDefaultsFunction(monaco, libs) {
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
|
||||
Object.assign(
|
||||
{},
|
||||
@@ -14,14 +17,13 @@ function monacoEvalDefaultsFunction(monaco, types, sdk, client) {
|
||||
)
|
||||
);
|
||||
|
||||
const catLibs = Object.values(libs).join('\n');
|
||||
const catlibsNoExport = Object.keys(libs).filter(lib => lib !== 'sdk').map(lib => libs[lib]).map(lib => lib.toString().replace(/export /g, '')).join('\n');
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(`
|
||||
${types}
|
||||
${sdk}
|
||||
${client}
|
||||
${catLibs}
|
||||
|
||||
declare global {
|
||||
${types.replace("export interface", "interface")}
|
||||
${client.replace("export interface", "interface")}
|
||||
${catlibsNoExport}
|
||||
|
||||
const log: Logger;
|
||||
|
||||
@@ -38,18 +40,16 @@ function monacoEvalDefaultsFunction(monaco, types, sdk, client) {
|
||||
);
|
||||
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
sdk,
|
||||
libs['sdk'],
|
||||
"node_modules/@types/scrypted__sdk/index.d.ts"
|
||||
);
|
||||
}
|
||||
|
||||
export const monacoEvalDefaults = `(function() {
|
||||
const types = \`${types}\`;
|
||||
const sdk = \`${sdk}\`;
|
||||
const client = \`${client}\`;
|
||||
const libs = ${JSON.stringify(libs)};
|
||||
|
||||
return (monaco) => {
|
||||
(${monacoEvalDefaultsFunction})(monaco, types, sdk, client);
|
||||
(${monacoEvalDefaultsFunction})(monaco, libs);
|
||||
}
|
||||
})();
|
||||
`;
|
||||
|
||||
@@ -2,6 +2,13 @@ import ts, { ScriptTarget } from "typescript";
|
||||
import sdk, { ScryptedDeviceBase } from "@scrypted/sdk";
|
||||
import vm from "vm";
|
||||
|
||||
const frigate = require("!!raw-loader!./api/frigate.ts");
|
||||
const types = require("!!raw-loader!!@scrypted/sdk/types.d.ts");
|
||||
const libs = {
|
||||
frigate,
|
||||
types,
|
||||
};
|
||||
|
||||
const { systemManager, deviceManager, mediaManager, endpointManager } = sdk;
|
||||
|
||||
function tsCompile(source: string, options: ts.TranspileOptions = null): string {
|
||||
@@ -19,7 +26,8 @@ function tsCompile(source: string, options: ts.TranspileOptions = null): string
|
||||
|
||||
export async function scryptedEval(device: ScryptedDeviceBase, script: string, params: { [name: string]: any }) {
|
||||
try {
|
||||
const compiled = tsCompile(script);
|
||||
const allScripts = Object.values(libs).join('\n').toString() + script;
|
||||
const compiled = tsCompile(allScripts);
|
||||
|
||||
const allParams = Object.assign({}, params, {
|
||||
systemManager,
|
||||
@@ -30,6 +38,7 @@ export async function scryptedEval(device: ScryptedDeviceBase, script: string, p
|
||||
console: device.console,
|
||||
localStorage: device.storage,
|
||||
device,
|
||||
exports: {},
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user