Добавить общую модель конструктора ProtoCAN для Android

This commit is contained in:
2026-09-06 00:11:25 +03:00
parent 27ef6fcfdf
commit 0ce464499f
3 changed files with 90 additions and 19 deletions

View File

@@ -265,31 +265,14 @@ data class ProtoCanId(
val messageType: Int,
val body: Int,
) {
val messageTypeName: String get() = MESSAGE_TYPES[messageType] ?: "Reserved 0x${messageType.toString(16).uppercase()}"
val messageTypeName: String get() = ProtoCanMessageType.fromCode(messageType)?.title
?: "Reserved 0x${messageType.toString(16).uppercase()}"
val deviceName: String? get() = DEVICE_NAMES[device]
fun summary(): String = "P$priority · PM$pm · Type $deviceType · Dev $device" +
(deviceName?.let { " ($it)" } ?: "") + " · $messageTypeName · Body 0x%04X".format(body)
companion object {
private val MESSAGE_TYPES = mapOf(
0x0 to "Broadcast",
0x1 to "Discrete",
0x2 to "Analog",
0x3 to "General Address Space",
0x4 to "Modbus Coil",
0x5 to "Modbus Discrete",
0x6 to "Modbus Holding",
0x7 to "Modbus Input",
0x8 to "Error",
0x9 to "Boot Control",
0xA to "Boot Data A",
0xB to "Boot Data B",
0xC to "Boot Status",
0xD to "Boot Discovery",
0xE to "Settings",
0xF to "Pulse",
)
private val DEVICE_NAMES = mapOf(
0xD to "DS_CONTROL",
0xE to "Android GUI",

View File

@@ -0,0 +1,67 @@
package ru.setcorp.setflash.core
/** Canonical ProtoCAN message-type registry shared by Android protocol clients. */
enum class ProtoCanMessageType(val code: Int, val title: String) {
BROADCAST(0x0, "Broadcast"),
DISCRETE(0x1, "Discrete"),
ANALOG(0x2, "Analog"),
GENERAL_ADDRESS_SPACE(0x3, "General Address Space"),
MODBUS_COIL(0x4, "Modbus Coil"),
MODBUS_DISCRETE(0x5, "Modbus Discrete"),
MODBUS_HOLDING(0x6, "Modbus Holding"),
MODBUS_INPUT(0x7, "Modbus Input"),
ERROR(0x8, "Error"),
BOOT_CONTROL(0x9, "Boot Control"),
BOOT_DATA_A(0xA, "Boot Data A"),
BOOT_DATA_B(0xB, "Boot Data B"),
BOOT_STATUS(0xC, "Boot Status"),
BOOT_DISCOVERY(0xD, "Boot Discovery"),
SETTINGS(0xE, "Settings"),
PULSE(0xF, "Pulse");
companion object {
fun fromCode(code: Int): ProtoCanMessageType? = entries.firstOrNull { it.code == code }
}
}
enum class ProtoCanBroadcastType(val code: Int, val title: String) {
STATUS(0x0, "STATUS · запрос статуса"),
ONOFF(0x1, "ONOFF · вкл/выкл пульса"),
RESTART_DEVICE(0x2, "RESTARTDEVICE · перезапуск"),
RTC_SETUP(0x3, "RTCSETUP · установка RTC"),
END(0xFFF, "END · конец диапазона"),
}
enum class ProtoCanDiscreteType(val code: Int, val title: String) {
ACCIDENT(0x0, "ACCIDENT · авария"),
WARNING(0x1, "WARNING · предупреждение"),
CONTROL_SIGNALS(0x2, "CONTROL_SIGNALS · управление"),
FLAGS(0x3, "FLAGS · флаги"),
RESET(0x4, "RESET · сброс"),
CHANGE_MODE(0x5, "CHANGE_MODE · смена режима"),
REQUEST_PARAMETERS(0x6, "REQUEST_LIST_OF_PARAMETERS"),
END(0xF, "END · конец диапазона"),
}
enum class ProtoCanAnalogType(val code: Int, val title: String) {
UNIVERSAL(0x0, "UNIVERSAL · универсальный"),
SETTINGS(0x1, "SETTINGS · уставки"),
U(0x2, "U · напряжение"),
I(0x3, "I · ток"),
T(0x4, "T · температура"),
END(0xF, "END · конец диапазона"),
}
/** Portable MsgBody layouts matching `pcan_id.h` and SETGUI's frame builder. */
object ProtoCanBody {
fun broadcast(type: Int, body: Int): Int = ((type and 0xFFF) shl 4) or (body and 0xF)
fun typed(type: Int, body: Int): Int = ((type and 0xF) shl 12) or (body and 0xFFF)
fun modbus(address: Int, registerCount: Int): Int =
((address and 0xFFF) shl 4) or (registerCount and 0xF)
fun error(info: Int, code: Int): Int = ((info and 0xFF) shl 8) or (code and 0xFF)
fun settings(z: Int, y: Int): Int = ((z and 0xFF) shl 8) or (y and 0xFF)
}

View File

@@ -0,0 +1,21 @@
package ru.setcorp.setflash.core
import org.junit.Assert.assertEquals
import org.junit.Test
class ProtoCanCatalogTest {
@Test
fun bodyLayoutsMatchSetGuiBuilder() {
assertEquals(0x1234, ProtoCanBody.broadcast(0x123, 0x4))
assertEquals(0x2001, ProtoCanBody.typed(ProtoCanAnalogType.U.code, 1))
assertEquals(0x1234, ProtoCanBody.modbus(0x123, 4))
assertEquals(0xABCD, ProtoCanBody.error(0xAB, 0xCD))
assertEquals(0xFF01, ProtoCanBody.settings(0xFF, 0x01))
}
@Test
fun messageRegistryCoversAllFourBitValues() {
assertEquals((0..0xF).toList(), ProtoCanMessageType.entries.map { it.code })
assertEquals("Settings", ProtoCanId.parse(0x17FE1234).messageTypeName)
}
}