Skip to content

Commit

Permalink
Implement Invoke wildcard Btn in CHIPTool (#25587)
Browse files Browse the repository at this point in the history
  • Loading branch information
joonhaengHeo authored and pull[bot] committed Nov 21, 2023
1 parent c2a63ad commit c6cc874
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ChipIdLookup
import chip.devicecontroller.InvokeCallback
import chip.devicecontroller.ReportCallback
import chip.devicecontroller.ResubscriptionAttemptCallback
import chip.devicecontroller.SubscriptionEstablishedCallback
Expand All @@ -23,8 +24,10 @@ import chip.devicecontroller.model.AttributeWriteRequest
import chip.devicecontroller.model.ChipAttributePath
import chip.devicecontroller.model.ChipEventPath
import chip.devicecontroller.model.ChipPathId
import chip.devicecontroller.model.InvokeElement
import chip.devicecontroller.model.NodeState
import chip.tlv.AnonymousTag
import chip.tlv.ContextSpecificTag
import chip.tlv.TlvWriter
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.R
Expand Down Expand Up @@ -86,6 +89,18 @@ class WildcardFragment : Fragment() {
}
}

private val invokeCallback = object : InvokeCallback {
override fun onError(e: java.lang.Exception?) {
Log.e(TAG, "Report error", e)
}

override fun onResponse(invokeElement: InvokeElement?, successCode: Long) {
val text = "Invoke Response : $invokeElement, $successCode"
requireActivity().runOnUiThread { binding.outputTv.text = text }
}

}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -98,6 +113,7 @@ class WildcardFragment : Fragment() {
binding.writeBtn.setOnClickListener { scope.launch { showWriteDialog() } }
binding.subscribeEventBtn.setOnClickListener { scope.launch { showSubscribeDialog(EVENT) } }
binding.readEventBtn.setOnClickListener { scope.launch { showReadDialog(EVENT) } }
binding.invokeBtn.setOnClickListener { scope.launch { showInvokeDialog() } }

addressUpdateFragment =
childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment
Expand Down Expand Up @@ -234,6 +250,37 @@ class WildcardFragment : Fragment() {
imTimeoutMs)
}

private suspend fun invoke(invokeField: 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 invokeElement = InvokeElement.newInstance(endpointId, clusterId, commandId, tlvWriter.getEncoded(), null)
deviceController.invoke(invokeCallback,
ChipClient.getConnectedDevicePointer(requireContext(),
addressUpdateFragment.deviceId),
invokeElement,
timedRequestTimeoutMs,
imTimeoutMs)
}

