fdc4047c5c
테스터 코드 분석 결과:
exe: mls? + [0x00, 0x05] (16비트 Big Endian) → LED 바뀜
앱: mls? + [0x05, 0x00] (16비트 Little Endian) → LED 안 바뀜
CRC16.buildCommandBE() 추가: 파라미터를 Big Endian으로 직렬화
sendLedMode(): buildCommandBE("mls", [state]) 사용
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
72 lines
2.6 KiB
Kotlin
72 lines
2.6 KiB
Kotlin
package com.example.medilightv2android.ble
|
|
|
|
object CRC16 {
|
|
private const val POLYNOMIAL: Int = 0x1021
|
|
private const val INITIAL_VALUE: Int = 0xFFFF
|
|
|
|
fun calculate(data: ByteArray): Int {
|
|
var crc = INITIAL_VALUE
|
|
for (byte in data) {
|
|
crc = crc xor ((byte.toInt() and 0xFF) shl 8)
|
|
for (j in 0 until 8) {
|
|
crc = if ((crc and 0x8000) != 0) {
|
|
(crc shl 1) xor POLYNOMIAL
|
|
} else {
|
|
crc shl 1
|
|
}
|
|
crc = crc and 0xFFFF
|
|
}
|
|
}
|
|
return crc
|
|
}
|
|
|
|
fun calculate(string: String): Int = calculate(string.toByteArray(Charsets.UTF_8))
|
|
|
|
fun appendCRC(data: ByteArray): ByteArray {
|
|
val crc = calculate(data)
|
|
return data + byteArrayOf(
|
|
(crc and 0xFF).toByte(), // Low byte first (Little Endian)
|
|
((crc shr 8) and 0xFF).toByte() // High byte
|
|
)
|
|
}
|
|
|
|
fun appendCRC(string: String): ByteArray = appendCRC(string.toByteArray(Charsets.UTF_8))
|
|
|
|
fun verify(data: ByteArray): Boolean {
|
|
if (data.size < 2) return false
|
|
val payload = data.copyOfRange(0, data.size - 2)
|
|
val receivedCRC = (data[data.size - 2].toInt() and 0xFF) or
|
|
((data[data.size - 1].toInt() and 0xFF) shl 8)
|
|
return calculate(payload) == receivedCRC
|
|
}
|
|
|
|
fun buildCommand(cmd: String, params: IntArray = intArrayOf()): ByteArray {
|
|
val cmdBytes = "$cmd?".toByteArray(Charsets.UTF_8)
|
|
val paramBytes = ByteArray(params.size * 2)
|
|
for (i in params.indices) {
|
|
paramBytes[i * 2] = (params[i] and 0xFF).toByte() // Low byte
|
|
paramBytes[i * 2 + 1] = ((params[i] shr 8) and 0xFF).toByte() // High byte
|
|
}
|
|
return appendCRC(cmdBytes + paramBytes)
|
|
}
|
|
|
|
fun buildCommandASCII(cmd: String, asciiParams: String = ""): ByteArray {
|
|
return appendCRC("$cmd?$asciiParams".toByteArray(Charsets.UTF_8))
|
|
}
|
|
|
|
/** 파라미터를 16비트 Big Endian으로 추가 (펌웨어 테스터와 동일 포맷) */
|
|
fun buildCommandBE(cmd: String, params: IntArray = intArrayOf()): ByteArray {
|
|
val cmdBytes = "$cmd?".toByteArray(Charsets.UTF_8)
|
|
val paramBytes = ByteArray(params.size * 2)
|
|
for (i in params.indices) {
|
|
paramBytes[i * 2] = ((params[i] shr 8) and 0xFF).toByte() // High byte first
|
|
paramBytes[i * 2 + 1] = (params[i] and 0xFF).toByte() // Low byte
|
|
}
|
|
return appendCRC(cmdBytes + paramBytes)
|
|
}
|
|
|
|
fun buildSimpleCommand(cmd: String): ByteArray {
|
|
return appendCRC(cmd.toByteArray(Charsets.UTF_8))
|
|
}
|
|
}
|