Skip to content

Commit de97473

Browse files
committed
Update to new SubscribeAttribute API
1 parent 9cc8269 commit de97473

File tree

11 files changed

+15405
-25310
lines changed

11 files changed

+15405
-25310
lines changed

src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt

+15-20
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import kotlinx.android.synthetic.main.on_off_client_fragment.view.readBtn
3131
import kotlinx.android.synthetic.main.on_off_client_fragment.view.showSubscribeDialogBtn
3232
import kotlinx.android.synthetic.main.on_off_client_fragment.view.toggleBtn
3333
import kotlinx.coroutines.CoroutineScope
34-
import kotlinx.coroutines.isActive
3534
import kotlinx.coroutines.launch
3635

3736
class OnOffClientFragment : Fragment() {
@@ -108,7 +107,9 @@ class OnOffClientFragment : Fragment() {
108107
minIntervalEd.text.toString().toInt(),
109108
maxIntervalEd.text.toString().toInt()
110109
)
111-
dialog.dismiss()
110+
requireActivity().runOnUiThread {
111+
dialog.dismiss()
112+
}
112113
}
113114
}
114115
dialog.show()
@@ -117,26 +118,20 @@ class OnOffClientFragment : Fragment() {
117118
private suspend fun sendSubscribeOnOffClick(minInterval: Int, maxInterval: Int) {
118119
val onOffCluster = getOnOffClusterForDevice()
119120

120-
val subscribeCallback = object : ChipClusters.DefaultClusterCallback {
121-
override fun onSuccess() {
122-
val message = "Subscribe on/off success"
123-
Log.v(TAG, message)
124-
showMessage(message)
125-
126-
onOffCluster.reportOnOffAttribute(object : ChipClusters.BooleanAttributeCallback {
127-
override fun onSuccess(on: Boolean) {
128-
Log.v(TAG, "Report on/off attribute value: $on")
121+
val subscribeCallback = object : ChipClusters.BooleanAttributeCallback {
122+
override fun onSuccess(value: Boolean) {
123+
val formatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
124+
val time = formatter.format(Calendar.getInstance(Locale.getDefault()).time)
125+
val message = "Subscribed on/off value at $time: ${if (value) "ON" else "OFF"}"
129126

130-
val formatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
131-
val time = formatter.format(Calendar.getInstance(Locale.getDefault()).time)
132-
showReportMessage("Report on/off at $time: ${if (on) "ON" else "OFF"}")
133-
}
127+
Log.v(TAG, message)
128+
showReportMessage(message)
129+
}
134130

135-
override fun onError(ex: Exception) {
136-
Log.e(TAG, "Error reporting on/off attribute", ex)
137-
showReportMessage("Error reporting on/off attribute: $ex")
138-
}
139-
})
131+
override fun onSubscriptionEstablished() {
132+
val message = "Subscription for on/off established"
133+
Log.v(TAG, message)
134+
showMessage(message)
140135
}
141136

142137
override fun onError(ex: Exception) {

src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt

+54-66
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,8 @@ import kotlinx.android.synthetic.main.sensor_client_fragment.clusterNameSpinner
2626
import kotlinx.android.synthetic.main.sensor_client_fragment.deviceIdEd
2727
import kotlinx.android.synthetic.main.sensor_client_fragment.endpointIdEd
2828
import kotlinx.android.synthetic.main.sensor_client_fragment.lastValueTv
29+
import kotlinx.android.synthetic.main.sensor_client_fragment.readSensorBtn
2930
import kotlinx.android.synthetic.main.sensor_client_fragment.sensorGraph
30-
import kotlinx.android.synthetic.main.sensor_client_fragment.view.clusterNameSpinner
31-
import kotlinx.android.synthetic.main.sensor_client_fragment.view.readSensorBtn
32-
import kotlinx.android.synthetic.main.sensor_client_fragment.view.sensorGraph
33-
import kotlinx.android.synthetic.main.sensor_client_fragment.view.watchSensorBtn
3431
import kotlinx.android.synthetic.main.sensor_client_fragment.watchSensorBtn
3532
import kotlinx.coroutines.CoroutineScope
3633
import kotlinx.coroutines.launch
@@ -52,53 +49,56 @@ class SensorClientFragment : Fragment() {
5249
savedInstanceState: Bundle?
5350
): View {
5451
scope = viewLifecycleOwner.lifecycleScope
52+
return inflater.inflate(R.layout.sensor_client_fragment, container, false)
53+
}
5554

56-
return inflater.inflate(R.layout.sensor_client_fragment, container, false).apply {
57-
ChipClient.getDeviceController(requireContext()).setCompletionListener(null)
58-
deviceIdEd.setOnEditorActionListener { textView, actionId, _ ->
59-
if (actionId == EditorInfo.IME_ACTION_DONE) {
60-
updateAddress(textView.text.toString())
61-
resetSensorGraph() // reset the graph on device change
62-
}
63-
actionId == EditorInfo.IME_ACTION_DONE
64-
}
65-
endpointIdEd.setOnEditorActionListener { textView, actionId, _ ->
66-
if (actionId == EditorInfo.IME_ACTION_DONE)
67-
resetSensorGraph() // reset the graph on endpoint change
68-
actionId == EditorInfo.IME_ACTION_DONE
55+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
56+
super.onViewCreated(view, savedInstanceState)
57+
58+
ChipClient.getDeviceController(requireContext()).setCompletionListener(null)
59+
deviceIdEd.setOnEditorActionListener { textView, actionId, _ ->
60+
if (actionId == EditorInfo.IME_ACTION_DONE) {
61+
updateAddress(textView.text.toString())
62+
resetSensorGraph() // reset the graph on device change
6963
}
70-
clusterNameSpinner.adapter = makeClusterNamesAdapter()
71-
clusterNameSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
72-
override fun onNothingSelected(parent: AdapterView<*>?) = Unit
73-
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
74-
resetSensorGraph() // reset the graph on cluster change
75-
}
64+
actionId == EditorInfo.IME_ACTION_DONE
65+
}
66+
endpointIdEd.setOnEditorActionListener { textView, actionId, _ ->
67+
if (actionId == EditorInfo.IME_ACTION_DONE)
68+
resetSensorGraph() // reset the graph on endpoint change
69+
actionId == EditorInfo.IME_ACTION_DONE
70+
}
71+
clusterNameSpinner.adapter = makeClusterNamesAdapter()
72+
clusterNameSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
73+
override fun onNothingSelected(parent: AdapterView<*>?) = Unit
74+
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
75+
resetSensorGraph() // reset the graph on cluster change
7676
}
77+
}
7778

78-
readSensorBtn.setOnClickListener { scope.launch { readSensorCluster() } }
79-
watchSensorBtn.setOnCheckedChangeListener { _, isChecked ->
80-
if (isChecked) {
81-
scope.launch { subscribeSensorCluster() }
82-
} else {
83-
unsubscribeSensorCluster()
84-
}
79+
readSensorBtn.setOnClickListener { scope.launch { readSensorCluster() } }
80+
watchSensorBtn.setOnCheckedChangeListener { _, isChecked ->
81+
if (isChecked) {
82+
scope.launch { subscribeSensorCluster() }
83+
} else {
84+
unsubscribeSensorCluster()
8585
}
86+
}
8687

87-
val currentTime = Calendar.getInstance().time.time
88-
sensorGraph.addSeries(sensorData)
89-
sensorGraph.viewport.isXAxisBoundsManual = true
90-
sensorGraph.viewport.setMinX(currentTime.toDouble())
91-
sensorGraph.viewport.setMaxX(currentTime.toDouble() + MIN_REFRESH_PERIOD_S * 1000 * MAX_DATA_POINTS)
92-
sensorGraph.gridLabelRenderer.padding = 20
93-
sensorGraph.gridLabelRenderer.numHorizontalLabels = 4
94-
sensorGraph.gridLabelRenderer.setHorizontalLabelsAngle(150)
95-
sensorGraph.gridLabelRenderer.labelFormatter = object : LabelFormatter {
96-
override fun setViewport(viewport: Viewport?) = Unit
97-
override fun formatLabel(value: Double, isValueX: Boolean): String {
98-
if (!isValueX)
99-
return "%.2f".format(value)
100-
return SimpleDateFormat("H:mm:ss").format(Date(value.toLong())).toString()
101-
}
88+
val currentTime = Calendar.getInstance().time.time
89+
sensorGraph.addSeries(sensorData)
90+
sensorGraph.viewport.isXAxisBoundsManual = true
91+
sensorGraph.viewport.setMinX(currentTime.toDouble())
92+
sensorGraph.viewport.setMaxX(currentTime.toDouble() + MIN_REFRESH_PERIOD_S * 1000 * MAX_DATA_POINTS)
93+
sensorGraph.gridLabelRenderer.padding = 20
94+
sensorGraph.gridLabelRenderer.numHorizontalLabels = 4
95+
sensorGraph.gridLabelRenderer.setHorizontalLabelsAngle(150)
96+
sensorGraph.gridLabelRenderer.labelFormatter = object : LabelFormatter {
97+
override fun setViewport(viewport: Viewport?) = Unit
98+
override fun formatLabel(value: Double, isValueX: Boolean): String {
99+
if (!isValueX)
100+
return "%.2f".format(value)
101+
return SimpleDateFormat("H:mm:ss").format(Date(value.toLong())).toString()
102102
}
103103
}
104104
}
@@ -243,13 +243,9 @@ class SensorClientFragment : Fragment() {
243243
},
244244
"subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
245245
val cluster = ChipClusters.TemperatureMeasurementCluster(device, endpointId)
246-
cluster.reportMeasuredValueAttribute(callback)
247-
cluster.subscribeMeasuredValueAttribute(object : ChipClusters.DefaultClusterCallback {
248-
override fun onSuccess() = Unit
249-
override fun onError(ex: Exception) {
250-
callback.onError(ex)
251-
}
252-
}, MIN_REFRESH_PERIOD_S, MAX_REFRESH_PERIOD_S)
246+
cluster.subscribeMeasuredValueAttribute(callback,
247+
MIN_REFRESH_PERIOD_S,
248+
MAX_REFRESH_PERIOD_S)
253249
},
254250
"unitValue" to 0.01,
255251
"unitSymbol" to "\u00B0C"
@@ -261,13 +257,9 @@ class SensorClientFragment : Fragment() {
261257
},
262258
"subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
263259
val cluster = ChipClusters.PressureMeasurementCluster(device, endpointId)
264-
cluster.reportMeasuredValueAttribute(callback)
265-
cluster.subscribeMeasuredValueAttribute(object : ChipClusters.DefaultClusterCallback {
266-
override fun onSuccess() = Unit
267-
override fun onError(ex: Exception) {
268-
callback.onError(ex)
269-
}
270-
}, MIN_REFRESH_PERIOD_S, MAX_REFRESH_PERIOD_S)
260+
cluster.subscribeMeasuredValueAttribute(callback,
261+
MIN_REFRESH_PERIOD_S,
262+
MAX_REFRESH_PERIOD_S)
271263
},
272264
"unitValue" to 1.0,
273265
"unitSymbol" to "hPa"
@@ -279,13 +271,9 @@ class SensorClientFragment : Fragment() {
279271
},
280272
"subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
281273
val cluster = ChipClusters.RelativeHumidityMeasurementCluster(device, endpointId)
282-
cluster.reportMeasuredValueAttribute(callback)
283-
cluster.subscribeMeasuredValueAttribute(object : ChipClusters.DefaultClusterCallback {
284-
override fun onSuccess() = Unit
285-
override fun onError(ex: Exception) {
286-
callback.onError(ex)
287-
}
288-
}, MIN_REFRESH_PERIOD_S, MAX_REFRESH_PERIOD_S)
274+
cluster.subscribeMeasuredValueAttribute(callback,
275+
MIN_REFRESH_PERIOD_S,
276+
MAX_REFRESH_PERIOD_S)
289277
},
290278
"unitValue" to 0.01,
291279
"unitSymbol" to "%"

src/controller/java/templates/CHIPClusters-JNI.zapt

+16-19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <zap-generated/CHIPClusters.h>
99
#include <zap-generated/CHIPClientCallbacks.h>
1010

11+
#include <controller/java/AndroidCallbacks.h>
1112
#include <controller/java/AndroidClusterExceptions.h>
1213
#include <controller/java/CHIPDefaultCallbacks.h>
1314
#include <lib/support/JniReferences.h>
@@ -125,38 +126,34 @@ JNI_METHOD(void, {{asUpperCamelCase ../name}}Cluster, write{{asUpperCamelCase na
125126
JNI_METHOD(void, {{asCamelCased ../name false}}Cluster, subscribe{{asCamelCased name false}}Attribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
126127
{
127128
chip::DeviceLayer::StackLock lock;
128-
std::unique_ptr<CHIPDefaultSuccessCallback, void (*)(CHIPDefaultSuccessCallback *)> onSuccess(Platform::New<CHIPDefaultSuccessCallback>(callback), Platform::Delete<CHIPDefaultSuccessCallback>);
129+
{{~#*inline "callbackName"~}}
130+
{{~#if_in_global_responses~}}
131+
CHIP{{chipCallback.name}}AttributeCallback
132+
{{~else~}}
133+
CHIP{{asCamelCased parent.name false}}{{asCamelCased name false}}AttributeCallback
134+
{{~/if_in_global_responses~}}
135+
{{~/inline}}
136+
137+
std::unique_ptr<{{>callbackName}}, void (*)({{>callbackName}} *)> onSuccess(Platform::New<{{>callbackName}}>(callback, true), chip::Platform::Delete<{{>callbackName}}>);
129138
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));
130139

131-
std::unique_ptr<CHIPDefaultFailureCallback, void (*)(CHIPDefaultFailureCallback *)> onFailure(Platform::New<CHIPDefaultFailureCallback>(callback), Platform::Delete<CHIPDefaultFailureCallback>);
140+
std::unique_ptr<CHIPDefaultFailureCallback, void (*)(CHIPDefaultFailureCallback *)> onFailure(Platform::New<CHIPDefaultFailureCallback>(callback), chip::Platform::Delete<CHIPDefaultFailureCallback>);
132141
VerifyOrReturn(onFailure.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));
133142

134143
CHIP_ERROR err = CHIP_NO_ERROR;
135144
{{asCamelCased ../name false}}Cluster * cppCluster = reinterpret_cast<{{asCamelCased ../name false}}Cluster *>(clusterPtr);
136145
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));
137146

138-
err = cppCluster->SubscribeAttribute{{asCamelCased name false}}(onSuccess->Cancel(), onFailure->Cancel(), static_cast<uint16_t>(minInterval), static_cast<uint16_t>(maxInterval));
147+
using TypeInfo = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::TypeInfo;
148+
auto successFn = chip::Callback::Callback<CHIP{{asUpperCamelCase parent.name}}Cluster{{asUpperCamelCase name}}AttributeCallbackType>::FromCancelable(onSuccess->Cancel());
149+
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
150+
151+
err = cppCluster->SubscribeAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall, static_cast<uint16_t>(minInterval), static_cast<uint16_t>(maxInterval), {{>callbackName}}::OnSubscriptionEstablished);
139152
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error subscribing to attribute", err));
140153

141154
onSuccess.release();
142155
onFailure.release();
143156
}
144-
145-
JNI_METHOD(void, {{asCamelCased ../name false}}Cluster, report{{asCamelCased name false}}Attribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback)
146-
{
147-
chip::DeviceLayer::StackLock lock;
148-
std::unique_ptr<CHIP{{chipCallback.name}}AttributeCallback, void (*)(CHIP{{chipCallback.name}}AttributeCallback *)> onReport(Platform::New<CHIP{{chipCallback.name}}AttributeCallback>(callback, true), Platform::Delete<CHIP{{chipCallback.name}}AttributeCallback>);
149-
VerifyOrReturn(onReport.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native report callback", CHIP_ERROR_NO_MEMORY));
150-
151-
CHIP_ERROR err = CHIP_NO_ERROR;
152-
{{asCamelCased ../name false}}Cluster * cppCluster = reinterpret_cast<{{asCamelCased ../name false}}Cluster *>(clusterPtr);
153-
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));
154-
155-
err = cppCluster->ReportAttribute{{asCamelCased name false}}(onReport->Cancel());
156-
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error registering for attribute reporting", err));
157-
158-
onReport.release();
159-
}
160157
{{/unless}}
161158
{{/if}}
162159
{{/unless}}

src/controller/java/templates/CHIPReadCallbacks-src.zapt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
#include <zap-generated/CHIPClientCallbacks.h>
66

7+
#include <jni.h>
78
#include <lib/support/JniReferences.h>
89
#include <lib/support/JniTypeWrappers.h>
9-
#include <jni.h>
1010
#include <lib/support/CodeUtils.h>
1111
#include <platform/PlatformManager.h>
1212

src/controller/java/templates/CHIPReadCallbacks.zapt

+11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
{{#if (chip_has_client_clusters)}}
33
#include "CHIPCallbackTypes.h"
44

5+
#include <controller/java/AndroidCallbacks.h>
56
#include <jni.h>
7+
#include <lib/support/ErrorStr.h>
8+
#include <lib/support/JniReferences.h>
69
#include <zap-generated/CHIPClientCallbacks.h>
710

811
{{#chip_server_global_responses}}
@@ -21,6 +24,10 @@ public:
2124
}
2225

2326
static void CallbackFn(void * context, {{chipCallback.type}} value);
27+
static void OnSubscriptionEstablished(void * context) {
28+
CHIP_ERROR err = chip::JniReferences::GetInstance().CallSubscriptionEstablished(reinterpret_cast<CHIP{{chipCallback.name}}AttributeCallback *>(context)->javaCallbackRef);
29+
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error calling onSubscriptionEstablished: %s", ErrorStr(err)));
30+
};
2431

2532
private:
2633
jobject javaCallbackRef;
@@ -49,6 +56,10 @@ public:
4956
}
5057

5158
static void CallbackFn(void * context, {{zapTypeToDecodableClusterObjectType type ns=parent.name isArgument=true}} {{#if isList}}list{{else}}value{{/if}});
59+
static void OnSubscriptionEstablished(void * context) {
60+
CHIP_ERROR err = chip::JniReferences::GetInstance().CallSubscriptionEstablished(reinterpret_cast<CHIP{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}AttributeCallback *>(context)->javaCallbackRef);
61+
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error calling onSubscriptionEstablished: %s", ErrorStr(err)));
62+
};
5263

5364
private:
5465
jobject javaCallbackRef;

0 commit comments

Comments
 (0)