Skip to content

Commit

Permalink
[Android]Initial implementation of Kotlin Matter Controller (#29574)
Browse files Browse the repository at this point in the history
* Initial implemenation of Kotlin Matter Controller

* Rename to KotlinMatterController

* Rename Interactions to InteractionClient

* Address review comments

* Restyled by gn

---------

Co-authored-by: Restyled.io <commits@restyled.io>
  • Loading branch information
2 people authored and pull[bot] committed Feb 13, 2024
1 parent d45dd63 commit 9158833
Show file tree
Hide file tree
Showing 12 changed files with 1,336 additions and 0 deletions.
2 changes: 2 additions & 0 deletions kotlin-detect-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ complexity:
- "**/src/controller/java/src/chip/onboardingpayload/OnboardingPayload.kt"
- "**/src/controller/java/src/chip/tlv/TlvReader.kt"
- "**/src/controller/java/src/chip/tlv/TlvWriter.kt"
- "**/src/controller/java/src/matter/controller/MatterControllerImpl.kt"
- "**/src/controller/java/src/matter/controller/CompletionListenerAdapter.kt"
- "**/src/controller/java/tests/chip/jsontlv/JsonToTlvToJsonTest.kt"
- "**/src/controller/java/tests/chip/onboardingpayload/ManualCodeTest.kt"
- "**/src/controller/java/tests/chip/onboardingpayload/QRCodeTest.kt"
Expand Down
33 changes: 33 additions & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,39 @@ kotlin_library("chipcluster_test") {
kotlinc_flags = [ "-Xlint:deprecation" ]
}

kotlin_library("kotlin_matter_controller") {
output_name = "KotlinMatterController.jar"

deps = [
":java",
"${chip_root}/third_party/java_deps:annotation",
]

sources = [
"src/matter/controller/CompletionListenerAdapter.kt",
"src/matter/controller/ControllerParams.kt",
"src/matter/controller/InteractionClient.kt",
"src/matter/controller/MatterController.kt",
"src/matter/controller/MatterControllerException.kt",
"src/matter/controller/MatterControllerImpl.kt",
"src/matter/controller/Messages.kt",
"src/matter/controller/OperationalKeyConfig.kt",
"src/matter/controller/model/Paths.kt",
"src/matter/controller/model/States.kt",
]

if (matter_enable_java_compilation) {
deps += [
"${chip_root}/third_party/java_deps:json",
"${chip_root}/third_party/java_deps:kotlin-stdlib",
"${chip_root}/third_party/java_deps:kotlinx-coroutines-core-jvm",
"${chip_root}/third_party/java_deps/stub_src",
]
} else {
deps += [ ":android" ]
}
}

group("unit_tests") {
deps = [
":chipcluster_test",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package matter.controller

import chip.devicecontroller.ChipDeviceController
import java.util.logging.Level
import java.util.logging.Logger

class CompletionListenerAdapter(val listener: MatterController.CompletionListener) :
chip.devicecontroller.ChipDeviceController.CompletionListener {

override fun onConnectDeviceComplete() = listener.onConnectDeviceComplete()

override fun onStatusUpdate(status: Int) = listener.onStatusUpdate(status)

override fun onPairingComplete(errorCode: Int) = listener.onPairingComplete(errorCode)

override fun onPairingDeleted(errorCode: Int) = listener.onPairingDeleted(errorCode)

override fun onNotifyChipConnectionClosed() = listener.onNotifyChipConnectionClosed()

override fun onCommissioningComplete(nodeId: Long, errorCode: Int) =
listener.onCommissioningComplete(nodeId, errorCode)

override fun onCommissioningStatusUpdate(nodeId: Long, stage: String?, errorCode: Int) =
listener.onCommissioningStatusUpdate(nodeId, stage, errorCode)

override fun onReadCommissioningInfo(
vendorId: Int,
productId: Int,
wifiEndpointId: Int,
threadEndpointId: Int
) = listener.onReadCommissioningInfo(vendorId, productId, wifiEndpointId, threadEndpointId)

override fun onOpCSRGenerationComplete(csr: ByteArray) = listener.onOpCSRGenerationComplete(csr)

override fun onError(error: Throwable) = listener.onError(error)

override fun onCloseBleComplete() {
logger.log(Level.INFO, "Not implemented, override the abstract function.")
}

companion object {
private val logger = Logger.getLogger(MatterController::class.java.simpleName)

fun from(
listener: MatterController.CompletionListener?
): chip.devicecontroller.ChipDeviceController.CompletionListener? {
if (listener == null) {
return null
}
return CompletionListenerAdapter(listener)
}
}
}
42 changes: 42 additions & 0 deletions src/controller/java/src/matter/controller/ControllerParams.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package matter.controller

/**
* Parameters representing initialization arguments for [MatterController].
*
* @param operationalKeyConfig An optional signing configuration for operational control of devices.
* @param udpListenPort A port for UDP communications, or [UDP_PORT_AUTO] to select automatically.
* @param vendorId The identifier for the vendor using this controller.
* @param countryCode The Regulatory Location country code.
*/
class ControllerParams
@JvmOverloads
constructor(
val operationalKeyConfig: OperationalKeyConfig? = null,
val udpListenPort: Int = UDP_PORT_AUTO,
val vendorId: Int = VENDOR_ID_TEST,
val countryCode: String? = null,
) {
companion object {
/** Matter assigned vendor ID for Google. */
const val VENDOR_ID_TEST = 0xFFF1
/** Indicates that the UDP listen port should be chosen automatically. */
const val UDP_PORT_AUTO = 0
}
}
59 changes: 59 additions & 0 deletions src/controller/java/src/matter/controller/InteractionClient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package matter.controller

import kotlinx.coroutines.flow.Flow

interface InteractionClient {
/**
* Subscribes to periodic updates of all attributes and events from a device.
*
* @param request The Subscribe command's path and arguments.
* @return A Flow of SubscriptionState representing the subscription's state updates.
*/
fun subscribe(request: SubscribeRequest): Flow<SubscriptionState>

/**
* Issues a read request to a target device for specified attributes and events.
*
* @param request Read command's path and arguments.
* @return A response to the read request.
* @throws Generic Exception if an error occurs during the read operation.
*/
suspend fun read(request: ReadRequest): ReadResponse

/**
* Issues attribute write requests to a target device.
*
* @param writeRequests A list of attribute WriteRequest.
* @return A response to the write request.
* @throws Generic Exception or MatterControllerException if an error occurs during the write
* operation.
*/
suspend fun write(writeRequests: WriteRequests): WriteResponse

/**
* Invokes a command on a target device.
*
* @param request Invoke command's path and arguments.
* @return A response to the invoke request.
* @throws Generic Exception or MatterControllerException if an error occurs during the invoke
* operation.
*/
suspend fun invoke(request: InvokeRequest): InvokeResponse
}
107 changes: 107 additions & 0 deletions src/controller/java/src/matter/controller/MatterController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package matter.controller

import java.io.Closeable

/** Controller interface for interacting with a CHIP device. */
interface MatterController : Closeable, InteractionClient {
/** Interface for listening to callbacks from the MatterController. */
interface CompletionListener {
/** Notifies the completion of the "ConnectDevice" command. */
fun onConnectDeviceComplete()

/** Notifies the pairing status. */
fun onStatusUpdate(status: Int)

/** Notifies the completion of pairing. */
fun onPairingComplete(errorCode: Int)

/** Notifies the deletion of a pairing session. */
fun onPairingDeleted(errorCode: Int)

/** Notifies that the CHIP connection has been closed. */
fun onNotifyChipConnectionClosed()

/** Notifies the completion of commissioning. */
fun onCommissioningComplete(nodeId: Long, errorCode: Int)

/** Notifies the completion of reading commissioning information. */
fun onReadCommissioningInfo(
vendorId: Int,
productId: Int,
wifiEndpointId: Int,
threadEndpointId: Int
)

/** Notifies the completion of each stage of commissioning. */
fun onCommissioningStatusUpdate(nodeId: Long, stage: String?, errorCode: Int)

/** Notifies the listener of an error. */
fun onError(error: Throwable)

/** Notifies the Commissioner when the OpCSR for the Comissionee is generated. */
fun onOpCSRGenerationComplete(csr: ByteArray)
}

/**
* Sets a completion listener for receiving controller events.
*
* @param listener The listener to set.
*/
fun setCompletionListener(listener: CompletionListener?)

/**
* Commissions a device into a Matter fabric.
*
* @param nodeId The ID of the node to connect to.
* @param address The IP address at which the node is located.
* @param port The port at which the node is located.
* @param discriminator A 12-bit value used to discern between multiple commissionable Matter
* device advertisements.
* @param pinCode The pincode for this node.
*/
fun pairDevice(
nodeId: Long,
address: String,
port: Int,
discriminator: Int,
pinCode: Long,
)

/**
* Removes pairing for a paired device. If the device is currently being paired, it will stop the
* pairing process.
*
* @param nodeId The remote device ID.
*/
fun unpairDevice(nodeId: Long)

/**
* Establishes a secure PASE connection to the given device via IP address.
*
* @param nodeId The ID of the node to connect to.
* @param address The IP address at which the node is located.
* @param port The port at which the node is located.
* @param setupPincode The pincode for this node.
*/
fun establishPaseConnection(nodeId: Long, address: String, port: Int, setupPincode: Long)

/** Closes any active connections through this device controller. */
override fun close()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package matter.controller

class MatterControllerException(errorCode: Long, message: String? = null) :
RuntimeException(message ?: "Error Code $errorCode") {

val errorCode: Long = errorCode
}
Loading

0 comments on commit 9158833

Please sign in to comment.