Successfully creating a database if it does not already exist

This commit is contained in:
watsonb8 2019-09-22 15:07:39 -04:00
parent b688b365fb
commit 0fc390c713
9 changed files with 1773 additions and 55 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules node_modules
bin bin
automation.db

1
automation.db.sqbpro Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><sqlb_project><db path="/Users/brandonwatson/Documents/Gitlab/Home/homebridge-automation/automation.db" foreign_keys="1" case_sensitive_like="0" temp_store="0" wal_autocheckpoint="1000" synchronous="2"/><attached/><window><current_tab id="0"/></window><tab_structure><column_width id="0" width="300"/><column_width id="1" width="0"/><column_width id="2" width="100"/><column_width id="3" width="1453"/><column_width id="4" width="0"/><expanded_item id="0" parent="1"/><expanded_item id="1" parent="1"/><expanded_item id="2" parent="1"/><expanded_item id="3" parent="1"/></tab_structure><tab_browse><current_table name="event_service_instance_characteristics"/><default_encoding codec=""/><browse_table_settings/></tab_browse><tab_sql><sql name="SQL 1"></sql><current_tab id="0"/></tab_sql></sqlb_project>

View File

@ -3,5 +3,10 @@
{ {
"path": "." "path": "."
} }
] ],
"settings": {
"files.exclude": {
"node_modules": true
}
}
} }

