From 1219955b5ce166008a81e851e646abb80fc10b91 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Tue, 29 Aug 2023 03:05:09 +0900 Subject: [PATCH] [Android] Remove TLV Decode / encode API in ChipTool (#28767) * Support JSON in Android ChipTool * restyle kotlin * Fix build error * Check isEndOfTlv in ArrayValue * Add kotlin exclude codeing check * Add TestData in Android ChipTool * Move TlvReader toAny method to ChipTool * rollback tlvtoJson class * rollback json test * Update kotlin codestyle --- .../clusterclient/BasicClientFragment.kt | 17 ++-- .../clusterclient/MultiAdminClientFragment.kt | 8 +- .../clusterclient/OnOffClientFragment.kt | 11 ++- .../clusterclient/OpCredClientFragment.kt | 38 +------- .../clusterclient/SensorClientFragment.kt | 5 +- .../clusterclient/WildcardFragment.kt | 93 +++++++++---------- .../google/chip/chiptool/util/TlvParseUtil.kt | 86 ----------------- .../com/google/chip/chiptool/util/TlvUtil.kt | 53 +++++++++++ scripts/build/builders/android.py | 1 + .../dry_run_android-arm64-chip-tool.txt | 2 + src/controller/java/BUILD.gn | 1 + .../java/src/chip/jsontlv/JsonToTlv.kt | 15 ++- src/controller/java/src/chip/tlv/values.kt | 16 ++++ 13 files changed, 160 insertions(+), 186 deletions(-) delete mode 100644 examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvParseUtil.kt create mode 100644 examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvUtil.kt diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt index 4d19a56c10c5c5..7e035a6d17149d 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt @@ -17,11 +17,14 @@ import chip.devicecontroller.model.AttributeWriteRequest import chip.devicecontroller.model.ChipAttributePath import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.NodeState +import chip.tlv.AnonymousTag +import chip.tlv.TlvReader +import chip.tlv.TlvWriter import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.BasicClientFragmentBinding -import com.google.chip.chiptool.util.TlvParseUtil +import com.google.chip.chiptool.util.toAny import java.util.Optional import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -55,7 +58,7 @@ class BasicClientFragment : Fragment() { // TODO : Need to be implement poj-to-tlv sendWriteAttribute( BasicInformation.Attribute.NodeLabel, - TlvParseUtil.encode(binding.nodeLabelEd.text.toString()) + TlvWriter().put(AnonymousTag, binding.nodeLabelEd.text.toString()).getEncoded() ) binding.nodeLabelEd.onEditorAction(EditorInfo.IME_ACTION_DONE) } @@ -65,7 +68,7 @@ class BasicClientFragment : Fragment() { // TODO : Need to be implement poj-to-tlv sendWriteAttribute( BasicInformation.Attribute.Location, - TlvParseUtil.encode(binding.locationEd.text.toString()) + TlvWriter().put(AnonymousTag, binding.locationEd.text.toString()).getEncoded() ) binding.locationEd.onEditorAction(EditorInfo.IME_ACTION_DONE) } @@ -75,7 +78,7 @@ class BasicClientFragment : Fragment() { // TODO : Need to be implement poj-to-tlv sendWriteAttribute( BasicInformation.Attribute.LocalConfigDisabled, - TlvParseUtil.encode(isChecked) + TlvWriter().put(AnonymousTag, isChecked).getEncoded() ) } } @@ -150,13 +153,13 @@ class BasicClientFragment : Fragment() { } override fun onReport(nodeState: NodeState?) { - val value = + val tlv = nodeState ?.getEndpointState(endpointId) ?.getClusterState(clusterId) ?.getAttributeState(attributeId) - ?.value - ?: "null" + ?.tlv + val value = tlv?.let { TlvReader(it).toAny() } Log.i(TAG, "[Read Success] $attributeName: $value") showMessage("[Read Success] $attributeName: $value") } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt index 4df9d2a1a1d230..e60520c6597bb6 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt @@ -17,11 +17,13 @@ import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.InvokeElement import chip.devicecontroller.model.NodeState import chip.tlv.AnonymousTag +import chip.tlv.TlvReader import chip.tlv.TlvWriter import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.MultiAdminClientFragmentBinding +import com.google.chip.chiptool.util.toAny import kotlinx.coroutines.* class MultiAdminClientFragment : Fragment() { @@ -209,13 +211,13 @@ class MultiAdminClientFragment : Fragment() { deviceController.readAttributePath( object : ReportCallback { override fun onReport(nodeState: NodeState?) { - val value = + val tlv = nodeState ?.getEndpointState(endpointId) ?.getClusterState(clusterId) ?.getAttributeState(attributeId) - ?.value - ?: "null" + ?.tlv + val value = tlv?.let { TlvReader(it).toAny() } Log.i(TAG, "read $attributeName: $value") showMessage("read $attributeName: $value") } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt index b4bc72c103c986..8efe4334445f93 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt @@ -24,12 +24,13 @@ import chip.devicecontroller.model.InvokeElement import chip.devicecontroller.model.NodeState import chip.tlv.AnonymousTag import chip.tlv.ContextSpecificTag +import chip.tlv.TlvReader import chip.tlv.TlvWriter import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.OnOffClientFragmentBinding -import com.google.chip.chiptool.util.TlvParseUtil +import com.google.chip.chiptool.util.toAny import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -116,13 +117,13 @@ class OnOffClientFragment : Fragment() { } override fun onReport(nodeState: NodeState?) { - val value = + val tlv = nodeState ?.getEndpointState(endpointId) ?.getClusterState(clusterId) ?.getAttributeState(attributeId) - ?.value - ?: "null" + ?.tlv + val value = tlv?.let { TlvReader(it).toAny() } Log.v(TAG, "On/Off attribute value: $value") showMessage("On/Off attribute value: $value") } @@ -201,7 +202,7 @@ class OnOffClientFragment : Fragment() { ?.tlv ?: return // TODO : Need to be implement poj-to-tlv - val value = TlvParseUtil.decodeBoolean(tlv) + val value = TlvReader(tlv).getBool(AnonymousTag) val formatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault()) val time = formatter.format(Calendar.getInstance(Locale.getDefault()).time) val message = "Subscribed on/off value at $time: ${if (value) "ON" else "OFF"}" diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt index b14f4a57062a57..86c96b34d1627c 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt @@ -8,8 +8,6 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import chip.devicecontroller.ChipDeviceController -import chip.devicecontroller.ChipStructs -import chip.devicecontroller.ChipTLVValueDecoder import chip.devicecontroller.ClusterIDMapping.OperationalCredentials import chip.devicecontroller.InvokeCallback import chip.devicecontroller.ReportCallback @@ -19,11 +17,13 @@ import chip.devicecontroller.model.InvokeElement import chip.devicecontroller.model.NodeState import chip.tlv.AnonymousTag import chip.tlv.ContextSpecificTag +import chip.tlv.TlvReader import chip.tlv.TlvWriter import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.OpCredClientFragmentBinding +import com.google.chip.chiptool.util.toAny import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -115,13 +115,6 @@ class OpCredClientFragment : Fragment() { } override fun onReport(nodeState: NodeState?) { - val value = - nodeState - ?.getEndpointState(endpointId) - ?.getClusterState(clusterId) - ?.getAttributeState(attributeId) - ?.value - ?: "null" val tlv = nodeState ?.getEndpointState(endpointId) @@ -129,30 +122,9 @@ class OpCredClientFragment : Fragment() { ?.getAttributeState(attributeId) ?.tlv - if (tlv == null) { - Log.i(TAG, "OpCred $attributeName value: $value") - showMessage("OpCred $attributeName value: $value") - return - } - - val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) - when (attribute) { - OperationalCredentials.Attribute.Fabrics -> { - val ret = - ChipTLVValueDecoder.decodeAttributeValue< - List - >( - attributePath, - tlv - ) - Log.i(TAG, "OpCred $attributeName value: $value") - showMessage(ret.toString()) - } - else -> { - Log.i(TAG, "OpCred $attributeName value: $value") - showMessage("OpCred $attributeName value: $value") - } - } + val value = tlv?.let { TlvReader(it).toAny() } + Log.i(TAG, "OpCred $attributeName value: $value") + showMessage("OpCred $attributeName value: $value") } }, devicePtr, diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt index 53294c8037f981..594d158ee04049 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt @@ -17,11 +17,12 @@ import chip.devicecontroller.ReportCallback import chip.devicecontroller.model.ChipAttributePath import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.NodeState +import chip.tlv.AnonymousTag +import chip.tlv.TlvReader import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.SensorClientFragmentBinding import com.google.chip.chiptool.util.DeviceIdUtil -import com.google.chip.chiptool.util.TlvParseUtil import com.jjoe64.graphview.LabelFormatter import com.jjoe64.graphview.Viewport import com.jjoe64.graphview.series.DataPoint @@ -224,7 +225,7 @@ class SensorClientFragment : Fragment() { // TODO : Need to be implement poj-to-tlv val value = try { - TlvParseUtil.decodeInt(tlv) + TlvReader(tlv).getInt(AnonymousTag) } catch (ex: Exception) { showMessage(R.string.sensor_client_read_error_text, "value is null") return diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index f03f68eee8c089..aa939250bdff51 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -27,13 +27,14 @@ import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.ChipPathId import chip.devicecontroller.model.InvokeElement import chip.devicecontroller.model.NodeState +import chip.jsontlv.putJsonString import chip.tlv.AnonymousTag -import chip.tlv.ContextSpecificTag import chip.tlv.TlvReader import chip.tlv.TlvWriter import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.WildcardFragmentBinding +import com.google.chip.chiptool.util.toAny import java.lang.StringBuilder import java.util.Optional import kotlin.coroutines.resume @@ -219,7 +220,8 @@ class WildcardFragment : Fragment() { stringBuilder.append("\t${ChipIdLookup.clusterIdToName(clusterId)}Cluster: {\n") clusterState.attributeStates.forEach { (attributeId, attributeState) -> val attributeName = ChipIdLookup.attributeIdToName(clusterId, attributeId) - stringBuilder.append("\t\t$attributeName: ${attributeState.value}\n") + val tlv = attributeState.tlv + stringBuilder.append("\t\t$attributeName: ${TlvReader(tlv).toAny()}\n") } clusterState.eventStates.forEach { (eventId, events) -> for (event in events) { @@ -229,7 +231,8 @@ class WildcardFragment : Fragment() { stringBuilder.append("\t\ttimestampValue: ${event.timestampValue}\n") val eventName = ChipIdLookup.eventIdToName(clusterId, eventId) - stringBuilder.append("\t\t$eventName: ${event.value}\n") + val tlv = event.tlv + stringBuilder.append("\t\t$eventName: ${TlvReader(tlv).toAny()}\n") } } stringBuilder.append("\t}\n") @@ -305,19 +308,6 @@ class WildcardFragment : Fragment() { val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString()) - val tlvWriter = TlvWriter() - val values = writeValue.split(",") - - if (values.size > 1) tlvWriter.startArray(AnonymousTag) - for (value in values) { - try { - TLV_MAP[writeValueType]?.generate(tlvWriter, value.trim()) - } catch (ex: Exception) { - Log.e(TAG, "Invalid Data Type", ex) - return - } - } - if (values.size > 1) tlvWriter.endArray() val version = if (dataVersion == null) { @@ -326,14 +316,36 @@ class WildcardFragment : Fragment() { Optional.of(dataVersion) } - val writeRequest = - AttributeWriteRequest.newInstance( - endpointId, - clusterId, - attributeId, - tlvWriter.getEncoded(), - version - ) + lateinit var writeRequest: AttributeWriteRequest + + if (writeValueType == "json") { + writeRequest = + AttributeWriteRequest.newInstance(endpointId, clusterId, attributeId, writeValue, version) + } else { + val tlvWriter = TlvWriter() + val values = writeValue.split(",") + + if (values.size > 1) tlvWriter.startArray(AnonymousTag) + for (value in values) { + try { + TLV_MAP[writeValueType]?.generate(tlvWriter, value.trim()) + } catch (ex: Exception) { + Log.e(TAG, "Invalid Data Type", ex) + return + } + } + if (values.size > 1) tlvWriter.endArray() + + writeRequest = + AttributeWriteRequest.newInstance( + endpointId, + clusterId, + attributeId, + tlvWriter.getEncoded(), + version + ) + } + deviceController.write( writeAttributeCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), @@ -343,35 +355,14 @@ class WildcardFragment : Fragment() { ) } - private suspend fun invoke(invokeField: String, timedRequestTimeoutMs: Int, imTimeoutMs: Int) { + private suspend fun invoke(invokeJson: String, timedRequestTimeoutMs: Int, imTimeoutMs: Int) { val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) val commandId = getChipPathIdForText(binding.commandIdEd.text.toString()) - val tlvWriter = TlvWriter() - val fields = - if (invokeField.isEmpty()) { - listOf() - } else { - invokeField.split(",") - } - var count = 0 - tlvWriter.startStructure(AnonymousTag) - for (field in fields) { - try { - val type = field.split(":")[0] - val value = field.split(":")[1] - - Log.d(TAG, "value : $type - $value") - TLV_MAP[type]?.generate(tlvWriter, value.trim(), ContextSpecificTag(count++)) - } catch (ex: Exception) { - Log.e(TAG, "Invalid value", ex) - return - } - } - tlvWriter.endStructure() + val jsonString = invokeJson.ifEmpty { "{}" } val invokeElement = - InvokeElement.newInstance(endpointId, clusterId, commandId, tlvWriter.getEncoded(), null) + InvokeElement.newInstance(endpointId, clusterId, commandId, null, jsonString) deviceController.invoke( invokeCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), @@ -652,6 +643,12 @@ class WildcardFragment : Fragment() { private val TLV_MAP = mapOf( + "json" to + object : TlvWriterInterface { + override fun generate(writer: TlvWriter, value: String, tag: chip.tlv.Tag) { + writer.putJsonString(tag, value) + } + }, "UnsignedInt" to object : TlvWriterInterface { override fun generate(writer: TlvWriter, value: String, tag: chip.tlv.Tag) { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvParseUtil.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvParseUtil.kt deleted file mode 100644 index f153d35783a5de..00000000000000 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvParseUtil.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.google.chip.chiptool.util - -import chip.tlv.AnonymousTag -import chip.tlv.TlvReader -import chip.tlv.TlvWriter - -object TlvParseUtil { - fun encode(input: Boolean): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: String): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: ULong): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: Long): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: UInt): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: Int): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: Float): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: Double): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun encode(input: ByteArray): ByteArray { - val tlvWriter = TlvWriter() - tlvWriter.put(AnonymousTag, input) - return tlvWriter.getEncoded() - } - - fun decodeBoolean(tlv: ByteArray): Boolean { - val tlvReader = TlvReader(tlv) - return tlvReader.getBool(AnonymousTag) - } - - fun decodeInt(tlv: ByteArray): Int { - val tlvReader = TlvReader(tlv) - return tlvReader.getInt(AnonymousTag) - } - - fun decodeUInt(tlv: ByteArray): UInt { - val tlvReader = TlvReader(tlv) - return tlvReader.getUInt(AnonymousTag) - } - - fun decodeLong(tlv: ByteArray): Long { - val tlvReader = TlvReader(tlv) - return tlvReader.getLong(AnonymousTag) - } - - fun decodeULong(tlv: ByteArray): ULong { - val tlvReader = TlvReader(tlv) - return tlvReader.getULong(AnonymousTag) - } -} diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvUtil.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvUtil.kt new file mode 100644 index 00000000000000..375381021c256e --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/util/TlvUtil.kt @@ -0,0 +1,53 @@ +package com.google.chip.chiptool.util + +import chip.tlv.AnonymousTag +import chip.tlv.ArrayValue +import chip.tlv.NullValue +import chip.tlv.StructureValue +import chip.tlv.Tag +import chip.tlv.TlvReader + +/** + * Encodes TLV into kotlin Object. If the TLV reader is positioned TLV Structure, Object will return + * to json format. + */ +fun TlvReader.toAny(tag: Tag = AnonymousTag): Any? { + val element = peekElement() + val value = element.value + value.toAny()?.let { + skipElement() + return it + } + return when (value) { + is ArrayValue -> { + buildList { + enterArray(tag) + while (!isEndOfTlv() && !isEndOfContainer()) { + add(toAny()) + } + exitContainer() + } + } + is StructureValue -> { + buildMap { + enterStructure(tag) + while (!isEndOfTlv() && !isEndOfContainer()) { + put(getTag(), toAny(getTag())) + } + exitContainer() + } + } + is NullValue -> { + skipElement() + null + } + else -> { + skipElement() + null + } + } +} + +private fun TlvReader.getTag(): Tag { + return peekElement().tag +} diff --git a/scripts/build/builders/android.py b/scripts/build/builders/android.py index 7b12090b9f15f5..a5b86e7ccd1388 100644 --- a/scripts/build/builders/android.py +++ b/scripts/build/builders/android.py @@ -234,6 +234,7 @@ def copyToSrcAndroid(self): "CHIPController.jar": "src/controller/java/CHIPController.jar", "OnboardingPayload.jar": "src/controller/java/OnboardingPayload.jar", "AndroidPlatform.jar": "src/platform/android/AndroidPlatform.jar", + "libCHIPJson.jar": "src/controller/java/libCHIPJson.jar", "libCHIPTlv.jar": "src/controller/java/libCHIPTlv.jar", "CHIPClusters.jar": "src/controller/java/CHIPClusters.jar", "CHIPClusterID.jar": "src/controller/java/CHIPClusterID.jar", diff --git a/scripts/build/testdata/dry_run_android-arm64-chip-tool.txt b/scripts/build/testdata/dry_run_android-arm64-chip-tool.txt index 766a82be3bb318..41de17332bd7e7 100644 --- a/scripts/build/testdata/dry_run_android-arm64-chip-tool.txt +++ b/scripts/build/testdata/dry_run_android-arm64-chip-tool.txt @@ -29,6 +29,8 @@ cp {out}/android-arm64-chip-tool/lib/src/controller/java/OnboardingPayload.jar { cp {out}/android-arm64-chip-tool/lib/src/platform/android/AndroidPlatform.jar {root}/examples/android/CHIPTool/app/libs/AndroidPlatform.jar +cp {out}/android-arm64-chip-tool/lib/src/controller/java/libCHIPJson.jar {root}/examples/android/CHIPTool/app/libs/libCHIPJson.jar + cp {out}/android-arm64-chip-tool/lib/src/controller/java/libCHIPTlv.jar {root}/examples/android/CHIPTool/app/libs/libCHIPTlv.jar cp {out}/android-arm64-chip-tool/lib/src/controller/java/CHIPClusters.jar {root}/examples/android/CHIPTool/app/libs/CHIPClusters.jar diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index a2865ffd326c1c..2cbb402a512f87 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -372,6 +372,7 @@ android_library("java") { deps = [ ":chipcluster", ":chipclusterID", + ":jsontlv", ":tlv", "${chip_root}/third_party/java_deps:annotation", ] diff --git a/src/controller/java/src/chip/jsontlv/JsonToTlv.kt b/src/controller/java/src/chip/jsontlv/JsonToTlv.kt index 6f7cc05bde7081..01b16c2b1b6515 100644 --- a/src/controller/java/src/chip/jsontlv/JsonToTlv.kt +++ b/src/controller/java/src/chip/jsontlv/JsonToTlv.kt @@ -44,8 +44,19 @@ import java.util.Base64 * @throws IllegalArgumentException if the data was invalid */ fun TlvWriter.fromJsonString(json: String): ByteArray { - validateIsJsonObjectAndConvert(JsonParser.parseString(json), AnonymousTag) - return validateTlv().getEncoded() + return putJsonString(AnonymousTag, json).validateTlv().getEncoded() +} + +/** + * Converts Json string into TLV writer object. + * + * @param tag the TLV tag to be encoded. + * @param json String representing Json to be converted to TLV. + * @throws IllegalArgumentException if the data was invalid + */ +fun TlvWriter.putJsonString(tag: Tag, json: String): TlvWriter { + validateIsJsonObjectAndConvert(JsonParser.parseString(json), tag) + return this } /** diff --git a/src/controller/java/src/chip/tlv/values.kt b/src/controller/java/src/chip/tlv/values.kt index 21dc88fb958126..8f9c27a83e2c3b 100644 --- a/src/controller/java/src/chip/tlv/values.kt +++ b/src/controller/java/src/chip/tlv/values.kt @@ -26,6 +26,8 @@ sealed class Value { internal abstract fun toType(): Type internal abstract fun encode(): ByteArray + + open fun toAny(): Any? = null } /** Represents a signed integer value of a TLV element. */ @@ -33,6 +35,8 @@ data class IntValue(val value: Long) : Value() { override fun toType() = SignedIntType(signedIntSize(value)) override fun encode() = value.toByteArrayLittleEndian(toType().valueSize) + + override fun toAny() = value } /** Represents an unsigned integer value of a TLV element. */ @@ -40,6 +44,8 @@ data class UnsignedIntValue(val value: Long) : Value() { override fun toType() = UnsignedIntType(unsignedIntSize(value.toULong())) override fun encode() = value.toByteArrayLittleEndian(toType().valueSize) + + override fun toAny() = value } /** Represents a boolean value of a TLV element. */ @@ -47,6 +53,8 @@ data class BooleanValue(val value: Boolean) : Value() { override fun toType() = BooleanType(value) override fun encode() = ByteArray(0) + + override fun toAny() = value } /** Represents a floating-point Float value of a TLV element. */ @@ -54,6 +62,8 @@ data class FloatValue(val value: Float) : Value() { override fun toType() = FloatType() override fun encode() = floatToIntBits(value).toByteArrayLittleEndian(4) + + override fun toAny() = value } /** Represents a floating-point DoubleFloat value of a TLV element. */ @@ -61,6 +71,8 @@ data class DoubleValue(val value: Double) : Value() { override fun toType() = DoubleType() override fun encode() = doubleToLongBits(value).toByteArrayLittleEndian(8) + + override fun toAny() = value } /** Represents a UTF8 string value of a TLV element. */ @@ -69,6 +81,8 @@ data class Utf8StringValue(val value: String) : Value() { override fun encode() = value.toByteArray().size.toByteArrayLittleEndian(toType().lengthSize) + value.toByteArray() + + override fun toAny() = value } /** Represents an octet string value of a TLV element. */ @@ -76,6 +90,8 @@ data class ByteStringValue(val value: ByteArray) : Value() { override fun toType() = ByteStringType(unsignedIntSize(value.size.toULong())) override fun encode() = value.size.toByteArrayLittleEndian(toType().lengthSize) + value + + override fun toAny() = value } /** Represents a null value in a TLV element. */