From f6bce369249b0940e5fbb3472ee5f4d73df3597e Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Fri, 27 Mar 2026 10:59:59 +0900 Subject: [PATCH] ... --- src/main/kotlin/Main.kt | 2 +- src/main/kotlin/service/AutoTradingManager.kt | 35 ++-- .../kotlin/service/SystemSleepPreventer.kt | 152 ++++++++++++++++-- 3 files changed, 150 insertions(+), 39 deletions(-) diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 6b37551..717a759 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -80,7 +80,7 @@ fun getLlamaBinPath(): String { fun main() = application { val trayState = rememberTrayState() - var isWindowOpen by remember { mutableStateOf(true) } // 창의 표시 상태 관리 + var isWindowOpen by remember { mutableStateOf(false) } // 창의 표시 상태 관리 LaunchedEffect(Unit) { diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 8385a26..5b43996 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -72,29 +72,18 @@ object AutoTradingManager { var tradeToken by mutableStateOf(false) var webSocketConnect by mutableStateOf(false) + var testFlag = false fun startBackgroundScheduler() { -// scope.launch { -// while (isActive) { -// val now = LocalTime.now(ZoneId.of("Asia/Seoul")) -// -// // 1. 오전 8시 30분 ~ 15시 30분 사이인지 확인 -// if (now.isAfter(LocalTime.of(8, 30)) && now.isBefore(LocalTime.of(15, 30))) { -// // 2. 아직 오늘 시스템 준비가 안 되었고, 설정값이 있는 경우 -// if (!isSystemReadyToday && KisSession.config.realAppKey.isNotEmpty()) { -// println("⏰ [Scheduler] 자동 실행 시간이 되어 인증을 시작합니다.") -// SystemSleepPreventer.wakeDisplay() // -// -// // 인증 및 토큰 갱신 시도 -// val success = KisAuthService.refreshAllTokens() && KisTradeService.refreshWebsocketKey() -// if (success) { -// isSystemReadyToday = true -// startAutoDiscoveryLoop() // 자동 매매 루프 시작 -// } -// } -// } -// delay(60_000) // 1분마다 체크 -// } -// } + scope.launch { + while (isActive) { + val now = LocalTime.now(ZoneId.of("Asia/Seoul")) + if (now.isAfter(H08M30) && now.isBefore(H18) && !shouldShowFullWindow) { + shouldShowFullWindow = true + SystemSleepPreventer.wakeDisplay() + } + delay(60_000 * 3) // 1분마다 체크 + } + } } val globalCallback = { completeTradingDecision: TradingDecision?, isSuccess: Boolean -> @@ -619,7 +608,7 @@ object AutoTradingManager { } } - (AutoTradingManager.now.isAfter(LocalTime.of(18, 0))) -> { + (AutoTradingManager.now.isAfter(LocalTime.of(18, 30))) -> { try { waitTime = 5.0 println("current SystemCleanedUpToday is $isSystemCleanedUpToday") diff --git a/src/main/kotlin/service/SystemSleepPreventer.kt b/src/main/kotlin/service/SystemSleepPreventer.kt index 1d6da90..f66f1cb 100644 --- a/src/main/kotlin/service/SystemSleepPreventer.kt +++ b/src/main/kotlin/service/SystemSleepPreventer.kt @@ -4,9 +4,21 @@ import java.util.concurrent.TimeUnit import org.slf4j.LoggerFactory import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger +import java.awt.MouseInfo +import java.awt.Robot +import java.time.LocalTime +import java.util.concurrent.Executors object SystemSleepPreventer { private var process: Process? = null + + private val robot = Robot() + private val scheduler = Executors.newSingleThreadScheduledExecutor() + + // 작동 시간 설정 + private val startTime = LocalTime.of(8, 30) + private val endTime = LocalTime.of(16, 0) + fun checkAndRequestAccessibility() { if (!hasAccessibilityPermission()) { println("⚠️ [System] 접근성 권한이 없습니다. 설정창을 엽니다.") @@ -70,14 +82,112 @@ object SystemSleepPreventer { if (process?.isAlive == true) return if (!isWin) { - try { - // -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지 - val command = listOf("caffeinate", "-i", "-d", "-m") - process = ProcessBuilder(command).start() - println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.") - } catch (e: Exception) { - println("⚠️ [System] caffeinate 실행 실패: ${e.message}") +// try { +// // -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지 +// val command = listOf("caffeinate", "-i", "-d", "-m") +// process = ProcessBuilder(command).start() +// println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.") +// } catch (e: Exception) { +// println("⚠️ [System] caffeinate 실행 실패: ${e.message}") +// } + } + start2() + } + + fun start2() { + println("🚀 화면 잠금 방지 프로그램이 시작되었습니다. (작동 시간: $startTime ~ $endTime)") + + // 1분(60초)마다 체크 + scheduler.scheduleAtFixedRate({ + if (isWorkingTime()) { + moveMouseSlightly() + } else { + println("💤 현재는 휴식 시간입니다. (${LocalTime.now().withNano(0)})") } + }, 0, 60 * 2, TimeUnit.SECONDS) + } + + private fun isWorkingTime(): Boolean { + val now = LocalTime.now() + // 시작 시간 이후 AND 종료 시간 이전인지 확인 + return now.isAfter(startTime) && now.isBefore(endTime) + } + + private fun moveMouseSlightly() { + try { + val pointer = MouseInfo.getPointerInfo().location + val x = pointer.x + val y = pointer.y + + // 현재 위치에서 1픽셀씩 이동했다가 복귀 (사용자 방해 최소화) + robot.mouseMove(x + 1, y + 1) + robot.mouseMove(x, y) + + println("🖱️ [${LocalTime.now().withNano(0)}] 마우스 신호를 보냈습니다.") + + robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT) + robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT) + println("🖱️ [${LocalTime.now().withNano(0)}] 키보드 신호를 보냈습니다.") + } catch (e: Exception) { + println("⚠️ 마우스 제어 실패: ${e.message}") + } + } + + private val osName = System.getProperty("os.name").lowercase() + + // 설정 시간 + private val dimTime = LocalTime.of(16, 0) // 오후 4시 이후 최저 밝기 + + fun start3() { + scheduler.scheduleAtFixedRate({ + val now = LocalTime.now() + + // 16:00 이후라면 밝기를 낮춤 + if (now.isAfter(dimTime) || now.isBefore(LocalTime.of(8, 30))) { + setBrightness(0) + } else { + setBrightness(80) // 업무 시간에는 다시 밝게 (80%) + } + }, 0, 10, TimeUnit.MINUTES) // 10분마다 체크 + } + + private fun setBrightness(level: Int) { + try { + if (osName.contains("mac")) { + // macOS: AppleScript 사용 (0.0 ~ 1.0 사이 값) +// val macLevel = level / 100.0 +// val command = arrayOf("osascript", "-e", +// "tell application \"Image Events\" to set darkness to $macLevel") +// // 참고: 최신 macOS에서는 'display services' 관련 스크립트가 더 정확할 수 있습니다. +// Runtime.getRuntime().exec(arrayOf("osascript", "-e", +// "tell application \"System Events\" to repeat $level times \n key code 107 \n end repeat")) // 밝기 감소 키 반복 + val keyCode = if (level < 50) 145 else 144 // 145: 감소, 144: 증가 + val action = if (level < 50) "어둡게" else "밝게" + + // 32번 연타하면 어떤 상태에서든 최소/최대에 도달합니다. + val script = """ + tell application "System Events" + repeat 32 times + key code $keyCode + end repeat + end tell + """.trimIndent() + + try { + val process = ProcessBuilder("osascript", "-e", script).start() + process.waitFor() + println("🍏 Mac 화면을 $action 설정했습니다. ${keyCode}") + } catch (e: Exception) { + println("⚠️ AppleScript 실행 실패: ${e.message}") + } + } else if (osName.contains("win")) { + // Windows: PowerShell 사용 (0 ~ 100 사이 값) + val psCommand = "Get-CimInstance -Namespace root/WMI -ClassName WmiMonitorBrightnessMethods | ForEach-Object { \$.WmiSetBrightness(1, $level) }" + ProcessBuilder("powershell.exe", "-Command", psCommand).start() + } + println("🔆 밝기를 $level%로 설정했습니다.") + } catch (e: Exception) { + println("⚠️ 밝기 조절 실패: ${e.message}") } } @@ -86,25 +196,37 @@ object SystemSleepPreventer { */ fun sleepDisplay() { try { - // pmset을 이용해 디스플레이를 즉시 끔 - Runtime.getRuntime().exec("pmset displaysleepnow") + setBrightness(0) println("🌙 [System] 오후 6시 30분: 모니터를 잠자기 모드로 전환합니다.") } catch (e: Exception) { println("⚠️ 모니터 잠자기 실패: ${e.message}") } } + fun preventSleepWithRobot() { + try { + val robot = Robot() + // 현재 마우스 위치 가져오기 + val pointer = MouseInfo.getPointerInfo().location + val x = pointer.x + val y = pointer.y + + // 마우스를 1픽셀 옆으로 움직였다가 다시 제자리로 (OS는 활동으로 간주함) + robot.mouseMove(x + 1, y + 1) + robot.mouseMove(x, y) + + println("🖱️ 마우스 이벤트를 시뮬레이션하여 화면 잠금을 방지했습니다.") + } catch (e: Exception) { + println("⚠️ 이벤트 생성 실패: ${e.message}") + } + } + /** * 마우스 움직임을 시뮬레이션하거나 디스플레이 깨우기 명령 실행 */ fun wakeDisplay() { try { - // caffeinate를 다시 실행하여 깨우거나, - // 쉘 명령어로 키 입력을 시뮬레이션하여 화면을 깨움 - Runtime.getRuntime().exec( - arrayOf("caffeinate", "-u", "-t", "3600") - ) -// Runtime.getRuntime().exec(arrayOf("osascript", "-e", "tell application \"System Events\" to key code 123")) + setBrightness(100) println("☀️ 오전 8시: 모니터를 깨웁니다.") } catch (e: Exception) { println("⚠️ 모니터 깨우기 실패: ${e.message}")