1665
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,15 +25,19 @@
"dependencies": { "dependencies": {
"@types/bonjour": "^3.5.5", "@types/bonjour": "^3.5.5",
"@types/inflection": "^1.5.28", "@types/inflection": "^1.5.28",
"@types/knex": "^0.16.1",
"@types/request-promise": "^4.1.44", "@types/request-promise": "^4.1.44",
"@types/request-promise-native": "^1.0.16", "@types/request-promise-native": "^1.0.16",
"@types/sqlite3": "^3.1.5",
"bonjour": "^3.5.0", "bonjour": "^3.5.0",
"decamelize": "^3.2.0", "decamelize": "^3.2.0",
"inflection": "^1.12.0", "inflection": "^1.12.0",
"knex": "^0.19.4",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"request": "^2.88.0", "request": "^2.88.0",
"request-promise-native": "^1.0.7", "request-promise-native": "^1.0.7",
"source-map-support": "^0.5.13", "source-map-support": "^0.5.13",
"sqlite3": "^4.1.0",
"tsyringe": "^3.3.0" "tsyringe": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -55,16 +55,16 @@ export class HapMonitor extends EventEmitter {
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` + this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` +
`Got Event: ${JSON.stringify(body.characteristics)}`); `Got Event: ${JSON.stringify(body.characteristics)}`);
const response = body.characteristics.map((c: CharacteristicType): IServiceType | undefined => { const response: Array<IServiceType> = body.characteristics.map((charType: CharacteristicType): IServiceType | undefined => {
// find the matching service for each characteristics // find the matching service for each characteristics
const service = this.services.find(x => x.aid === c.aid && x.instance.username === instance.username); const service = this.services.find(x => x.aid === charType.aid && x.instance.username === instance.username);
if (service) { if (service) {
// find the correct characteristic and update it // find the correct characteristic and update it
const characteristic = service.serviceCharacteristics.find(x => x.iid === c.iid); const characteristic = service.serviceCharacteristics.find(x => x.iid === charType.iid);
if (characteristic) { if (characteristic) {
characteristic.value = c.value; characteristic.value = charType.value;
service.values[characteristic.type] = c.value; service.values[characteristic.type] = charType.value;
return service; return service;
} }
} }
@ -74,7 +74,7 @@ export class HapMonitor extends EventEmitter {
}); });
// push update to listeners // push update to listeners
this.emit('service-update', response.filter((x: unknown) => x)); this.emit('service-updated', response.filter((service: IServiceType) => service));
} }
} catch (e) { } catch (e) {
// do nothing // do nothing

3
src/Models/IConfig.ts Normal file
View File

@ -0,0 +1,3 @@
export interface IConfig {
databaseLocation?: string;
}

View File

@ -4,13 +4,15 @@ import { log, Homebridge } from './Types/types';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { container } from 'tsyringe'; import { container } from 'tsyringe';
import { Monitor } from './Services'; import { Monitor } from './Services';
import { IConfig } from './Models/IConfig';
import Knex = require('knex');
class AutomationPlatform { class AutomationPlatform {
private log: log; private log: log;
private config: {} = {}; private config: IConfig;
private api: EventEmitter; private api: EventEmitter;
constructor(log: log, config: {}, api: EventEmitter) { constructor(log: log, config: IConfig, api: EventEmitter) {
this.log = log; this.log = log;
this.config = config; this.config = config;
this.api = api; this.api = api;
@ -30,7 +32,11 @@ class AutomationPlatform {
private main = (): void => { private main = (): void => {
//Register the log function for DI //Register the log function for DI
container.register("log", { useValue: this.log }); container.register("log", { useValue: this.log });
container.register<IConfig>("config", { useValue: this.config });
//Resolve singleton instances
container.resolve(Monitor); container.resolve(Monitor);
} }
/** /**

View File

@ -1,21 +1,136 @@
import { HapClient } from "../HapClient"; import { HapClient, HapMonitor } from "../HapClient";
import { log } from '../Types/types'; import { log } from '../Types/types';
import { singleton, inject } from 'tsyringe'; import { singleton, inject, container } from 'tsyringe';
import { IServiceType } from "../HapClient/interfaces";
import { IConfig } from "../Models/IConfig";
import { Database } from "sqlite3";
import { mkdirSync } from 'fs';
import { join } from 'path';
import Knex = require("knex");
@singleton() @singleton()
export default class Monitor { export default class Monitor {
private log: log; private log: log;
private api: any; private config: IConfig
private client: HapClient; private client: HapClient;
private pin = "031-45-154";
private databaseLocation = `/Users/brandonwatson/.homebridge/automation`;
private databaseName = 'automation.db';
private db?: Database;
private knex?: Knex;
constructor(@inject("log") log: log) { constructor(@inject("log") log: log, @inject("config") config: IConfig) {
this.log = log; this.log = log;
this.config = config;
this.client = new HapClient({ this.client = new HapClient({
pin: "031-45-154", pin: this.pin,
logger: this.log, logger: this.log,
config: {} config: {}
}); });
//Overwrite default db location
if (config.databaseLocation) {
this.databaseLocation = config.databaseLocation;
}
this.initializeDatabase().catch((err) => {
this.log(`Error connecting to sqlite database: ${err}`);
});
this.initializeHapMonitor();
}
private get dbFullPath(): string {
return join(this.databaseLocation, this.databaseName);
}
private initializeHapMonitor = async (): Promise<void> => {
await this.client.discover();
const services: Array<IServiceType> = await this.client.getAllServices();
const hapMonitor = new HapMonitor(this.log, this.log, this.pin, services);
//Set service updated event
hapMonitor.on('service-updated', this.onServiceUpdated);
this.log("Monitor ready");
}
private initializeDatabase = async (): Promise<void> => {
try {
mkdirSync(this.databaseLocation);
} catch (err) {
if (err.code !== 'EEXIST') {
throw err;
}
}
try {
await this.initDbFile(this.dbFullPath);
} catch (err) {
throw err;
}
this.knex = Knex({
client: 'sqlite3',
connection: {
filename: this.dbFullPath
}
});
container.register<Knex>('knex', { useValue: this.knex });
const hasTables = await this.knex.schema.hasTable('events');
if (!hasTables) {
//create databse tables
await this.knex.raw(`CREATE TABLE "event_service_instance_characteristics" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"instance_id" INTEGER NOT NULL,
"key" TEXT NOT NULL,
"type" TEXT NOT NULL,
"value" BLOB NOT NULL)`);
await this.knex.raw(`CREATE TABLE "event_service_instances" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"event_id" INTEGER NOT NULL,
"service_id" INTEGER NOT NULL)`);
await this.knex.raw(`CREATE TABLE "events" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"timestamp" BLOB NOT NULL)`);
await this.knex.raw(`CREATE TABLE "services" (
"id" INTEGER NOT NULL UNIQUE,
"uniqueId" TEXT NOT NULL UNIQUE,
"uuid" TEXT NOT NULL UNIQUE,
"type" TEXT NOT NULL,
"humanType" TEXT NOT NULL,
"serviceName" TEXT NOT NULL)`);
}
console.log();
};
private initDbFile = (path: string): Promise<Database> => {
return new Promise((resolve, reject): void => {
const db: Database = new Database(path, (err): void => {
if (err) {
return reject(err);
} else {
return resolve(db);
}
});
});
}
private syncDatabase = async (): Promise<void> => {
}
private onServiceUpdated = (updatedServices: Array<IServiceType>): void => {
console.log("asdf");
} }
} }