Skip to content

Commit

Permalink
[Android] Support subscriptions (#10294)
Browse files Browse the repository at this point in the history
* Support subscriptions in Android

* Regenerate
  • Loading branch information
austinh0 authored and pull[bot] committed Oct 18, 2021
1 parent 2a3cb0b commit 1610098
Show file tree
Hide file tree
Showing 8 changed files with 10,833 additions and 14,143 deletions.
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
package com.google.chip.chiptool.clusterclient

import android.app.AlertDialog
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.SeekBar
import android.widget.Toast
import androidx.fragment.app.Fragment
import chip.devicecontroller.ChipClusters
import chip.devicecontroller.ChipClusters.OnOffCluster
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ChipDeviceControllerException
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.GenericChipDeviceListener
import com.google.chip.chiptool.R
import com.google.chip.chiptool.util.DeviceIdUtil
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import kotlinx.android.synthetic.main.on_off_client_fragment.commandStatusTv
import kotlinx.android.synthetic.main.on_off_client_fragment.deviceIdEd
import kotlinx.android.synthetic.main.on_off_client_fragment.fabricIdEd
import kotlinx.android.synthetic.main.on_off_client_fragment.levelBar
import kotlinx.android.synthetic.main.on_off_client_fragment.reportStatusTv
import kotlinx.android.synthetic.main.on_off_client_fragment.view.levelBar
import kotlinx.android.synthetic.main.on_off_client_fragment.view.offBtn
import kotlinx.android.synthetic.main.on_off_client_fragment.view.onBtn
import kotlinx.android.synthetic.main.on_off_client_fragment.view.readBtn
import kotlinx.android.synthetic.main.on_off_client_fragment.view.showSubscribeDialogBtn
import kotlinx.android.synthetic.main.on_off_client_fragment.view.toggleBtn
import kotlinx.android.synthetic.main.on_off_client_fragment.view.updateAddressBtn
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -51,6 +58,7 @@ class OnOffClientFragment : Fragment() {
offBtn.setOnClickListener { scope.launch { sendOffCommandClick() } }
toggleBtn.setOnClickListener { scope.launch { sendToggleCommandClick() } }
readBtn.setOnClickListener { scope.launch { sendReadOnOffClick() } }
showSubscribeDialogBtn.setOnClickListener { showSubscribeDialog() }

levelBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
Expand Down Expand Up @@ -85,6 +93,58 @@ class OnOffClientFragment : Fragment() {
})
}

private fun showSubscribeDialog() {
val dialogView = requireActivity().layoutInflater.inflate(R.layout.subscribe_dialog, null)
val dialog = AlertDialog.Builder(requireContext()).apply {
setView(dialogView)
}.create()

val minIntervalEd = dialogView.findViewById<EditText>(R.id.minIntervalEd)
val maxIntervalEd = dialogView.findViewById<EditText>(R.id.maxIntervalEd)
dialogView.findViewById<Button>(R.id.subscribeBtn).setOnClickListener {
scope.launch {
sendSubscribeOnOffClick(
minIntervalEd.text.toString().toInt(),
maxIntervalEd.text.toString().toInt()
)
dialog.dismiss()
}
}
dialog.show()
}

private suspend fun sendSubscribeOnOffClick(minInterval: Int, maxInterval: Int) {
val onOffCluster = getOnOffClusterForDevice()

val subscribeCallback = object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
val message = "Subscribe on/off success"
Log.v(TAG, message)
showMessage(message)

onOffCluster.reportOnOffAttribute(object : ChipClusters.BooleanAttributeCallback {
override fun onSuccess(on: Boolean) {
Log.v(TAG, "Report on/off attribute value: $on")

val formatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
val time = formatter.format(Calendar.getInstance(Locale.getDefault()).time)
showReportMessage("Report on/off at $time: ${if (on) "ON" else "OFF"}")
}

override fun onError(ex: Exception) {
Log.e(TAG, "Error reporting on/off attribute", ex)
showReportMessage("Error reporting on/off attribute: $ex")
}
})
}

override fun onError(ex: Exception) {
Log.e(TAG, "Error configuring on/off attribute", ex)
}
}
onOffCluster.subscribeOnOffAttribute(subscribeCallback, minInterval, maxInterval)
}

