feat(daemon): add serial console reader and UI tab for serial logs; add version propagation and CI/release workflows
This commit is contained in:
@@ -8,6 +8,7 @@ import { ProcessManager } from './process-manager.ts';
|
||||
import { SystemInfo } from './system-info.ts';
|
||||
import { UIServer } from '../ui/server.ts';
|
||||
import { runCommand } from '../utils/command.ts';
|
||||
import { VERSION } from '../version.ts';
|
||||
|
||||
export interface DaemonConfig {
|
||||
uiPort: number;
|
||||
@@ -29,6 +30,7 @@ export class EcoDaemon {
|
||||
private systemInfo: SystemInfo;
|
||||
private uiServer: UIServer;
|
||||
private logs: string[] = [];
|
||||
private serialLogs: string[] = [];
|
||||
private swayStatus: ServiceStatus = { state: 'stopped' };
|
||||
private chromiumStatus: ServiceStatus = { state: 'stopped' };
|
||||
private manualRestartUntil: number = 0; // Timestamp until which auto-restart is disabled
|
||||
@@ -62,15 +64,21 @@ export class EcoDaemon {
|
||||
return [...this.logs];
|
||||
}
|
||||
|
||||
getSerialLogs(): string[] {
|
||||
return [...this.serialLogs];
|
||||
}
|
||||
|
||||
async getStatus(): Promise<Record<string, unknown>> {
|
||||
const systemInfo = await this.systemInfo.getInfo();
|
||||
return {
|
||||
version: VERSION,
|
||||
sway: this.swayStatus.state === 'running',
|
||||
swayStatus: this.swayStatus,
|
||||
chromium: this.chromiumStatus.state === 'running',
|
||||
chromiumStatus: this.chromiumStatus,
|
||||
systemInfo,
|
||||
logs: this.logs.slice(-50),
|
||||
serialLogs: this.serialLogs.slice(-50),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,6 +139,9 @@ export class EcoDaemon {
|
||||
await this.uiServer.start();
|
||||
this.log('Management UI started successfully');
|
||||
|
||||
// Start serial console reader in the background
|
||||
this.startSerialReader();
|
||||
|
||||
// Start the Sway/Chromium initialization in the background
|
||||
// This allows the UI server to remain responsive even if Sway fails
|
||||
this.startServicesInBackground();
|
||||
@@ -302,6 +313,31 @@ export class EcoDaemon {
|
||||
return parseInt(result.stdout.trim(), 10);
|
||||
}
|
||||
|
||||
private startSerialReader(): void {
|
||||
(async () => {
|
||||
try {
|
||||
const file = await Deno.open('/dev/ttyS0', { read: true });
|
||||
this.log('Serial console reader started on /dev/ttyS0');
|
||||
const reader = file.readable.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
const text = decoder.decode(value);
|
||||
for (const line of text.split('\n').filter((l) => l.trim())) {
|
||||
this.serialLogs.push(line);
|
||||
if (this.serialLogs.length > 1000) {
|
||||
this.serialLogs = this.serialLogs.slice(-1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.log(`Serial reader not available: ${error}`);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
private async runForever(): Promise<void> {
|
||||
// Monitor processes and restart if needed
|
||||
while (true) {
|
||||
|
||||
Reference in New Issue
Block a user