#1: Добавлено отслеживение длины нажатий кнопки. Это нужно для отключения самбы и размонтирования флешки. (спустя два часа страданий)
This commit is contained in:
@@ -7,11 +7,11 @@ import java.io.BufferedReader
|
|||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
// Событие клика по кнопке
|
|
||||||
class ButtonClickEvent
|
class ButtonClickEvent
|
||||||
|
class ButtonLongPressEvent
|
||||||
|
|
||||||
// Слушатель событий клика
|
|
||||||
typealias ButtonClickListener = (ButtonClickEvent) -> Unit
|
typealias ButtonClickListener = (ButtonClickEvent) -> Unit
|
||||||
|
typealias ButtonLongPressListener = (ButtonLongPressEvent) -> Unit
|
||||||
|
|
||||||
class ButtonListener(
|
class ButtonListener(
|
||||||
private var process: Process? = null,
|
private var process: Process? = null,
|
||||||
@@ -19,63 +19,128 @@ class ButtonListener(
|
|||||||
private var isListening: AtomicBoolean = AtomicBoolean(false),
|
private var isListening: AtomicBoolean = AtomicBoolean(false),
|
||||||
private var listenerJob: Job? = null
|
private var listenerJob: Job? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val clickListeners = mutableListOf<ButtonClickListener>()
|
private val clickListeners = mutableListOf<ButtonClickListener>()
|
||||||
|
private val longPressListeners = mutableListOf<ButtonLongPressListener>()
|
||||||
|
|
||||||
|
var shortPressThresholdMs: Long = 100
|
||||||
|
var longPressThresholdMs: Long = 1000
|
||||||
|
|
||||||
|
private var pressStartTime: Long = 0
|
||||||
|
|
||||||
fun addClickListener(listener: ButtonClickListener) {
|
fun addClickListener(listener: ButtonClickListener) {
|
||||||
clickListeners.add(listener)
|
clickListeners.add(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeClickListener(listener: ButtonClickListener) {
|
||||||
|
clickListeners.remove(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addLongPressListener(listener: ButtonLongPressListener) {
|
||||||
|
longPressListeners.add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeLongPressListener(listener: ButtonLongPressListener) {
|
||||||
|
longPressListeners.remove(listener)
|
||||||
|
}
|
||||||
|
|
||||||
private fun notifyClick() {
|
private fun notifyClick() {
|
||||||
|
println("=== [CLICK] Короткое нажатие ===")
|
||||||
val event = ButtonClickEvent()
|
val event = ButtonClickEvent()
|
||||||
clickListeners.forEach { it.invoke(event) }
|
clickListeners.forEach { it.invoke(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun notifyLongPress() {
|
||||||
|
println("=== [LONG] Длинное нажатие ===")
|
||||||
|
val event = ButtonLongPressEvent()
|
||||||
|
longPressListeners.forEach { it.invoke(event) }
|
||||||
|
}
|
||||||
|
|
||||||
fun startListening(onStateChange: ((Boolean) -> Unit)? = null): Boolean {
|
fun startListening(onStateChange: ((Boolean) -> Unit)? = null): Boolean {
|
||||||
if (isListening.get()) {
|
if (isListening.get()) {
|
||||||
return currentButtonState.get()
|
return currentButtonState.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startListeningInternal(onStateChange)
|
||||||
|
return currentButtonState.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startListeningInternal(onStateChange: ((Boolean) -> Unit)? = null) {
|
||||||
try {
|
try {
|
||||||
val cmd = listOf("gpiomon", "--chip=0", "$BUTTON")
|
val cmd = listOf("gpiomon", "--chip=0", "$BUTTON")
|
||||||
val processBuilder = ProcessBuilder(cmd)
|
val processBuilder = ProcessBuilder(cmd)
|
||||||
.redirectErrorStream(true)
|
.redirectErrorStream(true)
|
||||||
|
|
||||||
// Сохраняем процесс в поле
|
|
||||||
process = processBuilder.start()
|
process = processBuilder.start()
|
||||||
isListening.set(true)
|
isListening.set(true)
|
||||||
|
|
||||||
listenerJob = CoroutineScope(Dispatchers.IO).launch {
|
listenerJob = CoroutineScope(Dispatchers.IO).launch {
|
||||||
// Используем process, который теперь не null
|
|
||||||
val reader = BufferedReader(InputStreamReader(process!!.inputStream))
|
val reader = BufferedReader(InputStreamReader(process!!.inputStream))
|
||||||
var line: String?
|
var line: String?
|
||||||
|
|
||||||
while (reader.readLine().also { line = it } != null) {
|
try {
|
||||||
println(if (isDebug) "$line" else "")
|
while (reader.readLine().also { line = it } != null) {
|
||||||
when {
|
println(if (isDebug) "$line" else "")
|
||||||
line?.contains("rising") == true -> {
|
when {
|
||||||
currentButtonState.set(true)
|
line?.contains("rising") == true -> {
|
||||||
onStateChange?.invoke(true)
|
currentButtonState.set(true)
|
||||||
println(if (isDebug) "Кнопка нажата" else "")
|
onStateChange?.invoke(true)
|
||||||
// Генерируем событие клика при нажатии
|
pressStartTime = System.currentTimeMillis()
|
||||||
notifyClick()
|
println(if (isDebug) "Кнопка нажата, время: $pressStartTime" else "")
|
||||||
}
|
}
|
||||||
line?.contains("falling") == true -> {
|
line?.contains("falling") == true -> {
|
||||||
currentButtonState.set(false)
|
val pressDuration = System.currentTimeMillis() - pressStartTime
|
||||||
onStateChange?.invoke(false)
|
currentButtonState.set(false)
|
||||||
println(if (isDebug) "Кнопка разжата" else "")
|
onStateChange?.invoke(false)
|
||||||
// Убрана проверка на разжатие для генерации события
|
println(if (isDebug) "Кнопка отпущена, длительность: ${pressDuration}ms" else "")
|
||||||
|
|
||||||
|
// Определяем тип нажатия по длительности
|
||||||
|
when {
|
||||||
|
pressDuration >= longPressThresholdMs -> {
|
||||||
|
println(if (isDebug) "Длинное нажатие (${pressDuration}ms)" else "")
|
||||||
|
notifyLongPress()
|
||||||
|
}
|
||||||
|
pressDuration >= shortPressThresholdMs -> {
|
||||||
|
println(if (isDebug) "Короткое нажатие (${pressDuration}ms)" else "")
|
||||||
|
notifyClick()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
println(if (isDebug) "Слишком короткое нажатие (${pressDuration}ms) - игнорируем" else "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Ошибка чтения процесса: ${e.message}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val exitCode = process!!.waitFor()
|
val exitCode = process!!.waitFor()
|
||||||
println(if (isDebug) "Процесс завершён ($exitCode)" else "")
|
println("Процесс завершён ($exitCode)")
|
||||||
isListening.set(false)
|
isListening.set(false)
|
||||||
|
|
||||||
|
// Автоматически перезапускаем прослушивание, если оно должно быть активно
|
||||||
|
if (isListening.get()) {
|
||||||
|
println("Перезапуск прослушивания...")
|
||||||
|
delay(100)
|
||||||
|
startListeningInternal(onStateChange)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
isListening.set(false)
|
isListening.set(false)
|
||||||
}
|
}
|
||||||
return currentButtonState.get()
|
}
|
||||||
|
|
||||||
|
fun stopListening() {
|
||||||
|
isListening.set(false)
|
||||||
|
listenerJob?.cancel()
|
||||||
|
process?.destroy()
|
||||||
|
process = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restartListening(onStateChange: ((Boolean) -> Unit)? = null) {
|
||||||
|
stopListening()
|
||||||
|
Thread.sleep(200)
|
||||||
|
startListening(onStateChange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,9 +538,15 @@ fun main(args: Array<String>) {
|
|||||||
scanner.initialize()
|
scanner.initialize()
|
||||||
|
|
||||||
val buttonListener = ButtonListener()
|
val buttonListener = ButtonListener()
|
||||||
|
|
||||||
buttonListener.addClickListener { event ->
|
buttonListener.addClickListener { event ->
|
||||||
scanner.startScan()
|
scanner.startScan()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buttonListener.addLongPressListener { event ->
|
||||||
|
println("TODO: Сделать отключение samba и отмонтирование накопителя.")
|
||||||
|
}
|
||||||
|
|
||||||
buttonListener.startListening()
|
buttonListener.startListening()
|
||||||
|
|
||||||
println(if (isDebug) """
|
println(if (isDebug) """
|
||||||
|
|||||||
Reference in New Issue
Block a user