private fun showReadDialog(type: Int) {
val dialogView = requireActivity().layoutInflater.inflate(R.layout.read_dialog, null)
val dialog = AlertDialog.Builder(requireContext()).apply {
Expand Down Expand Up @@ -316,12 +363,34 @@ class WildcardFragment : Fragment() {
dialog.show()
}

private fun showInvokeDialog() {
binding.outputTv.text = ""
val dialogView = requireActivity().layoutInflater.inflate(R.layout.invoke_dialog, null)
val invokeValueEd = dialogView.findViewById<EditText>(R.id.invokeValueEd)
val dialog = AlertDialog.Builder(requireContext()).apply {
setView(dialogView)
}.create()

dialogView.findViewById<Button>(R.id.invokeBtn).setOnClickListener {
val invokeValue = invokeValueEd.text.toString()
val timedRequestTimeoutMs = dialogView.findViewById<EditText>(R.id.timedRequestTimeoutEd).text.toString()
val imTimeout = dialogView.findViewById<EditText>(R.id.imTimeoutEd).text.toString()
scope.launch {
invoke(invokeValue,
if (timedRequestTimeoutMs.isEmpty()) { 0 } else { timedRequestTimeoutMs.toInt() },
if (imTimeout.isEmpty()) { 0 } else { imTimeout.toInt() } )
requireActivity().runOnUiThread { dialog.dismiss() }
}
}
dialog.show()
}

private fun getChipPathIdForText(text: String): ChipPathId {
return if (text.isEmpty()) ChipPathId.forWildcard() else ChipPathId.forId(text.toLong())
}

interface TlvWriterInterface {
fun generate(writer : TlvWriter, value: String)
fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag = AnonymousTag)
}

companion object {
Expand All @@ -332,39 +401,39 @@ class WildcardFragment : Fragment() {

private val TLV_MAP = mapOf(
"UnsignedInt" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value.toUInt())
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value.toUInt())
}
},
"Int" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value.toInt())
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value.toInt())
}
},
"Boolean" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value.toBoolean())
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value.toBoolean())
}
},
"Float" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value.toFloat())
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value.toFloat())
}
},
"Double" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value.toDouble())
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value.toDouble())
}
},
"String" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
writer.put(AnonymousTag, value)
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
writer.put(tag, value)
}
},
"ByteArray(Hex)" to object:TlvWriterInterface {
override fun generate(writer : TlvWriter, value: String) {
override fun generate(writer : TlvWriter, value: String, tag: chip.tlv.Tag) {
val byteStringValue = ByteString.fromHex(value)
writer.put(AnonymousTag, byteStringValue)
writer.put(tag, byteStringValue)
}
},
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp">

<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/invoke_dialog_title_text"
android:textSize="22sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/invokeValueEd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/invoke_dialog_write_value_hint"
android:inputType="text"
android:textSize="16sp"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" />

<EditText
android:id="@+id/timedRequestTimeoutEd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/invoke_dialog_timed_request_timeout_hint"
android:inputType="number"
android:textSize="16sp"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/invokeValueEd" />

<EditText
android:id="@+id/imTimeoutEd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/invoke_dialog_im_timeout_hint"
android:inputType="number"
android:textSize="16sp"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/timedRequestTimeoutEd"
app:layout_constraintBottom_toTopOf="@id/exampleHint"/>

<TextView
android:id="@+id/exampleHint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/invoke_dialog_user_guide_hint"
android:textSize="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imTimeoutEd"
app:layout_constraintBottom_toTopOf="@id/invokeBtn"
tools:ignore="SmallSp" />

<Button
android:id="@+id/invokeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/invoke_dialog_write_btn_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:constraint_referenced_ids="endpointIdLabel,endpointIdEd,clusterIdLabel,clusterIdEd,attributeIdLabel,attributeIdEd,eventIdLabel,eventIdEd"
app:constraint_referenced_ids="endpointIdLabel,endpointIdEd,clusterIdLabel,clusterIdEd,attributeIdLabel,attributeIdEd,eventIdLabel,eventIdEd,commandIdLabel,commandIdEd"
app:flow_horizontalBias="0.0"
app:flow_horizontalGap="8dp"
app:flow_horizontalStyle="packed"
Expand Down Expand Up @@ -92,6 +92,22 @@
android:inputType="number"
android:hint="@string/wildcard_help_label"/>

<TextView
android:id="@+id/commandIdLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textSize="16sp"
android:text="@string/command_id_label" />

<EditText
android:id="@+id/commandIdEd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:inputType="number"
android:hint="@string/wildcard_help_label"/>

<Button
android:id="@+id/readBtn"
android:layout_width="wrap_content"
Expand All @@ -117,6 +133,20 @@
android:text="@string/wildcard_write_btn_text"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/readBtn"
app:layout_constraintEnd_toStartOf="@id/invokeBtn"
app:layout_constraintTop_toBottomOf="@id/flow"/>

<Button
android:id="@+id/invokeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:layout_gravity="center"
android:text="@string/wildcard_invoke_btn_text"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/writeBtn"
app:layout_constraintEnd_toStartOf="@id/subscribeBtn"
app:layout_constraintTop_toBottomOf="@id/flow"/>

Expand All @@ -130,7 +160,7 @@
android:layout_gravity="center"
android:text="@string/wildcard_subscribe_btn_text"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/writeBtn"
app:layout_constraintStart_toEndOf="@id/invokeBtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/flow"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
android:id="@+id/writeValueTypeSp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/subscribe_dialog_is_urgent_hint"
android:hint="@string/write_dialog_value_type_hint"
android:inputType="text"
android:spinnerMode="dropdown"
android:textSize="16sp"
Expand Down
10 changes: 10 additions & 0 deletions examples/android/CHIPTool/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,23 @@
<string name="write_dialog_im_timeout_hint">Timeout</string>
<string name="write_dialog_user_guide_hint">Example:\nIdentifyCluster, IdentifyTime - Type : UInt\nBasicInformationCluster, UserLabel - Type : String\nIf you want to enter an array, separate the value by \',\'.(abc,def)</string>

<string name="invoke_dialog_title_text">Invoke</string>
<string name="invoke_dialog_write_btn_text">Invoke</string>
<string name="invoke_dialog_value_type_hint">Invoke Value Type</string>
<string name="invoke_dialog_write_value_hint">Invoke Value</string>
<string name="invoke_dialog_timed_request_timeout_hint">Timed Request Timeout</string>
<string name="invoke_dialog_im_timeout_hint">Timeout</string>
<string name="invoke_dialog_user_guide_hint">Usage : [Type]:[Value],[Type]:[Value]\nType:UnsignedInt, Int, Boolean, Float, Double, String, ByteArray(Hex)\nExample:\nLevelControlCluster, moveToLevel : UnsignedInt:100,UnsignedInt:0</string>

<string name="endpoint_id_label">Endpoint ID</string>
<string name="cluster_id_label">Cluster ID</string>
<string name="attribute_id_label">Attribute ID</string>
<string name="event_id_label">Event ID</string>
<string name="command_id_label">Command ID</string>
<string name="wildcard_help_label">Leave blank for wildcard</string>
<string name="wildcard_subscribe_btn_text">Subscribe</string>
<string name="wildcard_read_btn_text">Read</string>
<string name="wildcard_invoke_btn_text">Invoke</string>
<string name="wildcard_write_btn_text">Write</string>
<string name="wildcard_subscribe_event_btn_text">Subscribe Event</string>
<string name="wildcard_read_event_btn_text">Read Event</string>
Expand Down

0 comments on commit c6cc874

Please sign in to comment.