feat(infrared): add infrared control, learning, and virtual remote module #9

Merged
KremeCN merged 41 commits from feat/moler-infrared-control into main 2026-08-25 14:51:34 +08:00
2 changed files with 19 additions and 17 deletions
Showing only changes of commit 849b7e4aea - Show all commits
@@ -25,14 +25,11 @@ class LearnVirtualRemoteKey(
val binding = bindings.find { it.buttonId == buttonId } val binding = bindings.find { it.buttonId == buttonId }
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "Button not found")) ?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "Button not found"))
val targetSlot = when (remote.transmissionMode) { val targetSlot = binding.assignedSlot ?: run {
TransmissionMode.STATIC_SLOTS -> { val allBindings = (repository.getKeyBindings(remoteId) as? DomainResult.Success)?.value.orEmpty()
binding.assignedSlot ?: run { val usedSlots = allBindings.mapNotNull { it.assignedSlot?.toIntOrNull() }.toSet()
// Find available slot from quota val nextSlot = (1..99).firstOrNull { it !in usedSlots } ?: 1
"1" nextSlot.toString()
}
}
TransmissionMode.DYNAMIC_SCRATCH -> remote.dynamicScratchSlot
} }
// Set status to LEARNING while hardware listens // Set status to LEARNING while hardware listens
@@ -37,16 +37,21 @@ class SendVirtualRemoteAction(
gateway.sendKey(profileId, remote.deviceName, slot) gateway.sendKey(profileId, remote.deviceName, slot)
} }
TransmissionMode.DYNAMIC_SCRATCH -> { TransmissionMode.DYNAMIC_SCRATCH -> {
val hexCode = binding.rawHexCode if (binding.rawHexCode != null) {
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "No hex code available for dynamic transmission"))
// 1. Download to scratch slot // 1. Download to scratch slot
val scratchSlot = remote.dynamicScratchSlot val scratchSlot = remote.dynamicScratchSlot
when (val dlResult = gateway.downloadCodes(profileId, listOf(InfraredCode(remote.deviceName, scratchSlot, hexCode)))) { when (val dlResult = gateway.downloadCodes(profileId, listOf(InfraredCode(remote.deviceName, scratchSlot, binding.rawHexCode)))) {
is DomainResult.Failure -> return dlResult is DomainResult.Failure -> return dlResult
is DomainResult.Success -> Unit is DomainResult.Success -> Unit
} }
// 2. Send scratch slot // 2. Send scratch slot
gateway.sendKey(profileId, remote.deviceName, scratchSlot) gateway.sendKey(profileId, remote.deviceName, scratchSlot)
} else if (binding.assignedSlot != null) {
// Fallback to sending learned hardware slot
gateway.sendKey(profileId, remote.deviceName, binding.assignedSlot)
} else {
DomainResult.Failure(DomainError.InvalidRequest(detail = "No hex code or slot available for transmission"))
}
} }
} }
} }