Working debug configuration
This commit is contained in:
parent
3ccf85cb00
commit
e047ef6549
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
@ -4,17 +4,6 @@
|
|||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Launch Program",
|
|
||||||
"program": "${workspaceFolder}/bin/index.js",
|
|
||||||
"preLaunchTask": "build",
|
|
||||||
"console": "internalConsole",
|
|
||||||
"internalConsoleOptions": "openOnSessionStart",
|
|
||||||
"sourceMaps": true,
|
|
||||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Current TS File",
|
"name": "Current TS File",
|
||||||
"type": "node",
|
"type": "node",
|
||||||
@ -24,6 +13,18 @@
|
|||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"protocol": "inspector"
|
"protocol": "inspector"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Program",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
"internalConsoleOptions": "openOnSessionStart",
|
||||||
|
"program": "/Users/brandonwatson/.nvm/versions/node/v14.15.0/lib/node_modules/homebridge/bin/homebridge",
|
||||||
|
"env": {
|
||||||
|
"HOMEBRIDGE_OPTS": "/Users/brandonwatson/.homebridge"
|
||||||
|
},
|
||||||
|
"sourceMaps": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
11
.vscode/tasks.json
vendored
11
.vscode/tasks.json
vendored
@ -4,10 +4,15 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "build",
|
||||||
"label": "build",
|
"label": "build",
|
||||||
"type": "typescript",
|
"problemMatcher": []
|
||||||
"tsconfig": "tsconfig.json",
|
},
|
||||||
"problemMatcher": ["$tsc"]
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"label": "build and install",
|
||||||
|
"command": "npm run build&&sudo npm install -g --unsafe-perm ."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"editor.tabSize": 2
|
"editor.tabSize": 2,
|
||||||
|
"debug.javascript.unmapMissingSources": true
|
||||||
}
|
}
|
||||||
}
|
}
|
20
package.json
20
package.json
@ -2,7 +2,7 @@
|
|||||||
"name": "homebridge-face-location",
|
"name": "homebridge-face-location",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.ts",
|
"main": "bin/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build": "npm run copy-files && tsc --build",
|
"build": "npm run copy-files && tsc --build",
|
||||||
@ -15,8 +15,12 @@
|
|||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"homebridge",
|
"homebridge",
|
||||||
"typescript"
|
"typescript",
|
||||||
|
"homebridge-plugin"
|
||||||
],
|
],
|
||||||
|
"engines": {
|
||||||
|
"homebridge": ">=1.1.6"
|
||||||
|
},
|
||||||
"author": "Brandon Watson",
|
"author": "Brandon Watson",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -25,16 +29,16 @@
|
|||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
"@vladmandic/face-api": "^0.8.8",
|
"@vladmandic/face-api": "^0.8.8",
|
||||||
"canvas": "^2.6.1",
|
"canvas": "^2.6.1",
|
||||||
"copyfiles": "^2.4.0",
|
|
||||||
"dotenv-extended": "^2.9.0",
|
"dotenv-extended": "^2.9.0",
|
||||||
"homebridge": "^1.1.6",
|
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
"rtsp-stream": "file:../rtsp-stream",
|
"rtsp-stream": "file:../rtsp-stream",
|
||||||
"ts-node": "^9.0.0",
|
"tsyringe": "^4.4.0"
|
||||||
"tsyringe": "^4.4.0",
|
|
||||||
"typescript": "^4.0.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/webgl2": "0.0.5"
|
"@types/webgl2": "0.0.5",
|
||||||
|
"typescript": "^4.0.5",
|
||||||
|
"ts-node": "^9.0.0",
|
||||||
|
"homebridge": "^1.1.6",
|
||||||
|
"copyfiles": "^2.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,18 @@ export interface IRoom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isRoom = (object: any): object is IRoom => {
|
export const isRoom = (object: any): object is IRoom => {
|
||||||
return "name" in object && "rtspCameraConnectionString" in object;
|
return "name" in object && "rtspConnectionStrings" in object;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isConfig = (object: any): object is IConfig => {
|
export const isConfig = (object: any): object is IConfig => {
|
||||||
|
const roomsOkay =
|
||||||
|
object["rooms"].filter((room: any) => isRoom(room)).length ===
|
||||||
|
object["rooms"].length;
|
||||||
return (
|
return (
|
||||||
"refImageDirectory" in object &&
|
"refImageDirectory" in object &&
|
||||||
"trainedModelDirectory" in object &&
|
"trainedModelDirectory" in object &&
|
||||||
|
"weightDirectory" in object &&
|
||||||
"rooms" in object &&
|
"rooms" in object &&
|
||||||
isRoom(object["rooms"])
|
roomsOkay
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
CharacteristicSetCallback,
|
CharacteristicSetCallback,
|
||||||
CharacteristicGetCallback,
|
CharacteristicGetCallback,
|
||||||
} from "homebridge";
|
} from "homebridge";
|
||||||
|
import { LocationMonitor } from "./locationMonitor";
|
||||||
import { HomeLocationPlatform } from "./platform";
|
import { HomeLocationPlatform } from "./platform";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +27,8 @@ export class MonitorAccessory {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly platform: HomeLocationPlatform,
|
private readonly platform: HomeLocationPlatform,
|
||||||
private readonly accessory: PlatformAccessory
|
private readonly accessory: PlatformAccessory,
|
||||||
|
private monitor: LocationMonitor
|
||||||
) {
|
) {
|
||||||
// set accessory information
|
// set accessory information
|
||||||
this.accessory
|
this.accessory
|
||||||
@ -42,17 +43,17 @@ export class MonitorAccessory {
|
|||||||
"Default-Serial"
|
"Default-Serial"
|
||||||
);
|
);
|
||||||
|
|
||||||
// get the LightBulb service if it exists, otherwise create a new LightBulb service
|
// get the MotionSensor service if it exists, otherwise create a new MotionSensor service
|
||||||
// you can create multiple services for each accessory
|
// you can create multiple services for each accessory
|
||||||
this.service =
|
this.service =
|
||||||
this.accessory.getService(this.platform.Service.Lightbulb) ||
|
this.accessory.getService(this.platform.Service.MotionSensor) ||
|
||||||
this.accessory.addService(this.platform.Service.Lightbulb);
|
this.accessory.addService(this.platform.Service.MotionSensor);
|
||||||
|
|
||||||
// set the service name, this is what is displayed as the default name on the Home app
|
// set the service name, this is what is displayed as the default name on the Home app
|
||||||
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
||||||
this.service.setCharacteristic(
|
this.service.setCharacteristic(
|
||||||
this.platform.Characteristic.Name,
|
this.platform.Characteristic.Name,
|
||||||
accessory.context.device.exampleDisplayName
|
accessory.context["DeviceName"]
|
||||||
);
|
);
|
||||||
|
|
||||||
// each service must implement at-minimum the "required characteristics" for the given service type
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
||||||
|
@ -19,7 +19,8 @@ import {
|
|||||||
FaceMatcher,
|
FaceMatcher,
|
||||||
} from "@vladmandic/face-api";
|
} from "@vladmandic/face-api";
|
||||||
import * as mime from "mime-types";
|
import * as mime from "mime-types";
|
||||||
import { getFaceDetectorOptions } from "../src/common";
|
import { LocationMonitor } from "./locationMonitor";
|
||||||
|
import { getFaceDetectorOptions } from "./common";
|
||||||
require("@tensorflow/tfjs-node");
|
require("@tensorflow/tfjs-node");
|
||||||
|
|
||||||
const { Canvas, Image, ImageData } = canvas;
|
const { Canvas, Image, ImageData } = canvas;
|
||||||
@ -99,16 +100,7 @@ export class HomeLocationPlatform implements DynamicPlatformPlugin {
|
|||||||
faceMatcher = FaceMatcher.fromJSON(JSON.parse(raw));
|
faceMatcher = FaceMatcher.fromJSON(JSON.parse(raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
const exampleDevices = [
|
const locationMonitor = new LocationMonitor(this.config.rooms, faceMatcher);
|
||||||
{
|
|
||||||
exampleUniqueId: "ABCD",
|
|
||||||
exampleDisplayName: "Bedroom",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
exampleUniqueId: "EFGH",
|
|
||||||
exampleDisplayName: "Kitchen",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const labels = faceMatcher.labeledDescriptors.map((e) => e.label);
|
const labels = faceMatcher.labeledDescriptors.map((e) => e.label);
|
||||||
for (const room of this.config.rooms) {
|
for (const room of this.config.rooms) {
|
||||||
@ -122,28 +114,23 @@ export class HomeLocationPlatform implements DynamicPlatformPlugin {
|
|||||||
existingAccessory.displayName
|
existingAccessory.displayName
|
||||||
);
|
);
|
||||||
|
|
||||||
// this is imported from `platformAccessory.ts`
|
new MonitorAccessory(this, existingAccessory, locationMonitor);
|
||||||
new MonitorAccessory(this, existingAccessory);
|
|
||||||
|
|
||||||
// update accessory cache with any changes to the accessory details and information
|
|
||||||
this.api.updatePlatformAccessories([existingAccessory]);
|
this.api.updatePlatformAccessories([existingAccessory]);
|
||||||
} else {
|
} else {
|
||||||
// the accessory does not yet exist, so we need to create it
|
this.log.info("Adding new accessory:", `${room.name}+${label}`);
|
||||||
this.log.info("Adding new accessory:", `${room}+${label}`);
|
|
||||||
|
|
||||||
// create a new accessory
|
// create a new accessory
|
||||||
const accessory = new this.api.platformAccessory(
|
const accessory = new this.api.platformAccessory(
|
||||||
`${room}+${label}`,
|
`${room.name} ${label}`,
|
||||||
uuid
|
uuid
|
||||||
);
|
);
|
||||||
|
|
||||||
// store a copy of the device object in the `accessory.context`
|
accessory.context["DeviceName"] = `${room.name} ${label}`;
|
||||||
// the `context` property can be used to store any data about the accessory you may need
|
|
||||||
// accessory.context.device = device;
|
|
||||||
|
|
||||||
// create the accessory handler for the newly create accessory
|
// create the accessory handler for the newly create accessory
|
||||||
// this is imported from `platformAccessory.ts`
|
// this is imported from `platformAccessory.ts`
|
||||||
new MonitorAccessory(this, accessory);
|
new MonitorAccessory(this, accessory, locationMonitor);
|
||||||
|
|
||||||
// link the accessory to your platform
|
// link the accessory to your platform
|
||||||
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
|
||||||
@ -152,73 +139,6 @@ export class HomeLocationPlatform implements DynamicPlatformPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over the discovered devices and register each one if it has not already been registered
|
|
||||||
for (const device of exampleDevices) {
|
|
||||||
// generate a unique id for the accessory this should be generated from
|
|
||||||
// something globally unique, but constant, for example, the device serial
|
|
||||||
// number or MAC address
|
|
||||||
const uuid = this.api.hap.uuid.generate(device.exampleUniqueId);
|
|
||||||
|
|
||||||
// see if an accessory with the same uuid has already been registered and restored from
|
|
||||||
// the cached devices we stored in the `configureAccessory` method above
|
|
||||||
const existingAccessory = this.accessories.find(
|
|
||||||
(accessory) => accessory.UUID === uuid
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingAccessory) {
|
|
||||||
// the accessory already exists
|
|
||||||
if (device) {
|
|
||||||
this.log.info(
|
|
||||||
"Restoring existing accessory from cache:",
|
|
||||||
existingAccessory.displayName
|
|
||||||
);
|
|
||||||
|
|
||||||
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
||||||
// existingAccessory.context.device = device;
|
|
||||||
// this.api.updatePlatformAccessories([existingAccessory]);
|
|
||||||
|
|
||||||
// create the accessory handler for the restored accessory
|
|
||||||
// this is imported from `platformAccessory.ts`
|
|
||||||
new MonitorAccessory(this, existingAccessory);
|
|
||||||
|
|
||||||
// update accessory cache with any changes to the accessory details and information
|
|
||||||
this.api.updatePlatformAccessories([existingAccessory]);
|
|
||||||
} else if (!device) {
|
|
||||||
// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
|
|
||||||
// remove platform accessories when no longer present
|
|
||||||
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
|
|
||||||
existingAccessory,
|
|
||||||
]);
|
|
||||||
this.log.info(
|
|
||||||
"Removing existing accessory from cache:",
|
|
||||||
existingAccessory.displayName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// the accessory does not yet exist, so we need to create it
|
|
||||||
this.log.info("Adding new accessory:", device.exampleDisplayName);
|
|
||||||
|
|
||||||
// create a new accessory
|
|
||||||
const accessory = new this.api.platformAccessory(
|
|
||||||
device.exampleDisplayName,
|
|
||||||
uuid
|
|
||||||
);
|
|
||||||
|
|
||||||
// store a copy of the device object in the `accessory.context`
|
|
||||||
// the `context` property can be used to store any data about the accessory you may need
|
|
||||||
accessory.context.device = device;
|
|
||||||
|
|
||||||
// create the accessory handler for the newly create accessory
|
|
||||||
// this is imported from `platformAccessory.ts`
|
|
||||||
new MonitorAccessory(this, accessory);
|
|
||||||
|
|
||||||
// link the accessory to your platform
|
|
||||||
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
|
|
||||||
accessory,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async trainModels(): Promise<FaceMatcher> {
|
private async trainModels(): Promise<FaceMatcher> {
|
||||||
|
@ -6,4 +6,4 @@ export const PLATFORM_NAME = "HomeLocation";
|
|||||||
/**
|
/**
|
||||||
* This must match the name of your plugin as defined the package.json
|
* This must match the name of your plugin as defined the package.json
|
||||||
*/
|
*/
|
||||||
export const PLUGIN_NAME = "homebridge-home-location";
|
export const PLUGIN_NAME = "homebridge-face-location";
|
||||||
|
Loading…
Reference in New Issue
Block a user