Fixed linting errors (Not tested)

This commit is contained in:
watsonb8 2019-09-07 22:06:45 -04:00
parent b836178356
commit 423be484b2
10 changed files with 279 additions and 259 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
**/HAPNodeJS.d.ts

View File

@ -6,81 +6,84 @@
// Borrowed and heaviliy modifed from https://github.com/miguelmota/http-message-parser
import { Buffer } from 'buffer';
import { Dictionary } from '../../../Types/types';
import { Dictionary } from '../../Types/types';
interface httpResult {
protocol?: string,
httpVersion?: number,
statusCode?: number,
statusMessage?: string,
method?: string,
url?: string,
headers?: Dictionary<string | number>,
body?: any,
boundary?: any,
multipart?: any,
additional?: any,
meta?: any
interface IHttpResult {
protocol?: string;
httpVersion?: number;
statusCode?: number;
statusMessage?: string;
method?: string;
url?: string;
headers?: Dictionary<string | number>;
//eslint-disable-next-line
body?: any;
//eslint-disable-next-line
boundary?: any;
//eslint-disable-next-line
multipart?: any;
//eslint-disable-next-line
additional?: any;
//eslint-disable-next-line
meta?: any;
}
function httpMessageParser(message: any) {
const result: httpResult = {}
export default class HttpMessageParser {
private static requestLineRegex = /(HTTP|EVENT)\/(1\.0|1\.1|2\.0)\s+(\d+)\s+([\w\s-_]+)/i;
private static responseLineRegex = /(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE|CONNECT)\s+(.*)\s+HTTP\/(1\.0|1\.1|2\.0)/i;
private static headerNewlineRegex = /^[\r\n]+/gim;
private static boundaryRegex = /(\n|\r\n)+--[\w-]+(\n|\r\n)+/g;
let messageString = '';
let headerNewlineIndex = 0;
let fullBoundary: any = null;
//eslint-disable-next-line
public static parse(message: any): IHttpResult {
const result: IHttpResult = {};
if (httpMessageParser._isBuffer(message)) {
messageString = message.toString();
} else if (typeof message === 'string') {
messageString = message;
message = new Buffer(messageString);
} else {
return result;
}
let messageString = '';
let headerNewlineIndex = 0;
//eslint-disable-next-line
let fullBoundary: any = null;
/*
* Strip extra return characters
*/
messageString = messageString.replace(/\r\n/gim, '\n');
/*
* Trim leading whitespace
*/
(function () {
const firstNonWhitespaceRegex = /[\w-]+/gim;
const firstNonWhitespaceIndex = messageString.search(firstNonWhitespaceRegex);
if (firstNonWhitespaceIndex > 0) {
message = message.slice(firstNonWhitespaceIndex, message.length);
if (this.isBuffer(message)) {
messageString = message.toString();
} else if (typeof message === 'string') {
messageString = message;
message = new Buffer(messageString);
} else {
return result;
}
})();
/* Parse request line
*/
(function () {
/*
* Strip extra return characters
*/
messageString = messageString.replace(/\r\n/gim, '\n');
messageString = this.trim(messageString);
/* Parse request line
*/
const possibleRequestLine = messageString.split(/\n|\r\n/)[0];
const requestLineMatch = possibleRequestLine.match(httpMessageParser._requestLineRegex);
const requestLineMatch = possibleRequestLine.match(this.requestLineRegex);
/* Parse request line
*/
if (Array.isArray(requestLineMatch) && requestLineMatch.length > 1) {
result.protocol = requestLineMatch[1];
result.httpVersion = parseFloat(requestLineMatch[2]);
result.statusCode = parseInt(requestLineMatch[3], 10);
result.statusMessage = requestLineMatch[4];
} else {
const responseLineMath = possibleRequestLine.match(httpMessageParser._responseLineRegex);
const responseLineMath = possibleRequestLine.match(this.responseLineRegex);
if (Array.isArray(responseLineMath) && responseLineMath.length > 1) {
result.method = responseLineMath[1];
result.url = responseLineMath[2];
result.httpVersion = parseFloat(responseLineMath[3]);
}
}
})();
/* Parse headers
*/
(function () {
headerNewlineIndex = messageString.search(httpMessageParser._headerNewlineRegex);
/* Parse headers
*/
headerNewlineIndex = messageString.search(this.headerNewlineRegex);
if (headerNewlineIndex > -1) {
headerNewlineIndex = headerNewlineIndex + 1; // 1 for newline length
} else {
@ -93,20 +96,18 @@ function httpMessageParser(message: any) {
}
const headersString = messageString.substr(0, headerNewlineIndex);
const headers = httpMessageParser._parseHeaders(headersString);
const headers = this.parseHeaders(headersString);
if (Object.keys(headers).length > 0) {
result.headers = headers;
// TOOD: extract boundary.
}
})();
/* Try to get boundary if no boundary header
*/
(function () {
/* Try to get boundary if no boundary header
*/
if (!result.boundary) {
const boundaryMatch = messageString.match(httpMessageParser._boundaryRegex);
const boundaryMatch = messageString.match(this.boundaryRegex);
if (Array.isArray(boundaryMatch) && boundaryMatch.length) {
fullBoundary = boundaryMatch[0].replace(/[\r\n]+/gi, '');
@ -114,13 +115,11 @@ function httpMessageParser(message: any) {
result.boundary = boundary;
}
}
})();
/* Parse body
*/
(function () {
/* Parse body
*/
let start = headerNewlineIndex;
let contentLength: number = result.headers!['Content-Length'] as number;
const contentLength: number = result.headers!['Content-Length'] as number;
let end = (result.headers && result.headers['Content-Length'] && contentLength ? contentLength + start : messageString.length);
@ -154,11 +153,9 @@ function httpMessageParser(message: any) {
}
}
}
})();
/* Parse multipart sections
*/
(function () {
/* Parse multipart sections
*/
if (result.boundary) {
const multipartStart = messageString.indexOf(fullBoundary) + fullBoundary.length;
const multipartEnd = messageString.lastIndexOf(fullBoundary);
@ -166,9 +163,9 @@ function httpMessageParser(message: any) {
const splitRegex = new RegExp('^' + fullBoundary + '.*[\n\r]?$', 'gm');
const parts = multipartBody.split(splitRegex);
result.multipart = parts.filter(httpMessageParser._isTruthy).map(function (part, i) {
result.multipart = parts.filter(this.isTruthy).map(function (part, i) {
// tslint:disable-next-line: no-shadowed-variable
const result: httpResult = {};
const result: IHttpResult = {};
const newlineRegex = /\n\n|\r\n\r\n/gim;
let newlineIndex = 0;
@ -191,7 +188,7 @@ function httpMessageParser(message: any) {
let endOffset = null;
if (newlineIndex > -1) {
const headers = httpMessageParser._parseHeaders(possibleHeadersString);
const headers = HttpMessageParser.parseHeaders(possibleHeadersString);
if (Object.keys(headers).length > 0) {
result.headers = headers;
@ -231,68 +228,73 @@ function httpMessageParser(message: any) {
return result;
});
}
})();
return result;
}
return result;
httpMessageParser._isTruthy = function _isTruthy(value: any) {
return !!value;
};
httpMessageParser._isNumeric = function _isNumeric(value: any) {
if (typeof value === 'number' && !isNaN(value)) {
return true;
}
value = (value || '').toString().trim();
if (!value) {
return false;
}
return !isNaN(value);
};
httpMessageParser._isBuffer = function (item: any) {
return ((httpMessageParser._isNodeBufferSupported() &&
typeof global === 'object' &&
global.Buffer.isBuffer(item)) ||
(item instanceof Object &&
item._isBuffer));
};
httpMessageParser._isNodeBufferSupported = function () {
return (typeof global === 'object' &&
typeof global.Buffer === 'function' &&
typeof global.Buffer.isBuffer === 'function');
};
httpMessageParser._parseHeaders = function _parseHeaders(body: any) {
const headers: Dictionary<string | number> = {};
if (typeof body !== 'string') {
return headers;
}
body.split(/[\r\n]/).forEach(function (string) {
const match = string.match(/([\w-]+):\s*(.*)/i);
if (Array.isArray(match) && match.length === 3) {
const key = match[1];
const value = match[2];
headers[key] = httpMessageParser._isNumeric(value) ? Number(value) : value;
private static trim(str: string): string {
const firstNonWhitespaceRegex = /[\w-]+/gim;
const firstNonWhitespaceIndex = str.search(firstNonWhitespaceRegex);
let tmpStr = "";
if (firstNonWhitespaceIndex > 0) {
tmpStr = str.slice(firstNonWhitespaceIndex, str.length);
str = tmpStr.toString();
}
});
return headers;
};
return str;
}
httpMessageParser._requestLineRegex = /(HTTP|EVENT)\/(1\.0|1\.1|2\.0)\s+(\d+)\s+([\w\s-_]+)/i;
httpMessageParser._responseLineRegex = /(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE|CONNECT)\s+(.*)\s+HTTP\/(1\.0|1\.1|2\.0)/i;
// httpMessageParser._headerNewlineRegex = /^[\r\n]+/gim;
httpMessageParser._headerNewlineRegex = /^[\r\n]+/gim;
httpMessageParser._boundaryRegex = /(\n|\r\n)+--[\w-]+(\n|\r\n)+/g;
private static isTruthy = function _isTruthy(value: any): boolean {
return !!value;
};
export default httpMessageParser;
private static isNumeric = function _isNumeric(value: any): boolean {
if (typeof value === 'number' && !isNaN(value)) {
return true;
}
value = (value || '').toString().trim();
if (!value) {
return false;
}
return !isNaN(value);
};
private static isBuffer = (item: any): boolean => {
return ((HttpMessageParser.isNodeBufferSupported() &&
typeof global === 'object' &&
global.Buffer.isBuffer(item)) ||
(item instanceof Object &&
item._isBuffer));
};
private static isNodeBufferSupported = (): boolean => {
return (typeof global === 'object' &&
typeof global.Buffer === 'function' &&
typeof global.Buffer.isBuffer === 'function');
};
private static parseHeaders = (body: any): Dictionary<string | number> => {
const headers: Dictionary<string | number> = {};
if (typeof body !== 'string') {
return headers;
}
body.split(/[\r\n]/).forEach(function (string) {
const match = string.match(/([\w-]+):\s*(.*)/i);
if (Array.isArray(match) && match.length === 3) {
const key = match[1];
const value = match[2];
headers[key] = HttpMessageParser.isNumeric(value) ? Number(value) : value;
}
});
return headers;
};
}

View File

@ -5,8 +5,8 @@
import * as net from 'net';
import * as url from 'url';
import httpMessageParser from './/httpParser';
import { Dictionary } from '../../../Types/types';
import HttpMessageParser from './httpParser';
import { Dictionary } from '../../Types/types';
interface IRequest {
method: 'PUT' | 'POST' | 'GET' | 'DELETE' | 'PATCH';
@ -16,7 +16,34 @@ interface IRequest {
body: string;
}
export const parseMessage = httpMessageParser;
export const parseMessage = HttpMessageParser.parse;
function _headersToString(headers: Dictionary<string>): string {
let response = '';
for (const header of Object.keys(headers)) {
response = response + header + ': ' + headers[header] + '\r\n';
}
return (response);
}
function _buildMessage(request: IRequest): string {
const context = url.parse(request.url);
let message;
message = request.method + ' ' + context.pathname;
if (context.search) {
message = message + context.search;
}
message = message + ' HTTP/1.1\r\nHost: ' + context.host + '\r\n' + _headersToString(request.headers);
if (request.body) {
message = message + 'Content-Length: ' + request.body.length + '\r\n\r\n' + request.body + '\r\n\r\n';
} else {
message = message + '\r\n\r\n';
}
// debug("Message ->", message);
return (message);
}
/**
* Create a socket connection.
@ -24,7 +51,7 @@ export const parseMessage = httpMessageParser;
* @param pin The authorization token
* @param body The connection body
*/
export function createConnection(instance: { ipAddress: string, port: number }, pin: string, body: any): net.Socket {
export function createConnection(instance: { ipAddress: string; port: number }, pin: string, body: unknown): net.Socket {
const client: net.Socket = net.createConnection({
host: instance.ipAddress,
port: instance.port,
@ -44,30 +71,3 @@ export function createConnection(instance: { ipAddress: string, port: number },
return client;
}
function _headersToString(headers: Dictionary<string>) {
let response = '';
for (const header of Object.keys(headers)) {
response = response + header + ': ' + headers[header] + '\r\n';
}
return (response);
}
function _buildMessage(request: IRequest) {
const context = url.parse(request.url);
let message;
message = request.method + ' ' + context.pathname;
if (context.search) {
message = message + context.search;
}
message = message + ' HTTP/1.1\r\nHost: ' + context.host + '\r\n' + _headersToString(request.headers);
if (request.body) {
message = message + 'Content-Length: ' + request.body.length + '\r\n\r\n' + request.body + '\r\n\r\n';
} else {
message = message + '\r\n\r\n';
}
// debug("Message ->", message);
return (message);
}

View File

@ -1,4 +1,4 @@
import { Dictionary } from "../../Types/types";
import { Dictionary } from "../Types/types";
/* This file is automatically generated */

View File

@ -2,35 +2,37 @@ import 'source-map-support/register';
import * as crypto from 'crypto';
import decamelize from 'decamelize';
import * as inflection from 'inflection';
import Bonjour, { Service } from 'bonjour';
import { EventEmitter } from 'events';
import Bonjour from 'bonjour';
import { get, put } from 'request-promise-native';
import { Services, Characteristics } from './hap-types';
import { HapMonitor } from './monitor';
import { HapMonitor } from './hapMonitor';
import { IHapAccessoriesRespType, IServiceType, ICharacteristicType, IHapInstance, createDefaultCharacteristicType, IAccessoryResp } from './interfaces';
import { log, Dictionary } from '../Types/types';
export type HapAccessoriesRespType = IHapAccessoriesRespType;
export type ServiceType = IServiceType;
export type CharacteristicType = ICharacteristicType;
export interface IDevice {
addresses: Array<string>
fqdn: string,
host: string,
name: string,
port: number,
protocol: "tcp" | "udp",
rawTxt: Buffer,
addresses: Array<string>;
fqdn: string;
host: string;
name: string;
port: number;
protocol: "tcp" | "udp";
rawTxt: Buffer;
referer: {
address: string,
family: "IPv4" | "IPv6",
port: number,
size: number,
},
subtypes: Array<any>,
txt: any,
type: string
address: string;
family: "IPv4" | "IPv6";
port: number;
size: number;
};
// eslint-disable-next-line
subtypes: Array<any>;
// eslint-disable-next-line
txt: any;
type: string;
}
interface IConfig {
@ -63,8 +65,8 @@ export class HapClient {
constructor(opts: {
pin: string;
logger?: any;
config: any;
logger: log;
config: IConfig;
}) {
this.pin = opts.pin;
this.log = opts.logger;
@ -72,19 +74,19 @@ export class HapClient {
this.config = opts.config;
}
private debug(msg: any) {
private debug(msg: string): void {
if (this.debugEnabled) {
this.log(msg);
}
}
private debugErr(msg: string, err: Error) {
private debugErr(msg: string, err: Error): void {
if (this.debugEnabled) {
this.log(`${msg}: ${err.message}\n ${err.stack}`);
}
}
public refreshInstances() {
public refreshInstances(): void {
if (!this.discoveryInProgress) {
this.discover();
} else {
@ -99,7 +101,7 @@ export class HapClient {
}
public async discover(): Promise<void> {
return new Promise((resolve) => {
return new Promise((resolve): void => {
this.discoveryInProgress = true;
this.browser = this.bonjour.find({
@ -111,8 +113,9 @@ export class HapClient {
this.debug(`[HapClient] Discovery :: Started`);
// service found
this.browser.on('up', async (service: any) => {
let device = service as IDevice;
this.browser.on('up', async (service: Bonjour.Service) => {
const unknownService: unknown = service as unknown;
const device = unknownService as IDevice;
if (!device || !device.txt) {
this.debug(`[HapClient] Discovery :: Ignoring device that contains no txt records. ${JSON.stringify(device)}`);
return;
@ -124,7 +127,7 @@ export class HapClient {
name: device.txt.md,
username: device.txt.id,
port: device.port,
}
};
this.debug(`[HapClient] Discovery :: Found HAP device ${instance.displayName} with username ${instance.username}`);
@ -194,7 +197,7 @@ export class HapClient {
});
}
private humanizeString(string: string) {
private humanizeString(string: string): string {
return inflection.titleize(decamelize(string));
}
@ -210,7 +213,7 @@ export class HapClient {
resp.accessories && resp.accessories.forEach((accessory: IAccessoryResp) => {
accessory.instance = instance;
accessories.push(accessory);
})
});
} catch (e) {
if (this.log) {
this.debugErr(`[HapClient] [${instance.displayName} - ${instance.ipAddress}:${instance.port} (${instance.username})] Failed to connect`, e);
@ -236,7 +239,7 @@ export class HapClient {
/* Parse Accessory Information */
const accessoryInformationService = accessory.services.find(x => x.type === Services.AccessoryInformation);
const accessoryInformation: { [key: string]: any } = {};
const accessoryInformation: Dictionary<unknown> = {};
if (accessoryInformationService && accessoryInformationService.characteristics) {
accessoryInformationService.characteristics.forEach((c) => {
@ -272,7 +275,7 @@ export class HapClient {
uuid: c.type,
type: Characteristics[c.type],
serviceType: Services[s.type],
serviceName: serviceName!.value.toString(),
serviceName: serviceName && serviceName.value ? serviceName.value.toString() : "Service name not found",
description: c.description,
value: c.value,
format: c.format,
@ -307,7 +310,7 @@ export class HapClient {
.digest('hex');
/* Helper function to trigger a call to the accessory to get all the characteristic values */
service.refreshCharacteristics = () => {
service.refreshCharacteristics = (): Promise<IServiceType> => {
return this.refreshServiceCharacteristics.bind(this)(service);
};
@ -318,7 +321,7 @@ export class HapClient {
/* Helper function to returns a characteristic by it's type name */
service.getCharacteristic = (type: string): ICharacteristicType => {
let characteristic = service.serviceCharacteristics.find(c => c.type === type);
const characteristic = service.serviceCharacteristics.find(c => c.type === type);
return characteristic ? characteristic : createDefaultCharacteristicType();
};
@ -345,7 +348,7 @@ export class HapClient {
}
public getService(iid: number): Promise<IServiceType | undefined> {
return new Promise(async (resolve, reject) => {
return new Promise(async (resolve, reject): Promise<void> => {
try {
const services = await this.getAllServices();
return resolve(services.find(x => x.iid === iid));
@ -357,7 +360,7 @@ export class HapClient {
}
public async getServiceByName(serviceName: string): Promise<IServiceType | undefined> {
return new Promise(async (resolve, reject) => {
return new Promise(async (resolve, reject): Promise<void> => {
try {
const services = await this.getAllServices();
return resolve(services.find(x => x.serviceName === serviceName));
@ -379,7 +382,9 @@ export class HapClient {
resp.characteristics.forEach((charType: ICharacteristicType) => {
const characteristic = service.serviceCharacteristics.find(x => x.iid === charType.iid && x.aid === service.aid);
characteristic!.value = charType.value;
if (characteristic) {
characteristic.value = charType.value;
}
});
return service;
@ -435,6 +440,6 @@ export class HapClient {
}
}
return characteristic
return characteristic;
}
}

View File

@ -2,15 +2,16 @@ import { EventEmitter } from 'events';
import { IServiceType, IHapEvInstance } from './interfaces';
import { createConnection, parseMessage } from './eventedHttpClient';
import { CharacteristicType } from './hapClient';
import { log } from '../Types/types';
export class HapMonitor extends EventEmitter {
private pin: string;
private evInstances: IHapEvInstance[];
private services: IServiceType[];
private logger: any;
private debug: any;
private logger: log;
private debug: log;
constructor(logger: any, debug: any, pin: string, services: IServiceType[]) {
constructor(logger: log, debug: log, pin: string, services: IServiceType[]) {
super();
this.logger = logger;
this.debug = debug;
@ -28,7 +29,7 @@ export class HapMonitor extends EventEmitter {
/**
* Start monitoring
*/
public start() {
public start(): void {
for (const instance of this.evInstances) {
instance.socket = createConnection(instance, this.pin, { characteristics: instance.evCharacteristics });
@ -40,7 +41,7 @@ export class HapMonitor extends EventEmitter {
if (message.statusCode === 401) {
if (this.logger) {
this.logger.warn(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` +
this.logger(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` +
`${message.statusCode} ${message.statusMessage} - make sure Homebridge pin for this instance is set to ${this.pin}.`);
}
}
@ -71,7 +72,7 @@ export class HapMonitor extends EventEmitter {
});
// push update to listeners
this.emit('service-update', response.filter((x: any) => x));
this.emit('service-update', response.filter((x: unknown) => x));
}
} catch (e) {
// do nothing
@ -84,7 +85,7 @@ export class HapMonitor extends EventEmitter {
/**
* Stop monitoring.
*/
public stop() {
public stop(): void {
for (const instance of this.evInstances) {
if (instance.socket) {
try {
@ -97,7 +98,7 @@ export class HapMonitor extends EventEmitter {
}
}
private parseServices() {
private parseServices(): void {
// get a list of characteristics we can watch for each instance
for (const service of this.services) {
const evCharacteristics = service.serviceCharacteristics.filter(x => x.perms.includes('ev'));
@ -113,8 +114,10 @@ export class HapMonitor extends EventEmitter {
const instance = this.evInstances.find(x => x.username === service.instance.username);
for (const evCharacteristic of evCharacteristics) {
if (!instance!.evCharacteristics!.find(x => x.aid === service.aid && x.iid === evCharacteristic.iid)) {
instance!.evCharacteristics!.push({ aid: service.aid, iid: evCharacteristic.iid, ev: true });
if (instance &&
instance.evCharacteristics &&
!instance.evCharacteristics.find(x => x.aid === service.aid && x.iid === evCharacteristic.iid)) {
instance.evCharacteristics.push({ aid: service.aid, iid: evCharacteristic.iid, ev: true });
}
}
}

View File

@ -1 +1,14 @@
export type Dictionary<T> = { [key: string]: T };
import { EventEmitter } from "events";
export type Dictionary<T> = { [key: string]: T };
export type log = (msg: string) => void;
export type Homebridge = {
registerPlatform: (
platformName: string,
platformExtension: string,
platformClass: new (log: log, config: {}, api: EventEmitter) => void,
someBool: boolean
) => void;
}

View File

@ -1,65 +1,37 @@
import { HapClient } from "./3rdParty/HapClient/hapClient";
import { HapMonitor } from "./3rdParty/HapClient/monitor";
import { log, Homebridge } from './Types/types';
import { EventEmitter } from 'events';
let Accessory: any;
let Homebridge: any;
class AutomationPlatform {
private log: log;
private config: {} = {};
private api: EventEmitter;
constructor(log: log, config: {}, api: EventEmitter) {
this.log = log;
this.config = config;
this.api = api;
this.log('INFO - Registering automation platform');
this.api.on('didFinishLaunching', this.didFinishLaunching.bind(this));
}
/**
* Handler for didFinishLaunching
* Happens after constructor
*/
private didFinishLaunching(): void {
//No external accessories to publish
}
}
/**
* Main entry.
* @param homebridge
*/
export default function (homebridge: any) {
Homebridge = homebridge;
Accessory = homebridge.platformAccessory;
export default function (homebridge: Homebridge): void {
homebridge.registerPlatform(
'ml-automation',
'automation',
AutomationPlatform,
true
);
};
class AutomationPlatform {
log: any = {};
config: any = {};
api: any;
client: HapClient;
constructor(log: any, config: any, api: any) {
this.log = log;
this.config = config;
this.api = api;
this.log('INFO - Registering automation platform');
this.api.on('didFinishLaunching', this.didFinishLaunching.bind(this));
this.client = new HapClient({
pin: "031-45-154",
logger: log,
config: config
});
this.client.discover().then(async () => {
let asdf = await this.client.getAccessories();
let asdff = "asdf";
})
}
/**
* Handler for didFinishLaunching
* Happens after constructor
*/
didFinishLaunching() {
//No external accessories to publish
}
/**
* Called by homebridge to gather accessories.
* @param callback
*/
accessories(callback: (accessories: Array<any>) => void) {
}
}
};

24
src/services/monitor.ts Normal file
View File

@ -0,0 +1,24 @@
import { HapClient } from "../HapClient/hapClient";
import { log } from '../Types/types';
import { singleton } from 'tsyringe';
export interface IMonitorProps {
log: log;
}
@singleton()
export class Monitor {
private log: log;
private api: any;
private client: HapClient;
constructor(props: IMonitorProps) {
this.log = props.log;
this.client = new HapClient({
pin: "031-45-154",
logger: this.log,
config: {}
});
}
}