Implemented all seven packet types.
This commit is contained in:
parent
bc6da05747
commit
c9704c4bf4
3 changed files with 240 additions and 71 deletions
|
@ -1,7 +1,10 @@
|
|||
package club.clubk.ktag.bletool
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
data class ByteCellData(
|
||||
val value: Byte,
|
||||
val isHeader: Boolean,
|
||||
val description: String
|
||||
val description: String,
|
||||
val backgroundColor: Color? = null
|
||||
)
|
|
@ -15,12 +15,15 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
|
@ -49,12 +52,8 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
private const val TAG = "BLE Tool"
|
||||
|
||||
|
@ -95,7 +94,7 @@ val advertisementPresets = listOf(
|
|||
0x00.toByte(),
|
||||
0x00.toByte(), // Event Data
|
||||
),
|
||||
"KTag Instigate Game Packet"
|
||||
"KTag Event Packet"
|
||||
),
|
||||
AdvertisementPreset(
|
||||
"03 Tag",
|
||||
|
@ -146,10 +145,64 @@ val advertisementPresets = listOf(
|
|||
),
|
||||
"KTag Status Packet"
|
||||
),
|
||||
AdvertisementPreset(
|
||||
"06 Configuration",
|
||||
byteArrayOf(
|
||||
0x06.toByte(), // Packet Type: Configuration
|
||||
0x00.toByte(), // Event Number
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(), // Target Bluetooth Device Address
|
||||
0x02.toByte(), // Subtype: Request Parameter Change
|
||||
0x01.toByte(),
|
||||
0x00.toByte(), // Key 1: Team ID
|
||||
0x02.toByte(),
|
||||
0x00.toByte(),
|
||||
0x00.toByte(),
|
||||
0x00.toByte(), // Value 1: 2
|
||||
0xFF.toByte(),
|
||||
0xFF.toByte(), // Key 2: Unused
|
||||
0x00.toByte(),
|
||||
0x00.toByte(),
|
||||
0x00.toByte(),
|
||||
0x00.toByte(), // Value 2: Unused
|
||||
),
|
||||
"KTag Configuration Packet"
|
||||
),
|
||||
AdvertisementPreset(
|
||||
"07 Hello",
|
||||
byteArrayOf(
|
||||
0x07.toByte(), // Packet Type: Hello
|
||||
0x00.toByte(), // Event Number
|
||||
0x01.toByte(), // SystemK Major Version
|
||||
0x00.toByte(), // SystemK Minor Version
|
||||
0x02.toByte(), //
|
||||
0x00.toByte(), // Device Type: Mobile App
|
||||
0x02.toByte(), // Team ID
|
||||
0x4B.toByte(), // 'K'
|
||||
0x54.toByte(), // 'T'
|
||||
0x61.toByte(), // 'a'
|
||||
0x67.toByte(), // 'g'
|
||||
0x20.toByte(), // ' '
|
||||
0x42.toByte(), // 'B'
|
||||
0x4C.toByte(), // 'L'
|
||||
0x45.toByte(), // 'E'
|
||||
0x20.toByte(), // ' '
|
||||
0x54.toByte(), // 'T'
|
||||
0x6F.toByte(), // 'o'
|
||||
0x6F.toByte(), // 'o'
|
||||
0x6C.toByte(), // 'l'
|
||||
0x00.toByte(), // Device Name: "KTag BLE Tool"
|
||||
),
|
||||
"KTag Hello Packet"
|
||||
),
|
||||
AdvertisementPreset(
|
||||
"Empty",
|
||||
ByteArray(23) { 0 },
|
||||
"All zeros - clear current data"
|
||||
"All zeros (clear current data)"
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -326,71 +379,13 @@ fun BleAdvertiserScreen() {
|
|||
|
||||
// Create list of byte cells with their properties
|
||||
val byteCells = remember(advertisementData) {
|
||||
val packetType = advertisementData[8]
|
||||
advertisementData.mapIndexed { index, byte ->
|
||||
ByteCellData(
|
||||
value = byte, isHeader = index < N_HEADER_BYTES, description = when (index) {
|
||||
0 -> "Length" // Always "Length"
|
||||
1 -> "Type" // Always "Type"
|
||||
2 -> "Mfg ID" // Always "Mfg ID"
|
||||
3 -> "Mfg ID" // Always "Mfg ID"
|
||||
4 -> "'K'" // Always "'K'"
|
||||
5 -> "'T'" // Always "'T'"
|
||||
6 -> "'a'" // Always "'a'"
|
||||
7 -> "'g'" // Always "'g'"
|
||||
9 -> "Event Number"
|
||||
else -> {
|
||||
when (advertisementData[8]) {
|
||||
0x01.toByte() -> when(index){
|
||||
8 -> "Instigate Game" // Packet Type 01
|
||||
else -> ""
|
||||
}
|
||||
0x02.toByte() -> when(index){
|
||||
8 -> "Event" // Packet Type 02
|
||||
else -> ""
|
||||
}
|
||||
0x03.toByte() -> when(index){
|
||||
8 -> "Tag" // Packet Type 03
|
||||
10 -> "Tx Pwr (dBm)"
|
||||
11 -> "Protocol"
|
||||
12 -> "Team ID"
|
||||
13 -> "Player ID"
|
||||
14 -> "Damage"
|
||||
15 -> "Damage"
|
||||
16 -> "Color"
|
||||
17 -> "Color"
|
||||
18 -> "Color"
|
||||
19 -> "Color"
|
||||
20 -> "Target Address"
|
||||
21 -> "Target Address"
|
||||
22 -> "Target Address"
|
||||
23 -> "Target Address"
|
||||
24 -> "Target Address"
|
||||
25 -> "Target Address"
|
||||
else -> ""
|
||||
}
|
||||
0x04.toByte() -> when(index){
|
||||
8 -> "Console" // Packet Type 04
|
||||
else -> ""
|
||||
}
|
||||
0x05.toByte() -> when(index){
|
||||
8 -> "Status" // Packet Type 05
|
||||
else -> ""
|
||||
}
|
||||
0x06.toByte() -> when(index){
|
||||
8 -> "Configuration" // Packet Type 06
|
||||
else -> ""
|
||||
}
|
||||
0x07.toByte() -> when(index){
|
||||
8 -> "Hello" // Packet Type 07
|
||||
else -> ""
|
||||
}
|
||||
else -> when(index){
|
||||
8 -> "Packet Type"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
value = byte,
|
||||
isHeader = index < N_HEADER_BYTES,
|
||||
description = PacketFieldUtils.getFieldDescription(packetType, index),
|
||||
backgroundColor = PacketFieldUtils.getFieldColor(packetType, index)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -556,6 +551,7 @@ fun ByteCell(
|
|||
val backgroundColor = when {
|
||||
data.isHeader -> MaterialTheme.colorScheme.secondaryContainer
|
||||
isSelected -> MaterialTheme.colorScheme.primary
|
||||
data.backgroundColor != null -> data.backgroundColor
|
||||
else -> MaterialTheme.colorScheme.primaryContainer
|
||||
}
|
||||
|
||||
|
|
170
app/src/main/java/club/clubk/ktag/bletool/PacketFieldUtils.kt
Normal file
170
app/src/main/java/club/clubk/ktag/bletool/PacketFieldUtils.kt
Normal file
|
@ -0,0 +1,170 @@
|
|||
package club.clubk.ktag.bletool
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
object PacketFieldUtils {
|
||||
fun getFieldDescription(packetType: Byte, index: Int): String {
|
||||
return when (index) {
|
||||
0 -> "Length" // Always "Length"
|
||||
1 -> "Type" // Always "Type"
|
||||
2 -> "Mfg ID" // Always "Mfg ID"
|
||||
3 -> "Mfg ID" // Always "Mfg ID"
|
||||
4 -> "'K'" // Always "'K'"
|
||||
5 -> "'T'" // Always "'T'"
|
||||
6 -> "'a'" // Always "'a'"
|
||||
7 -> "'g'" // Always "'g'"
|
||||
8 -> when (packetType) {
|
||||
0x01.toByte() -> "Instigate Game"
|
||||
0x02.toByte() -> "Event"
|
||||
0x03.toByte() -> "Tag"
|
||||
0x04.toByte() -> "Console"
|
||||
0x05.toByte() -> "Status"
|
||||
0x06.toByte() -> "Configuration"
|
||||
0x07.toByte() -> "Hello"
|
||||
else -> "Packet Type"
|
||||
}
|
||||
|
||||
9 -> "Event Number"
|
||||
else -> when (packetType) {
|
||||
0x01.toByte() -> when (index) { // Instigate Game packet fields
|
||||
in 10..13 -> "Game Length (ms)"
|
||||
in 14..17 -> "Time till Countdown (ms)"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x02.toByte() -> when (index) { // Event packet fields
|
||||
in 10..15 -> "Target Address"
|
||||
in 16..19 -> "Event ID"
|
||||
in 20..23 -> "Event Data"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x03.toByte() -> when (index) { // Tag packet fields
|
||||
10 -> "Tx Pwr (dBm)"
|
||||
11 -> "Protocol"
|
||||
12 -> "Team ID"
|
||||
13 -> "Player ID"
|
||||
14, 15 -> "Damage"
|
||||
in 16..19 -> "Color"
|
||||
in 20..25 -> "Target Address"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x04.toByte() -> when (index) { // Console packet fields
|
||||
in 10..30 -> "Console String"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x05.toByte() -> when (index) { // Status packet fields
|
||||
10 -> "Tx Pwr (dBm)"
|
||||
11 -> "Protocol"
|
||||
12 -> "Team ID"
|
||||
13 -> "Player ID"
|
||||
14, 15 -> "Health"
|
||||
16, 17 -> "Max Health"
|
||||
in 18..21 -> "Primary Color"
|
||||
in 22..25 -> "Secondary Color"
|
||||
26 -> "SystemK State"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x06.toByte() -> when (index) { // Configuration packet fields
|
||||
in 10..15 -> "Target Address"
|
||||
16 -> "Subtype"
|
||||
17, 18 -> "Key 1"
|
||||
in 19..22 -> "Value 1"
|
||||
23, 24 -> "Key 2"
|
||||
in 25..28 -> "Value 2"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
0x07.toByte() -> when (index) { // Hello packet fields
|
||||
10 -> "SystemK Major Version"
|
||||
11 -> "SystemK Minor Version"
|
||||
12, 13 -> "Device Type"
|
||||
14 -> "Team ID"
|
||||
in 15..30 -> "Device Name"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFieldColor(packetType: Byte, index: Int): Color? {
|
||||
// Header bytes always return null to use default header color
|
||||
if (index < 8) return null
|
||||
|
||||
// Packet type byte is always a distinct color
|
||||
if (index == 8) return Color(0xFFE6F3FF) // Light blue
|
||||
|
||||
// Event number is always the same color across all packet types
|
||||
if (index == 9) return Color(0xFFE6FFE6) // Light green
|
||||
|
||||
return when (packetType) {
|
||||
0x01.toByte() -> when (index) { // Instigate Game packet
|
||||
in 10..13 -> Color(0xFFFFF3E6) // Game Length - Light orange
|
||||
in 14..17 -> Color(0xFFE6FFF3) // Time until Countdown - Light cyan
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x02.toByte() -> when (index) { // Event packet
|
||||
in 10..15 -> Color(0xFFE6F3FF) // Target Address - Light blue
|
||||
in 16..19 -> Color(0xFFF3E6FF) // Event ID - Light purple
|
||||
in 20..23 -> Color(0xFFE6FFE6) // Event Data - Light green
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x03.toByte() -> when (index) { // Tag packet
|
||||
10 -> Color(0xFFFFF3E6) // Tx Power - Light orange
|
||||
11 -> Color(0xFFE6FFF3) // Protocol - Light cyan
|
||||
12 -> Color(0xFFFFE6F3) // Team ID - Light pink
|
||||
13 -> Color(0xFFF3E6FF) // Player ID - Light purple
|
||||
in 14..15 -> Color(0xFFFFE6E6) // Damage - Light red
|
||||
in 16..19 -> Color(0xFFE6FFE6) // Color - Light green
|
||||
in 20..25 -> Color(0xFFE6F3FF) // Target Address - Light blue
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x04.toByte() -> when (index) { // Console packet
|
||||
in 10..30 -> Color(0xFFFFF3E6) // Console String - Light orange
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x05.toByte() -> when (index) { // Status packet
|
||||
10 -> Color(0xFFFFF3E6) // Tx Power - Light orange
|
||||
11 -> Color(0xFFE6FFF3) // Protocol - Light cyan
|
||||
12 -> Color(0xFFFFE6F3) // Team ID - Light pink
|
||||
13 -> Color(0xFFF3E6FF) // Player ID - Light purple
|
||||
14, 15 -> Color(0xFFFFE6E6) // Health - Light red
|
||||
16, 17 -> Color(0xFFE6FFE6) // Maximum Health - Light green
|
||||
in 18..21 -> Color(0xFFE6F3FF) // Primary Color - Light blue
|
||||
in 22..25 -> Color(0xFFF3E6FF) // Secondary Color - Light purple
|
||||
26 -> Color(0xFFFFF3E6) // SystemK State - Light orange
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x06.toByte() -> when (index) { // Configuration packet
|
||||
in 10..15 -> Color(0xFFE6F3FF) // Target Address - Light blue
|
||||
16 -> Color(0xFFFFF3E6) // Subtype - Light orange
|
||||
17, 18 -> Color(0xFFF3E6FF) // Key 1 - Light purple
|
||||
in 19..22 -> Color(0xFFE6FFE6) // Value 1 - Light green
|
||||
23, 24 -> Color(0xFFF3E6FF) // Key 2 - Light purple
|
||||
in 25..28 -> Color(0xFFE6FFE6) // Value 2 - Light green
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
0x07.toByte() -> when (index) { // Hello packet
|
||||
10 -> Color(0xFFFFF3E6) // SystemK Major Version - Light orange
|
||||
11 -> Color(0xFFE6FFF3) // SystemK Minor Version - Light cyan
|
||||
12, 13 -> Color(0xFFE6F3FF) // Device Type - Light blue
|
||||
14 -> Color(0xFFFFE6F3) // Team ID - Light pink
|
||||
in 15..30 -> Color(0xFFF3E6FF) // Device Name - Light purple
|
||||
else -> Color(0xFFF5F5F5) // Light gray for undefined fields
|
||||
}
|
||||
|
||||
else -> Color(0xFFF5F5F5) // Light gray for unknown packet types
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue