@pmouli/isy-matter-server
Version:
Service to expose an ISY device as a Matter Border router
202 lines (201 loc) • 7.84 kB
JavaScript
import path from 'path';
import chalk from 'chalk';
import { emphasize, findPackageJson } from 'isy-nodejs/Utils';
import './utils.js';
import { addClientLogTransport, handleExit, initialize, isyConfig, logger, matterConfig, options, serverConfig } from './utils.js';
var ServerState;
(function (ServerState) {
ServerState[ServerState["Stopped"] = 0] = "Stopped";
ServerState[ServerState["Starting"] = 1] = "Starting";
ServerState[ServerState["Running"] = 2] = "Running";
ServerState[ServerState["Stopping"] = 3] = "Stopping";
})(ServerState || (ServerState = {}));
let bridgeServerState = ServerState.Stopped;
let interfaceState = ServerState.Stopped;
let apiInfo = {};
let isy;
let serverNode;
export let pluginEnv;
export let matterServer;
export async function startBridgeServer() {
if (bridgeServerState === ServerState.Starting || bridgeServerState === ServerState.Running) {
logger.info(emphasize('Bridge server already starting or running'));
return;
}
if (!isyConfig || !matterConfig) {
logger.error('Missing configuration');
return;
}
if (isy || serverNode) {
logger.info(emphasize('Bridge already started/starting'));
return;
}
bridgeServerState = ServerState.Starting;
try {
logger.info(emphasize('Connecting to IoX'));
isy = await loadISYInterface();
//await isy.initialize();
logger.info(emphasize('Connected to IoX'));
serverNode = await loadBridgeServer();
//if (process.send) process.send({ pairingInfo: matterServer.getPairingCode() });
bridgeServerState = ServerState.Running;
logger.info(emphasize('Bridge started'));
logger.info('*'.repeat(80));
logger.info(`IoX firmware version: ${emphasize(isy.firmwareVersion)}`);
logger.info(`IoX model: ${emphasize(isy.productName)}`);
logger.info(`IoX model number: ${isy.productId}`);
logger.info(`IoX api version: ${emphasize(apiInfo.isy_nodejs.version)}`);
logger.info(`IoX to Matter api version: ${emphasize(apiInfo.isy_matter.version)}`);
logger.info(`Matter api version: ${emphasize(apiInfo.matter_js.version)}`);
logger.info('*'.repeat(80));
}
catch (e) {
bridgeServerState = ServerState.Stopped;
if (e instanceof Error) {
logger.error(`Error starting bridge: ${e.message}`, e);
}
else
logger.error(`Error starting bridge: ${e}`);
try {
await isy[Symbol.asyncDispose]();
isy = undefined;
}
finally {
try {
await serverNode.close();
await serverNode[Symbol.asyncDispose]();
serverNode = undefined;
}
catch { }
}
}
}
async function loadISYInterface() {
let modulePath = 'isy-nodejs/ISY';
if (options.dependencies === 'plugin') {
logger.info('Locating ISY api from plugin dependencies');
if (!pluginEnv) {
logger.error('Plugin environment not set');
}
else {
modulePath = path.resolve('isy-nodejs', 'node_modules', pluginEnv.PLUGIN_PATH);
logger.info('IoX api located: ' + modulePath);
}
}
logger.info('Loading IoX api from ' + modulePath);
let ISYNS = (await import(modulePath)).ISY;
let pj = await findPackageJson('isy-nodejs');
let apiMeta = { name: pj.name, version: pj.version, path: pj.path.toString() };
logger.info(`IoX api loaded`);
logApiInfo(apiMeta);
apiInfo.isy_nodejs = apiMeta;
return ISYNS.create(isyConfig, logger, serverConfig.workingDir);
}
async function logApiInfo(apiMeta) {
logger.info(`module: ${apiMeta.name}, version: ${apiMeta.version}, location: ${apiMeta.path}`);
}
async function loadBridgeServer() {
if (!matterServer) {
logger.info('Loading IoX to matter bridge api');
matterServer = await import('isy-matter/Bridge/Server');
let pj = await findPackageJson('isy-matter');
apiInfo.isy_matter = { name: pj.name, version: pj.version, path: pj.path.toString() };
let pj2 = await findPackageJson('@matter/main');
apiInfo.matter_js = { name: pj2.name, version: pj2.version, path: pj2.path.toString() };
logger.info(`IoX to matter bridge & matter.js api loaded`);
logApiInfo(apiInfo.isy_matter);
logApiInfo(apiInfo.matter_js);
}
logger.info(emphasize('Starting bridge'));
return matterServer.create(isy, matterConfig);
}
export async function stopBridgeServer() {
const startState = bridgeServerState;
try {
if (!isy || !serverNode || startState === ServerState.Stopped) {
logger.info(chalk.white.bold('Matter bridge not started. Nothing to stop.'));
return;
}
if (startState === ServerState.Stopping) {
logger.info(chalk.white.bold('Bridge already stopping'));
return;
}
bridgeServerState = ServerState.Stopping;
if (isy) {
logger.info(chalk.white.bold('Disconnecting from ISY'));
await isy[Symbol.asyncDispose]();
isy = undefined;
logger.info(chalk.white.bold('Disconnected from ISY'));
}
if (serverNode) {
logger.info(chalk.white.bold('Stopping bridge'));
//await serverNode.prepareRuntimeShutdown();
await serverNode.env.runtime.close();
//await serverNode.close();
//await serverNode[Symbol.asyncDispose]();
serverNode = undefined;
matterServer = undefined;
logger.info(chalk.white.bold('Bridge stopped'));
}
bridgeServerState = ServerState.Stopped;
}
catch (e) {
logger.error(`Error stopping bridge server ${e.message}`, e);
//bridgeServerState = ServerState.Stopping;
}
}
/*process.on('SIGTERM', async () => {
if (exiting) {
logger.info('SIGTERM received again, exiting');
process.exit(0);
}
logger.info('SIGTERM received, stopping bridge server');
await stopBridgeServer();
process.exit(0);
});*/
let client;
process.on('uncaughtException', async (err) => {
logger.error('Uncaught exception: ' + err.message, err);
});
await initialize();
if (serverConfig.subprocess) {
logger.info('Running in subprocess');
logger.info(`args: [${process.argv.join(', ')}]`);
if (options.openSocket) {
addClientLogTransport(process);
}
await startBridgeServer();
if (process.send) {
process.send('Matter bridge started');
process.send({ pairingInfo: matterServer.getPairingCode() });
}
process.on('SIGABRT', handleExit(stopBridgeServer));
process.on('SIGINT', async () => {
logger.info('SIGINT received, doing nothing. Waiting for abort from parent');
});
process.on('SIGTERM', async () => {
logger.info('SIGTERM received, doing nothing. Waiting for abort from parent');
});
/*process.on('message', async (message, socket: Socket) => {
if (message === 'client') {
addClientLogTransport(process);
logger.info('Client logger connected');
client = socket;
await startBridgeServer();
socket.write(JSON.stringify({ pairingInfo: matterServer.getPairingCode() }));
}
});*/
/*process.on('disconnect', async () => {
logger.info('parent disconnected. removing client log transport');
if (clientLogTransport) {
removeClientLogTransport();
}
//ogger.info('Matter bridge server stopped');
//process.exit(0);
});*/
}
//main();
//# sourceMappingURL=server.js.map
//# sourceMappingURL=server.js.map
//# sourceMappingURL=server.js.map