Working debug configuration

This commit is contained in:
watsonb8 2020-11-30 20:55:31 -05:00
parent 3ccf85cb00
commit e047ef6549
9 changed files with 56 additions and 120 deletions

23
.vscode/launch.json vendored
View File

@ -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
View File

@ -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 ."
} }
] ]
} }

View File

@ -5,6 +5,7 @@
} }
], ],
"settings": { "settings": {
"editor.tabSize": 2 "editor.tabSize": 2,
"debug.javascript.unmapMissingSources": true
} }
} }

View File

@ -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"
} }
} }

View File

@ -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
); );
}; };

View File

@ -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

View File

@ -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> {

View File

@ -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";