// 配置日志文件 const now = new Date(); const log = require('log4js').configure({ appenders: { file: { type: 'file', filename: `./log/${now.getFullYear()}.${now.getMonth() + 1}.${now.getDate()}.log` } }, categories: { default: { appenders: ['file'], level: 'info' } } }).getLogger(); // 전역 예외 처리 process.on('uncaughtException', (error) => { log.error('Uncaught Exception:', error); }); process.on('unhandledRejection', (reason) => { log.error('Unhandled Rejection:', reason); }); // 플러그인 클래스 const ws = require('ws'); class Plugins { static language = process.argv[9] ? JSON.parse(process.argv[9]).application.language : 'en'; static globalSettings = {}; getGlobalSettingsFlag = true; constructor() { if (Plugins.instance) { return Plugins.instance; } log.info("process.argv", process.argv); this.ws = new ws("ws://127.0.0.1:" + process.argv[3]); this.ws.on('open', () => this.ws.send(JSON.stringify({ uuid: process.argv[5], event: process.argv[7] }))); this.ws.on('close', process.exit); this.ws.on('message', e => { if (this.getGlobalSettingsFlag) { // 한 번만 가져오기 this.getGlobalSettingsFlag = false; this.getGlobalSettings(); } const data = JSON.parse(e.toString()); log.info('Received event:', data); const action = data.action?.split('.').pop(); // 액션별 이벤트 처리 if (this[action] && this[action][data.event]) { log.info(`Calling ${action}.${data.event}`); this[action][data.event](data); } // 전역 이벤트 처리 if (data.event === 'didReceiveGlobalSettings') { Plugins.globalSettings = data.payload.settings; } if (this[data.event]) { this[data.event](data); } }); Plugins.instance = this; } setGlobalSettings(payload) { Plugins.globalSettings = payload; this.ws.send(JSON.stringify({ event: "setGlobalSettings", context: process.argv[5], payload })); } getGlobalSettings() { this.ws.send(JSON.stringify({ event: "getGlobalSettings", context: process.argv[5], })); } // 제목 설정 setTitle(context, str, row = 0, num = 6) { let newStr = null; if (row && str) { let nowRow = 1, strArr = str.split(''); strArr.forEach((item, index) => { if (nowRow < row && index >= nowRow * num) { nowRow++; newStr += '\n'; } if (nowRow <= row && index < nowRow * num) { newStr += item; } }); if (strArr.length > row * num) { newStr = newStr.substring(0, newStr.length - 1); newStr += '..'; } } this.ws.send(JSON.stringify({ event: "setTitle", context, payload: { target: 0, title: newStr || str + '' } })); } // 이미지 설정 setImage(context, url) { this.ws.send(JSON.stringify({ event: "setImage", context, payload: { target: 0, image: url } })); } // 상태 설정 setState(context, state) { this.ws.send(JSON.stringify({ event: "setState", context, payload: { state } })); } // 설정 저장 setSettings(context, payload) { this.ws.send(JSON.stringify({ event: "setSettings", context, payload })); } // 경고 표시 showAlert(context) { this.ws.send(JSON.stringify({ event: "showAlert", context })); } // 성공 표시 showOk(context) { this.ws.send(JSON.stringify({ event: "showOk", context })); } // 속성 검사기로 전송 sendToPropertyInspector(payload) { this.ws.send(JSON.stringify({ action: Actions.currentAction, context: Actions.currentContext, payload, event: "sendToPropertyInspector" })); } // URL 열기 openUrl(url) { this.ws.send(JSON.stringify({ event: "openUrl", payload: { url } })); } } // 액션 클래스 class Actions { constructor(data) { this.data = {}; this.default = {}; Object.assign(this, data); } // 속성 검사기 관련 static currentAction = null; static currentContext = null; static actions = {}; propertyInspectorDidAppear(data) { Actions.currentAction = data.action; Actions.currentContext = data.context; this._propertyInspectorDidAppear?.(data); } // 액션 초기화 willAppear(data) { Plugins.globalContext = data.context; Actions.actions[data.context] = data.action; const { context, payload: { settings } } = data; this.data[context] = Object.assign({ ...this.default }, settings); this._willAppear?.(data); } didReceiveSettings(data) { this.data[data.context] = data.payload.settings; this._didReceiveSettings?.(data); } // 키 이벤트 keyUp(data) { log.info('keyUp called with data:', data); if (typeof this._keyUp === 'function') { this._keyUp(data); } } keyDown(data) { log.info('keyDown called with data:', data); if (typeof this._keyDown === 'function') { this._keyDown(data); } } // 다이얼 이벤트 dialRotate(data) { log.info('dialRotate called with data:', data); if (typeof this._dialRotate === 'function') { this._dialRotate(data); } } dialDown(data) { log.info('dialDown called with data:', data); if (typeof this._dialDown === 'function') { this._dialDown(data); } } // 액션 해제 willDisappear(data) { this._willDisappear?.(data); delete this.data[data.context]; } } module.exports = { log, Plugins, Actions, };