mirror of
https://github.com/mtan93/homebridge.git
synced 2026-04-04 06:13:13 +01:00
User storage and settings, more cli
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import Server from './server';
|
|
||||||
import program from 'commander';
|
import program from 'commander';
|
||||||
import { HOMEBRIDGE_VERSION } from '../homebridge';
|
import { HOMEBRIDGE_VERSION } from '../homebridge';
|
||||||
|
import { Server } from './server';
|
||||||
|
import { Provider } from './provider';
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
|
|
||||||
@@ -11,14 +12,59 @@ export default function() {
|
|||||||
// Run the HomeBridge server
|
// Run the HomeBridge server
|
||||||
program
|
program
|
||||||
.command('server')
|
.command('server')
|
||||||
.description('Run the HomeBridge server')
|
.description('Run the HomeBridge server.')
|
||||||
.action((options) => new Server(options).run());
|
.action(runServer);
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('providers')
|
||||||
|
.description('List installed providers.')
|
||||||
|
.action(listInstalledProviders);
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('setup [provider]')
|
||||||
|
.description('Sets up a new HomeBridge provider or re-configures an existing one.')
|
||||||
|
.action(setupProvider);
|
||||||
|
|
||||||
// Parse options and execute HomeBridge
|
// Parse options and execute HomeBridge
|
||||||
program.parse(process.argv);
|
program.parse(process.argv);
|
||||||
|
|
||||||
// Display help by default if no commands or options given
|
// Display help by default if no commands or options given
|
||||||
if (!process.argv.slice(2).length) {
|
if (!process.argv.slice(2).length) {
|
||||||
program.outputHelp();
|
program.help();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runServer(options) {
|
||||||
|
|
||||||
|
// get all installed providers
|
||||||
|
let providers:Array<Provider> = Provider.installed();
|
||||||
|
|
||||||
|
// load and validate providers - check for valid package.json, etc.
|
||||||
|
try {
|
||||||
|
this.providerModules = providers.map((provider) => provider.load());
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(err.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function listInstalledProviders(options) {
|
||||||
|
Provider.installed().forEach((provider) => console.log(provider.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupProvider(providerName, options) {
|
||||||
|
|
||||||
|
// if you didn't specify a provider, print help
|
||||||
|
if (!providerName) {
|
||||||
|
console.log("You must specify the name of the provider to setup. Type 'homebridge providers' to list the providers currently installed.");
|
||||||
|
program.help();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let provider = new Provider(providerName);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
|
import { User } from './user';
|
||||||
import { HOMEBRIDGE_VERSION } from '../homebridge';
|
import { HOMEBRIDGE_VERSION } from '../homebridge';
|
||||||
|
|
||||||
// This class represents a HomeBridge Provider that may or may not be installed.
|
// This class represents a HomeBridge Provider that may or may not be installed.
|
||||||
@@ -11,11 +12,16 @@ export class Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get path():string {
|
get path():string {
|
||||||
return path.join(Provider.installedProvidersDir, this.name);
|
return path.join(User.providersPath, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
load():object {
|
load():object {
|
||||||
|
|
||||||
|
// does this provider exist at all?
|
||||||
|
if (!fs.existsSync(this.path)) {
|
||||||
|
throw new Error(`Provider ${this.name} was not found. Make sure a directory matching the name '${this.name}' exists in your ~/.homebridge/providers folder.`)
|
||||||
|
}
|
||||||
|
|
||||||
// check for a package.json
|
// check for a package.json
|
||||||
let pjsonPath:string = path.join(this.path, "package.json");
|
let pjsonPath:string = path.join(this.path, "package.json");
|
||||||
let pjson:object = null;
|
let pjson:object = null;
|
||||||
@@ -52,6 +58,21 @@ export class Provider {
|
|||||||
// try to require() it
|
// try to require() it
|
||||||
let loadedProvider:object = require(mainPath);
|
let loadedProvider:object = require(mainPath);
|
||||||
|
|
||||||
|
// pull out the configuration data, if any
|
||||||
|
let providerConfig = loadedProvider.config;
|
||||||
|
|
||||||
|
// verify that all required values are present
|
||||||
|
if (providerConfig) {
|
||||||
|
for (let key:string in providerConfig) {
|
||||||
|
|
||||||
|
let configParams:object = providerConfig[key];
|
||||||
|
|
||||||
|
if (configParams.required && !User.config.get(`${this.name}-${key}`)) {
|
||||||
|
throw new Error(`Provider ${this.name} requires the config value ${key} to be set.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return loadedProvider;
|
return loadedProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,12 +80,12 @@ export class Provider {
|
|||||||
static installed():Array<Provider> {
|
static installed():Array<Provider> {
|
||||||
|
|
||||||
let providers:Array<Provider> = [];
|
let providers:Array<Provider> = [];
|
||||||
let names:Array<string> = fs.readdirSync(Provider.installedProvidersDir);
|
let names:Array<string> = fs.readdirSync(User.providersPath);
|
||||||
|
|
||||||
for (let name:string of names) {
|
for (let name:string of names) {
|
||||||
|
|
||||||
// reconstruct full path
|
// reconstruct full path
|
||||||
let fullPath:string = path.join(Provider.installedProvidersDir, name);
|
let fullPath:string = path.join(User.providersPath, name);
|
||||||
|
|
||||||
// we only care about directories
|
// we only care about directories
|
||||||
if (!fs.statSync(fullPath).isDirectory()) continue;
|
if (!fs.statSync(fullPath).isDirectory()) continue;
|
||||||
@@ -74,16 +95,4 @@ export class Provider {
|
|||||||
|
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Private utility functions
|
|
||||||
//
|
|
||||||
|
|
||||||
static get userDir():string {
|
|
||||||
return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get installedProvidersDir():string {
|
|
||||||
return path.join(Provider.userDir, ".homebridge/providers");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { Provider } from './provider';
|
import { Provider } from './provider';
|
||||||
|
import { User, Config } from './user';
|
||||||
|
|
||||||
export default class Server {
|
export class Server {
|
||||||
|
|
||||||
|
constructor(providers:object) {
|
||||||
|
this.providers = providers; // providers[name] = loaded provider JS module
|
||||||
|
}
|
||||||
|
|
||||||
run() {
|
run() {
|
||||||
// get all installed providers
|
|
||||||
let providers:Array<Provider> = Provider.installed();
|
|
||||||
|
|
||||||
// validate providers - check for valid package.json, etc.
|
|
||||||
providers.forEach((provider) => provider.load());
|
|
||||||
|
|
||||||
console.log(`Loaded ${providers.length} providers.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
lib/homebridge/user.js
Normal file
56
lib/homebridge/user.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Manages user settings and storage locations.
|
||||||
|
//
|
||||||
|
|
||||||
|
// global cached config
|
||||||
|
let config:Config;
|
||||||
|
|
||||||
|
export class User {
|
||||||
|
|
||||||
|
static get config():Config {
|
||||||
|
return config || (config = new Config());
|
||||||
|
}
|
||||||
|
|
||||||
|
static get storagePath():string {
|
||||||
|
let home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
|
||||||
|
return path.join(home, ".homebridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
static get configPath():string {
|
||||||
|
return path.join(User.storagePath, "config.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
static get providersPath():string {
|
||||||
|
return path.join(User.storagePath, "providers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Config {
|
||||||
|
|
||||||
|
constructor(data:object = {}) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key:string) {
|
||||||
|
return this.data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key:string, value:object) {
|
||||||
|
this.data[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static load():Config {
|
||||||
|
// load up the previous config if found
|
||||||
|
if (fs.existsSync(User.configPath))
|
||||||
|
return new Config(JSON.parse(fs.readFileSync(User.configPath)));
|
||||||
|
else
|
||||||
|
return new Config(); // empty initial config
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
fs.writeFileSync(User.configPath, JSON.stringify(this.data));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user