forked from the1laz/cgateweb
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
executable file
·153 lines (132 loc) · 5.28 KB
/
index.js
File metadata and controls
executable file
·153 lines (132 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env node
const CgateWebBridge = require('./src/cgateWebBridge');
const ConfigLoader = require('./src/config/ConfigLoader');
const HAIntegration = require('./src/config/HAIntegration');
const { defaultSettings } = require('./src/defaultSettings');
// --- Initialize Home Assistant Integration ---
const haIntegration = new HAIntegration();
const haConfig = haIntegration.initialize();
// --- Load Settings using ConfigLoader ---
let settings = { ...defaultSettings };
const configLoader = new ConfigLoader();
try {
const loadedConfig = configLoader.load();
settings = { ...defaultSettings, ...loadedConfig };
const envInfo = configLoader.getEnvironment();
console.log(`[INFO] Environment: ${envInfo.type}`);
if (haConfig.isAddon) {
console.log(`[INFO] Home Assistant optimizations: ${haConfig.optimizationsApplied.join(', ')}`);
if (haConfig.ingressConfig) {
console.log(`[INFO] Ingress configured: ${haConfig.ingressConfig.ingressUrl}`);
}
}
const source = loadedConfig._environment ? loadedConfig._environment.type : 'unknown';
console.log(`[INFO] Configuration loaded from: ${source}`);
} catch (error) {
console.error(`[ERROR] Failed to load configuration: ${error.message}`);
let envInfo;
try { envInfo = configLoader.getEnvironment(); } catch { /* ignore */ }
if (process.env.SUPERVISOR_TOKEN || (envInfo && envInfo.isAddon)) {
console.error('[ERROR] Please check the addon configuration and restart.');
process.exit(1);
}
const allowFallback = String(process.env.ALLOW_DEFAULT_FALLBACK || '').toLowerCase() === 'true';
if (!allowFallback) {
console.error('[ERROR] Standalone startup aborted due to invalid configuration.');
process.exit(1);
}
settings = { ...defaultSettings, ...configLoader.getDefaultConfig() };
console.error('[WARN] ALLOW_DEFAULT_FALLBACK=true set; using safe fallback settings only');
}
const envOverrides = {
MQTT_HOST: 'mqtt',
MQTT_USERNAME: 'mqttusername',
MQTT_PASSWORD: 'mqttpassword',
CGATE_IP: 'cbusip',
CGATE_USERNAME: 'cgateusername',
CGATE_PASSWORD: 'cgatepassword',
CGATE_PROJECT: 'cbusname',
};
for (const [envKey, settingKey] of Object.entries(envOverrides)) {
if (process.env[envKey] !== undefined) {
settings[settingKey] = process.env[envKey];
}
}
// Application startup
async function main() {
console.log('[INFO] Starting cgateweb...');
console.log(`[INFO] Version: ${require('./package.json').version}`);
// Auto-detect MQTT credentials from Supervisor API when running as an addon
const envInfo = configLoader.getEnvironment();
if (process.env.SUPERVISOR_TOKEN || (envInfo && envInfo.isAddon)) {
try {
await configLoader.applyMqttAutoDetection(settings);
} catch (error) {
console.error('[WARN] MQTT auto-detection failed:', error.message);
}
}
configLoader.validate(settings);
// Create and start the bridge
const bridge = new CgateWebBridge(settings);
// Graceful shutdown handling
const shutdown = (signal) => {
console.log(`[INFO] Received ${signal}, shutting down gracefully...`);
bridge.stop();
process.exit(0);
};
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGUSR1', () => {
console.log('[INFO] Received SIGUSR1, reloading configuration...');
try {
const reloaded = configLoader.load();
const newSettings = { ...defaultSettings, ...reloaded };
bridge.reloadSettings(newSettings);
console.log('[INFO] Configuration reloaded successfully');
} catch (error) {
console.error(`[ERROR] Failed to reload configuration: ${error.message}`);
}
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
console.error('[ERROR] Uncaught exception:', error);
bridge.stop();
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('[ERROR] Unhandled promise rejection at:', promise, 'reason:', reason);
bridge.stop();
process.exit(1);
});
// Start the bridge (async)
return bridge.start()
.then(() => {
if (typeof bridge._getBridgeStatus === 'function') {
const status = bridge._getBridgeStatus();
console.log(`[INFO] cgateweb started successfully (${status.lifecycle.state})`);
} else {
console.log('[INFO] cgateweb started successfully');
}
})
.catch(error => {
console.error('[ERROR] Failed to start bridge:', error);
process.exit(1);
});
}
// Only run if this script is executed directly
if (require.main === module || (require.main && require.main.filename === __filename)) {
main().catch(error => {
console.error('[FATAL] Unhandled error during startup:', error);
process.exit(1);
});
}
// Export classes for tests
const CBusEvent = require('./src/cbusEvent');
const CBusCommand = require('./src/cbusCommand');
module.exports = {
main,
defaultSettings,
CgateWebBridge,
CBusEvent,
CBusCommand
};