google-home / sample-apps-for-matter-android

The Google Home Sample App for Matter (GHSA for Matter) uses the Home Mobile SDK to create an Android app that's similar to Google Home.
Apache License 2.0
107 stars 38 forks source link

Kotlin templates for CHIP commands, ClusterHelper #159

Open jonsmirl opened 1 year ago

jonsmirl commented 1 year ago

It should be possible in Kotlin to template all of this and just pass in the command: getAdministratorCommissioningClusterForDevice. From the command the template should be able to extract the parent class and the parameters. I'm sure a Google Kotlin expert can write this even more efficiently that I can think of. Then you'd just list the commands you need and the templates would expand everything.

/** Singleton to facilitate access to Clusters functionality. */
@Singleton
class ClustersHelper @Inject constructor(private val chipClient: ChipClient) {

    // -----------------------------------------------------------------------------------------------
    // Administrator Commissioning Cluster (11.19)

    suspend fun openCommissioningWindowAdministratorCommissioningCluster(
        deviceId: Long,
        endpoint: Int,
        timeoutSeconds: Int,
        pakeVerifier: ByteArray,
        discriminator: Int,
        iterations: Long,
        salt: ByteArray,
        timedInvokeTimeoutMs: Int
    ) {
        Timber.d("openCommissioningWindowAdministratorCommissioningCluster())")
        val connectedDevicePtr =
            try {
                chipClient.getConnectedDevicePointer(deviceId)
            } catch (e: IllegalStateException) {
                Timber.e(e, "Can't get connectedDevicePointer.")
                return
            }

        /*
        ChipClusters.DefaultClusterCallback var1, Integer var2, byte[] var3, Integer var4, Long var5, byte[] var6, int var7
         */
        return suspendCoroutine { continuation ->
            getAdministratorCommissioningClusterForDevice(connectedDevicePtr, endpoint)
                .openCommissioningWindow(
                    object : ChipClusters.DefaultClusterCallback {
                        override fun onSuccess() {
                            continuation.resume(Unit)
                        }

                        override fun onError(ex: java.lang.Exception?) {
                            Timber.e(
                                ex,
                                "getAdministratorCommissioningClusterForDevice.openCommissioningWindow command failure"
                            )
                            continuation.resumeWithException(ex!!)
                        }
                    },
                    timeoutSeconds,
                    pakeVerifier,
                    discriminator,
                    iterations,
                    salt,
                    timedInvokeTimeoutMs
                )
        }
    }

    private fun getAdministratorCommissioningClusterForDevice(
        devicePtr: Long,
        endpoint: Int
    ): ChipClusters.AdministratorCommissioningCluster {
        return ChipClusters.AdministratorCommissioningCluster(devicePtr, endpoint)
    }
}
jonsmirl commented 1 year ago

Does this work? It is from the Kotlin documentation.

inline suspend fun <T> vx(crossinline callback: (Handler<AsyncResult<T>>) -> Unit) = 
    suspendCoroutine<T> { cont ->
        callback(Handler { result: AsyncResult<T> ->
            if (result.succeeded()) {
                cont.resume(result.result())
            } else {
                cont.resumeWithException(result.cause())
            }
        })
    }

Using this helper function, an arbitrary asynchronous vert.x function async.foo(params, handler) can be invoked from a coroutine with vx { async.foo(params, it) }.