This commit is contained in:
lunaticbum 2026-03-27 10:59:59 +09:00
parent 1479face39
commit f6bce36924
3 changed files with 150 additions and 39 deletions

View File

@ -80,7 +80,7 @@ fun getLlamaBinPath(): String {
fun main() = application { fun main() = application {
val trayState = rememberTrayState() val trayState = rememberTrayState()
var isWindowOpen by remember { mutableStateOf(true) } // 창의 표시 상태 관리 var isWindowOpen by remember { mutableStateOf(false) } // 창의 표시 상태 관리
LaunchedEffect(Unit) { LaunchedEffect(Unit) {

View File

@ -72,29 +72,18 @@ object AutoTradingManager {
var tradeToken by mutableStateOf(false) var tradeToken by mutableStateOf(false)
var webSocketConnect by mutableStateOf(false) var webSocketConnect by mutableStateOf(false)
var testFlag = false
fun startBackgroundScheduler() { fun startBackgroundScheduler() {
// scope.launch { scope.launch {
// while (isActive) { while (isActive) {
// val now = LocalTime.now(ZoneId.of("Asia/Seoul")) val now = LocalTime.now(ZoneId.of("Asia/Seoul"))
// if (now.isAfter(H08M30) && now.isBefore(H18) && !shouldShowFullWindow) {
// // 1. 오전 8시 30분 ~ 15시 30분 사이인지 확인 shouldShowFullWindow = true
// if (now.isAfter(LocalTime.of(8, 30)) && now.isBefore(LocalTime.of(15, 30))) { SystemSleepPreventer.wakeDisplay()
// // 2. 아직 오늘 시스템 준비가 안 되었고, 설정값이 있는 경우 }
// if (!isSystemReadyToday && KisSession.config.realAppKey.isNotEmpty()) { delay(60_000 * 3) // 1분마다 체크
// println("⏰ [Scheduler] 자동 실행 시간이 되어 인증을 시작합니다.") }
// SystemSleepPreventer.wakeDisplay() // }
//
// // 인증 및 토큰 갱신 시도
// val success = KisAuthService.refreshAllTokens() && KisTradeService.refreshWebsocketKey()
// if (success) {
// isSystemReadyToday = true
// startAutoDiscoveryLoop() // 자동 매매 루프 시작
// }
// }
// }
// delay(60_000) // 1분마다 체크
// }
// }
} }
val globalCallback = { completeTradingDecision: TradingDecision?, isSuccess: Boolean -> 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 { try {
waitTime = 5.0 waitTime = 5.0
println("current SystemCleanedUpToday is $isSystemCleanedUpToday") println("current SystemCleanedUpToday is $isSystemCleanedUpToday")

View File

@ -4,9 +4,21 @@ import java.util.concurrent.TimeUnit
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import ch.qos.logback.classic.Level import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger 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 { object SystemSleepPreventer {
private var process: Process? = null 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() { fun checkAndRequestAccessibility() {
if (!hasAccessibilityPermission()) { if (!hasAccessibilityPermission()) {
println("⚠️ [System] 접근성 권한이 없습니다. 설정창을 엽니다.") println("⚠️ [System] 접근성 권한이 없습니다. 설정창을 엽니다.")
@ -70,14 +82,112 @@ object SystemSleepPreventer {
if (process?.isAlive == true) return if (process?.isAlive == true) return
if (!isWin) { if (!isWin) {
try { // try {
// -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지 // // -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지
val command = listOf("caffeinate", "-i", "-d", "-m") // val command = listOf("caffeinate", "-i", "-d", "-m")
process = ProcessBuilder(command).start() // process = ProcessBuilder(command).start()
println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.") // println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.")
} catch (e: Exception) { // } catch (e: Exception) {
println("⚠️ [System] caffeinate 실행 실패: ${e.message}") // 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() { fun sleepDisplay() {
try { try {
// pmset을 이용해 디스플레이를 즉시 끔 setBrightness(0)
Runtime.getRuntime().exec("pmset displaysleepnow")
println("🌙 [System] 오후 6시 30분: 모니터를 잠자기 모드로 전환합니다.") println("🌙 [System] 오후 6시 30분: 모니터를 잠자기 모드로 전환합니다.")
} catch (e: Exception) { } catch (e: Exception) {
println("⚠️ 모니터 잠자기 실패: ${e.message}") 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() { fun wakeDisplay() {
try { try {
// caffeinate를 다시 실행하여 깨우거나, setBrightness(100)
// 쉘 명령어로 키 입력을 시뮬레이션하여 화면을 깨움
Runtime.getRuntime().exec(
arrayOf("caffeinate", "-u", "-t", "3600")
)
// Runtime.getRuntime().exec(arrayOf("osascript", "-e", "tell application \"System Events\" to key code 123"))
println("☀️ 오전 8시: 모니터를 깨웁니다.") println("☀️ 오전 8시: 모니터를 깨웁니다.")
} catch (e: Exception) { } catch (e: Exception) {
println("⚠️ 모니터 깨우기 실패: ${e.message}") println("⚠️ 모니터 깨우기 실패: ${e.message}")