diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/data/BTDeviceInfo.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/data/BTDeviceInfo.kt new file mode 100644 index 00000000000..bdbf723d539 --- /dev/null +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/data/BTDeviceInfo.kt @@ -0,0 +1,9 @@ +package net.osmand.shared.data + +import net.osmand.shared.util.Localization + +data class BTDeviceInfo(val name: String, val address: String) { + companion object { + val UNKNOWN_DEVICE = BTDeviceInfo(Localization.getString("unknown_bt_device"), "") + } +} \ No newline at end of file diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDCommand.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDCommand.kt index 0fb526e88e4..7b5f9f552a1 100644 --- a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDCommand.kt +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDCommand.kt @@ -1,21 +1,24 @@ package net.osmand.shared.obd enum class OBDCommand( + val commandGroup: String, val command: String, private val responseParser: (String) -> String, - val isStale: Boolean = false) { - OBD_SUPPORTED_LIST1_COMMAND("00", OBDUtils::parseSupportedCommandsResponse, true), - OBD_SUPPORTED_LIST2_COMMAND("20", OBDUtils::parseSupportedCommandsResponse, true), - OBD_SUPPORTED_LIST3_COMMAND("40", OBDUtils::parseSupportedCommandsResponse, true), - OBD_BATTERY_VOLTAGE_COMMAND("42", OBDUtils::parseBatteryVoltageResponse), - OBD_AMBIENT_AIR_TEMPERATURE_COMMAND("46", OBDUtils::parseAmbientTempResponse), - OBD_RPM_COMMAND("0C", OBDUtils::parseRpmResponse), - OBD_SPEED_COMMAND("0D", OBDUtils::parseSpeedResponse), - OBD_AIR_INTAKE_TEMP_COMMAND("0F", OBDUtils::parseIntakeAirTempResponse), - OBD_ENGINE_COOLANT_TEMP_COMMAND("05", OBDUtils::parseEngineCoolantTempResponse), - OBD_FUEL_CONSUMPTION_RATE_COMMAND("5E", OBDUtils::parseFuelConsumptionRateResponse), - OBD_FUEL_TYPE_COMMAND("51", OBDUtils::parseFuelTypeResponse, true), - OBD_FUEL_LEVEL_COMMAND("2F", OBDUtils::parseFuelLevelResponse); + val isStale: Boolean = false, + val isMultiPartResponse: Boolean = false) { + OBD_SUPPORTED_LIST1_COMMAND("01", "00", OBDUtils::parseSupportedCommandsResponse, true), + OBD_SUPPORTED_LIST2_COMMAND("01", "20", OBDUtils::parseSupportedCommandsResponse, true), + OBD_SUPPORTED_LIST3_COMMAND("01", "40", OBDUtils::parseSupportedCommandsResponse, true), + OBD_BATTERY_VOLTAGE_COMMAND("01", "42", OBDUtils::parseBatteryVoltageResponse), + OBD_AMBIENT_AIR_TEMPERATURE_COMMAND("01", "46", OBDUtils::parseAmbientTempResponse), + OBD_RPM_COMMAND("01", "0C", OBDUtils::parseRpmResponse), + OBD_SPEED_COMMAND("01", "0D", OBDUtils::parseSpeedResponse), + OBD_AIR_INTAKE_TEMP_COMMAND("01", "0F", OBDUtils::parseIntakeAirTempResponse), + OBD_ENGINE_COOLANT_TEMP_COMMAND("01", "05", OBDUtils::parseEngineCoolantTempResponse), + OBD_FUEL_CONSUMPTION_RATE_COMMAND("01", "5E", OBDUtils::parseFuelConsumptionRateResponse), + OBD_FUEL_TYPE_COMMAND("01", "51", OBDUtils::parseFuelTypeResponse, true), + OBD_VIN_COMMAND("09", "02", OBDUtils::parseVINResponse, true, true), + OBD_FUEL_LEVEL_COMMAND("01", "2F", OBDUtils::parseFuelLevelResponse); fun parseResponse(response: String): String { return responseParser.invoke(response.lowercase()) diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataComputer.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataComputer.kt index e31b356a1b8..ccc860192e7 100644 --- a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataComputer.kt +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataComputer.kt @@ -101,9 +101,10 @@ object OBDDataComputer { FUEL_LEFT_DISTANCE(true, listOf(OBD_FUEL_LEVEL_COMMAND), { data -> OBDValue(OBD_FUEL_LEVEL_COMMAND, data) }), - FUEL_LEFT_LITERS(false, - listOf(OBD_FUEL_LEVEL_COMMAND), - { data -> OBDValue(OBD_FUEL_LEVEL_COMMAND, data) }), + + // FUEL_LEFT_LITERS(false, +// listOf(OBD_FUEL_LEVEL_COMMAND), +// { data -> OBDValue(OBD_FUEL_LEVEL_COMMAND, data) }), FUEL_LEFT_PERCENT(false, listOf(OBD_FUEL_LEVEL_COMMAND), { data -> OBDValue(OBD_FUEL_LEVEL_COMMAND, data) }), @@ -122,6 +123,9 @@ object OBDDataComputer { FUEL_TYPE(false, listOf(OBD_FUEL_TYPE_COMMAND), { data -> OBDIntValue(OBD_FUEL_TYPE_COMMAND, data) }), + VIN(false, + listOf(OBD_VIN_COMMAND), + { data -> OBDStringValue(OBD_VIN_COMMAND, data) }), TEMPERATURE_COOLANT(false, listOf(OBD_ENGINE_COOLANT_TEMP_COMMAND), { data -> OBDIntValue(OBD_ENGINE_COOLANT_TEMP_COMMAND, data) }); @@ -231,7 +235,7 @@ object OBDDataComputer { null } - FUEL_LEFT_LITERS, +// FUEL_LEFT_LITERS, FUEL_LEFT_PERCENT -> { if (locValues.size > 0) { locValues[locValues.size - 1].doubleValue @@ -247,6 +251,12 @@ object OBDDataComputer { null } } + + VIN -> if (locValues.size > 0) { + (locValues[locValues.size - 1] as OBDStringValue).value + } else { + null + } } } @@ -317,4 +327,17 @@ object OBDDataComputer { return accepted } } + + class OBDStringValue(cmd: OBDCommand, data: Map) : + OBDValue(cmd, data) { + var value = "" + override fun acceptData(dataField: OBDDataField?): Boolean { + var accepted = false + dataField?.let { + value = it.getValue() + accepted = true + } + return accepted + } + } } \ No newline at end of file diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataFieldType.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataFieldType.kt index 9e37cd56e4c..239f2603e52 100644 --- a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataFieldType.kt +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDataFieldType.kt @@ -10,6 +10,7 @@ enum class OBDDataFieldType(val nameId: String, private val unitNameId: String) BATTERY_VOLTAGE("obd_battery_voltage_desc", "unit_volt"), AIR_INTAKE_TEMP("obd_air_intake_temp_desc", "degree_celsius"), COOLANT_TEMP("obd_engine_coolant_temp", "degree_celsius"), + VIN("obd_vin", ""), FUEL_TYPE("obd_fuel_type", ""); fun getDisplayName(): String { diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDispatcher.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDispatcher.kt index 1db5df88e74..4b2a4c88d2b 100644 --- a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDispatcher.kt +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDDispatcher.kt @@ -26,7 +26,6 @@ object OBDDispatcher { private val log = LoggerFactory.getLogger("OBDDispatcher") private const val TERMINATE_SYMBOL = "\r\r>" private const val RESPONSE_LINE_TERMINATOR = "\r" - private const val READ_DATA_COMMAND_CODE = "01" private var job: Job? = null private var scope: CoroutineScope? = null private var readStatusListener: OBDReadStatusListener? = null @@ -49,12 +48,12 @@ object OBDDispatcher { for (command in commandQueue) { if (command.isStale) { val cachedCommandResponse = staleCommandsCache[command] - if (cachedCommandResponse != null) { + if (cachedCommandResponse != null && cachedCommandResponse != OBDUtils.INVALID_RESPONSE_CODE) { consumeResponse(command, cachedCommandResponse) continue } } - val fullCommand = "$READ_DATA_COMMAND_CODE${command.command}\r" + val fullCommand = "${command.commandGroup}${command.command}\r" val bufferToWrite = Buffer() bufferToWrite.write(fullCommand.encodeToByteArray()) outStream.write(bufferToWrite, bufferToWrite.size) @@ -99,7 +98,14 @@ object OBDDispatcher { } var response = resultRaw.toString() response = response.replace(TERMINATE_SYMBOL, "") - val listResponses = response.split(RESPONSE_LINE_TERMINATOR) + var listResponses = response.split(RESPONSE_LINE_TERMINATOR) +// val listResponses = if(command.isMultiPartResponse) { +// listOf(response) +// } else { +// } + if(command.isMultiPartResponse) { + listResponses = listOf(response.split(RESPONSE_LINE_TERMINATOR).subList(2, listResponses.size).joinToString(separator = "")) + } for (responseIndex in 1 until listResponses.size) { val result = command.parseResponse(listResponses[responseIndex]) log.debug("raw_response_$responseIndex: $result") @@ -141,11 +147,17 @@ object OBDDispatcher { readStatusListener = listener } - fun setReadWriteStreams(readStream: Source, writeStream: Sink) { + fun setReadWriteStreams(readStream: Source?, writeStream: Sink?) { scope?.cancel() inputStream = readStream outputStream = writeStream - startReadObdLooper() + if(readStream != null && writeStream != null) { + startReadObdLooper() + } + } + + fun stopReading() { + setReadWriteStreams(null, null) } private fun consumeResponse(command: OBDCommand, result: String) { @@ -155,6 +167,7 @@ object OBDDispatcher { OBDCommand.OBD_AIR_INTAKE_TEMP_COMMAND -> OBDDataField(OBDDataFieldType.AIR_INTAKE_TEMP, result) OBDCommand.OBD_ENGINE_COOLANT_TEMP_COMMAND -> OBDDataField(OBDDataFieldType.COOLANT_TEMP, result) OBDCommand.OBD_FUEL_TYPE_COMMAND -> OBDDataField(OBDDataFieldType.FUEL_TYPE, result) + OBDCommand.OBD_VIN_COMMAND -> OBDDataField(OBDDataFieldType.VIN, result) OBDCommand.OBD_FUEL_LEVEL_COMMAND -> OBDDataField(OBDDataFieldType.FUEL_LVL, result) OBDCommand.OBD_AMBIENT_AIR_TEMPERATURE_COMMAND -> OBDDataField(OBDDataFieldType.AMBIENT_AIR_TEMP, result) OBDCommand.OBD_BATTERY_VOLTAGE_COMMAND -> OBDDataField(OBDDataFieldType.BATTERY_VOLTAGE, result) diff --git a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDUtils.kt b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDUtils.kt index c4b44b1e404..392189db97f 100644 --- a/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDUtils.kt +++ b/OsmAnd-shared/src/commonMain/kotlin/net/osmand/shared/obd/OBDUtils.kt @@ -96,6 +96,22 @@ object OBDUtils { return INVALID_RESPONSE_CODE } + fun parseVINResponse(response: String): String { + val responseParts = response.split(" ") + + if (responseParts[0] == "49" && + responseParts[1] == OBDCommand.OBD_VIN_COMMAND.command.lowercase() && + responseParts.size > 3) { + val vinBuilder = StringBuilder() + for (i in 3 .. responseParts.size) { + val hexByte = responseParts[i] + vinBuilder.append(hexByte.toInt(16).toChar()) + } + return vinBuilder.toString() + } + return INVALID_RESPONSE_CODE + } + fun parseFuelConsumptionRateResponse(response: String): String { val hexValues = response.trim().split(" ") if (hexValues.size >= 4 && hexValues[0] == "41" && hexValues[1] == OBDCommand.OBD_FUEL_CONSUMPTION_RATE_COMMAND.command.lowercase()) { diff --git a/OsmAnd/res/layout/fragment_obd_main.xml b/OsmAnd/res/layout/fragment_obd_main.xml index becb38e24b8..20e47cbfd34 100644 --- a/OsmAnd/res/layout/fragment_obd_main.xml +++ b/OsmAnd/res/layout/fragment_obd_main.xml @@ -1,286 +1,238 @@ - - - - - - - - + android:layout_height="@dimen/toolbar_height" /> - + android:layout_height="60dp" + android:orientation="horizontal"> + + - + + + + android:layout_height="60dp" + android:orientation="horizontal" + android:visibility="gone"> + -