override fun onStart() {
super.onStart()
// TODO: use the fabric ID that was used to commission the device
Expand All @@ -98,6 +158,7 @@ class OnOffClientFragment : Fragment() {

override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
Log.d(TAG, "onCommissioningComplete for nodeId $nodeId: $errorCode")
showMessage("Address update complete for nodeId $nodeId with code $errorCode")
}

override fun onNotifyChipConnectionClosed() {
Expand All @@ -119,10 +180,10 @@ class OnOffClientFragment : Fragment() {
}

private fun updateAddressClick() {
try{
try {
deviceController.updateDevice(
fabricIdEd.text.toString().toULong().toLong(),
deviceIdEd.text.toString().toULong().toLong()
fabricIdEd.text.toString().toULong().toLong(),
deviceIdEd.text.toString().toULong().toLong()
)
showMessage("Address update started")
} catch (ex: Exception) {
Expand All @@ -132,7 +193,8 @@ class OnOffClientFragment : Fragment() {

private suspend fun sendLevelCommandClick() {
val cluster = ChipClusters.LevelControlCluster(
ChipClient.getConnectedDevicePointer(requireContext(), deviceIdEd.text.toString().toLong()), 1
ChipClient.getConnectedDevicePointer(requireContext(), deviceIdEd.text.toString().toLong()),
LEVEL_CONTROL_CLUSTER_ENDPOINT
)
cluster.moveToLevel(object : ChipClusters.DefaultClusterCallback {
override fun onSuccess() {
Expand Down Expand Up @@ -189,7 +251,8 @@ class OnOffClientFragment : Fragment() {

private suspend fun getOnOffClusterForDevice(): OnOffCluster {
return OnOffCluster(
ChipClient.getConnectedDevicePointer(requireContext(), deviceIdEd.text.toString().toLong()), 1
ChipClient.getConnectedDevicePointer(requireContext(), deviceIdEd.text.toString().toLong()),
ON_OFF_CLUSTER_ENDPOINT
)
}

Expand All @@ -199,8 +262,18 @@ class OnOffClientFragment : Fragment() {
}
}

private fun showReportMessage(msg: String) {
requireActivity().runOnUiThread {
reportStatusTv.text = msg
}
}

companion object {
private const val TAG = "OnOffClientFragment"

private const val ON_OFF_CLUSTER_ENDPOINT = 1
private const val LEVEL_CONTROL_CLUSTER_ENDPOINT = 1

fun newInstance(): OnOffClientFragment = OnOffClientFragment()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,69 +39,92 @@
android:text="@string/update_device_address_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@+id/onBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_margin="16dp"
android:layout_gravity="center"
android:layout_alignParentStart="true"
android:layout_below="@id/updateAddressBtn"
android:background="@android:color/darker_gray"
android:text="@string/send_command_on_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@+id/toggleBtn"
android:layout_width="wrap_content"
<GridLayout
android:id="@+id/buttonGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_marginStart="48dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="48dp"
android:layout_gravity="center"
android:layout_below="@id/updateAddressBtn"
android:layout_toEndOf="@id/onBtn"
android:layout_toStartOf="@+id/offBtn"
android:background="@android:color/darker_gray"
android:text="@string/send_command_toggle_btn_text"
android:textSize="16sp"/>
android:layout_below="@+id/updateAddressBtn"
android:columnCount="3"
android:rowCount="2">
<TextView
android:id="@+id/onBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_margin="8dp"
android:layout_gravity="center"
android:layout_columnWeight="1"
android:layout_column="0"
android:layout_row="0"
android:background="@android:color/darker_gray"
android:text="@string/send_command_on_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@id/offBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_margin="16dp"
android:layout_gravity="center"
android:gravity="center"
android:layout_alignParentEnd="true"
android:layout_below="@id/updateAddressBtn"
android:background="@android:color/darker_gray"
android:text="@string/send_command_off_btn_text"
android:textSize="16sp"/>
<TextView
android:id="@+id/toggleBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="0"
android:padding="16dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"
android:layout_gravity="center"
android:gravity="center"
android:background="@android:color/darker_gray"
android:text="@string/send_command_toggle_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@+id/offBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_row="0"
android:padding="16dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"
android:layout_gravity="center"
android:gravity="center"
android:background="@android:color/darker_gray"
android:text="@string/send_command_off_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@+id/readBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_margin="16dp"
android:layout_gravity="center"
android:gravity="center"
android:layout_alignParentStart="true"
android:layout_below="@id/onBtn"
android:background="@android:color/darker_gray"
android:text="@string/read_on_off_attribute_btn_text"
android:textSize="16sp"/>
<TextView
android:id="@+id/readBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_row="1"
android:padding="16dp"
android:layout_margin="8dp"
android:layout_gravity="center"
android:gravity="center"
android:background="@android:color/darker_gray"
android:text="@string/read_on_off_attribute_btn_text"
android:textSize="16sp"/>

<TextView
android:id="@+id/showSubscribeDialogBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_row="1"
android:padding="16dp"
android:layout_margin="8dp"
android:layout_gravity="center"
android:gravity="center"
android:background="@android:color/darker_gray"
android:text="@string/show_subscribe_dialog_btn_text"
android:textSize="16sp"/>
</GridLayout>

<SeekBar
android:id="@+id/levelBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/readBtn"
android:layout_below="@id/buttonGrid"
android:layout_gravity="center"
android:gravity="center"
android:max="254"
Expand All @@ -111,10 +134,20 @@
android:id="@+id/commandStatusTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_below="@id/levelBar"
android:padding="16dp"
android:minLines="4"
android:singleLine="false"
android:textSize="20sp" />

<TextView
android:id="@+id/reportStatusTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/commandStatusTv"
android:padding="16dp"
android:minLines="4"
android:textSize="20sp"/>
android:singleLine="false"
android:textSize="20sp" />

</RelativeLayout>
46 changes: 46 additions & 0 deletions src/android/CHIPTool/app/src/main/res/layout/subscribe_dialog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?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"
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/subscribe_dialog_title_text"
android:textSize="22sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/minIntervalEd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/subscribe_dialog_min_interval_hint"
android:inputType="number"
android:textSize="16sp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText" />

<EditText
android:id="@+id/maxIntervalEd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/subscribe_dialog_max_interval_hint"
android:inputType="number"
android:textSize="16sp"
android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/minIntervalEd"
app:layout_constraintBottom_toTopOf="@+id/subscribeBtn"/>

<Button
android:id="@+id/subscribeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subscribe_dialog_subscribe_btn_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit 1610098

Please sign in to comment.