ti-pote/apps/robot-client/src/config/robot.config.ts

76 lines
2.2 KiB
TypeScript

import { resolve } from 'node:path';
import { config } from 'dotenv';
/**
* Robot operating modes:
* - 'physical': Production on Pi with I2S audio
* - 'dev': Test on Pi with USB audio (e.g., USB headset)
* - 'simulator': PC dev, no real audio (future: mock services)
*/
export type RobotMode = 'physical' | 'dev' | 'simulator';
/**
* How conversations are triggered:
* - 'wakeword': OpenWakeWord listens for "Hey Ti-Pote" (requires Python + openwakeword)
* - 'keyboard': Press Enter in the terminal to start a conversation
*/
export type TriggerMode = 'wakeword' | 'keyboard';
export interface RobotConfig {
/** Operating mode */
mode: RobotMode;
/** How conversations are triggered */
triggerMode: TriggerMode;
/** Unique device identifier (generated at first setup or from env) */
deviceId: string;
/** JWT device token for cloud authentication */
deviceToken: string;
/** Cloud backend WebSocket URL */
cloudUrl: string;
/** Robot display name */
robotName: string;
/** Log level */
logLevel: string;
}
export function loadRobotConfig(): RobotConfig {
// Load the right .env file based on ROBOT_MODE or --env flag
const envFile = process.env.ENV_FILE || (process.env.ROBOT_MODE === 'dev' ? '.env.dev' : '.env');
config({ path: resolve(process.cwd(), envFile) });
const mode = (process.env.ROBOT_MODE || 'dev') as RobotMode;
if (!['physical', 'dev', 'simulator'].includes(mode)) {
throw new Error(`Invalid ROBOT_MODE: ${mode}. Must be 'physical', 'dev', or 'simulator'.`);
}
const triggerMode = (process.env.TRIGGER_MODE || 'wakeword') as TriggerMode;
if (!['wakeword', 'keyboard'].includes(triggerMode)) {
throw new Error(`Invalid TRIGGER_MODE: ${triggerMode}. Must be 'wakeword' or 'keyboard'.`);
}
return {
mode,
triggerMode,
deviceId: requireEnv('DEVICE_ID'),
deviceToken: requireEnv('DEVICE_TOKEN'),
cloudUrl: process.env.CLOUD_URL || 'ws://localhost:3000',
robotName: process.env.ROBOT_NAME || 'Ti-Pote',
logLevel: process.env.LOG_LEVEL || 'info',
};
}
function requireEnv(key: string): string {
const value = process.env[key];
if (!value) {
throw new Error(`Missing required environment variable: ${key}`);
}
return value;
}