Skip to content

Commit

Permalink
Add initial kotlin setuppayload implementation (#26676)
Browse files Browse the repository at this point in the history
* Add initial kotlin setuppayload implementation

* Address review comments
  • Loading branch information
yufengwangca authored and pull[bot] committed Jan 19, 2024
1 parent 5ce7a3c commit 3471109
Show file tree
Hide file tree
Showing 8 changed files with 614 additions and 3 deletions.
2 changes: 1 addition & 1 deletion examples/java-matter-controller/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ java_library("java") {
output_name = "JavaMatterController.jar"
deps = [
"${chip_root}/src/controller/java",
"${chip_root}/src/setup_payload/java",
"${chip_root}/third_party/java_deps:annotation",
]

Expand All @@ -39,6 +38,7 @@ kotlin_binary("java-matter-controller") {
deps = [
":java",
"${chip_root}/src/controller/java:json_to_tlv_to_json_test",
"${chip_root}/src/controller/java:onboarding_payload",
"${chip_root}/src/controller/java:tlv_read_write_test",
"${chip_root}/src/controller/java:tlv_reader_test",
"${chip_root}/src/controller/java:tlv_writer_test",
Expand Down
2 changes: 1 addition & 1 deletion examples/java-matter-controller/Manifest.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Main-Class: com.matter.controller.MainKt
Class-Path: ../lib/third_party/connectedhomeip/src/controller/java/CHIPController.jar ../lib/third_party/connectedhomeip/src/setup_payload/java/SetupPayloadParser.jar ../lib/third_party/connectedhomeip/third_party/java_deps/stub_src/Android.jar ../lib/third_party/connectedhomeip/third_party/java_deps/json-20220924.jar ../lib/third_party/connectedhomeip/third_party/java_deps/jsr305-3.0.2.jar ../lib/third_party/connectedhomeip/third_party/java_deps/kotlin-stdlib-1.8.10.jar
Class-Path: ../lib/third_party/connectedhomeip/src/controller/java/CHIPController.jar ../lib/third_party/connectedhomeip/src/setup_payload/java/OnboardingPayload.jar ../lib/third_party/connectedhomeip/third_party/java_deps/stub_src/Android.jar ../lib/third_party/connectedhomeip/third_party/java_deps/json-20220924.jar ../lib/third_party/connectedhomeip/third_party/java_deps/jsr305-3.0.2.jar ../lib/third_party/connectedhomeip/third_party/java_deps/kotlin-stdlib-1.8.10.jar

35 changes: 34 additions & 1 deletion src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ kotlin_library("json_to_tlv_to_json_test") {

deps = [
":jsontlv",
":tlv",
"${chip_root}/third_party/java_deps:gson",
"${chip_root}/third_party/java_deps:junit-4",
"${chip_root}/third_party/java_deps:kotlin-test",
Expand All @@ -237,6 +236,40 @@ kotlin_library("json_to_tlv_to_json_test") {
kotlinc_flags = [ "-Xlint:deprecation" ]
}

shared_library("jni_for_onboarding_payload") {
output_name = "libOnboardingPayload"
if (build_java_matter_controller) {
include_dirs = java_matter_controller_dependent_paths
output_dir = "${root_out_dir}/lib/jni"
} else {
output_dir = "${root_out_dir}/lib/jni/${android_abi}"
}

sources = [ "OnboardingPayloadParser-JNI.cpp" ]

deps = [
"${chip_root}/src/lib",
"${chip_root}/src/setup_payload",
]
}

kotlin_library("onboarding_payload") {
output_name = "OnboardingPayload.jar"

data_deps = [ ":jni_for_onboarding_payload" ]

if (!build_java_matter_controller) {
data_deps += [ "${chip_root}/build/chip/java:shared_cpplib" ]
}

sources = [
"src/chip/onboardingpayload/DiscoveryCapability.kt",
"src/chip/onboardingpayload/OnboardingPayload.kt",
"src/chip/onboardingpayload/OnboardingPayloadParser.kt",
"src/chip/onboardingpayload/OptionalQRCodeInfo.kt",
]
}

android_library("java") {
output_name = "CHIPController.jar"

Expand Down
378 changes: 378 additions & 0 deletions src/controller/java/OnboardingPayloadParser-JNI.cpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package chip.onboardingpayload

/**
* Enum values for possible bits in the onboarding paylod's discovery capabilities bitmask.
*/
enum class DiscoveryCapability {
SOFT_AP,
BLE,
ON_NETWORK
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package chip.onboardingpayload

/** Class to hold the data from the scanned QR code or Manual Pairing Code. */
class OnboardingPayload(
/** Version info of the OnboardingPayload: version SHALL be 0 */
var version: Int = 0,

/** The CHIP device vendor ID: Vendor ID SHALL be between 1 and 0xFFF4. */
var vendorId: Int = 0,

/** The CHIP device product ID: Product ID SHALL BE greater than 0. */
var productId: Int = 0,

/** Commissioning flow: 0 = standard, 1 = requires user action, 2 = custom */
var commissioningFlow: Int = 0,

/**
* The CHIP device supported rendezvous flags: At least one DiscoveryCapability must be included.
*/
var discoveryCapabilities: Set<DiscoveryCapability> = emptySet(),

/** The CHIP device discriminator: */
var discriminator: Int = 0,

/**
* If hasShortDiscriminator is true, the discriminator value contains just the high 4 bits of the
* full discriminator. For example, if hasShortDiscriminator is true and discriminator is 0xA,
* then the full discriminator can be anything in the range 0xA00 to 0xAFF.
*/
var hasShortDiscriminator: Boolean = false,

/**
* The CHIP device setup PIN code: setupPINCode SHALL be greater than 0. Also invalid setupPINCode
* is {000000000, 11111111, 22222222, 33333333, 44444444, 55555555, 66666666, 77777777, 88888888,
* 99999999, 12345678, 87654321}.
*/
var setupPinCode: Long = 0
) {
var optionalQRCodeInfo: HashMap<Int, OptionalQRCodeInfo>

init {
optionalQRCodeInfo = HashMap()
}

constructor(
version: Int,
vendorId: Int,
productId: Int,
commissioningFlow: Int,
discoveryCapabilities: Set<DiscoveryCapability>,
discriminator: Int,
setupPinCode: Long
) : this(
version,
vendorId,
productId,
commissioningFlow,
discoveryCapabilities,
discriminator,
false,
setupPinCode
)

fun addOptionalQRCodeInfo(info: OptionalQRCodeInfo) {
optionalQRCodeInfo[info.tag] = info
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package chip.onboardingpayload

import java.util.logging.Level
import java.util.logging.Logger

/** Parser for scanned QR code or Manual Pairing Code. */
class OnboardingPayloadParser {
/**
* Returns [OnboardingPayload] parsed from the QR code string. If an invalid element is included
* in the QRCode Parse result, OnboardingPayloadException occurs. Refer to [OnboardingPayload] for the
* description of the invalid element.
*/
@Throws(UnrecognizedQrCodeException::class, OnboardingPayloadException::class)
fun parseQrCode(qrCodeString: String): OnboardingPayload {
return fetchPayloadFromQrCode(qrCodeString, false)
}

/**
* Returns [OnboardingPayload] parsed from the QR code string.
*
* @param qrCodeString the QRCode for commissioning device.
* @param skipPayloadValidation If this value is true, payload element validation is not checked.
* Consider saying that the payload must still parse correctly, but this skips validation of the
* content past parsing (i.e. it does not validate ranges for individual elements).
* Refer to [OnboardingPayload] for the description of the invalid element.
*/
@Throws(UnrecognizedQrCodeException::class, OnboardingPayloadException::class)
fun parseQrCode(qrCodeString: String, skipPayloadValidation: Boolean): OnboardingPayload {
return fetchPayloadFromQrCode(qrCodeString, skipPayloadValidation)
}

/**
* Returns [OnboardingPayload] parsed from the Manual Pairing Code string. If an SetupPINCode has
* invalid value, OnboardingPayloadException occurs. Refer to [OnboardingPayload] for the description
* of the invalid element.
*/
@Throws(InvalidManualPairingCodeFormatException::class, OnboardingPayloadException::class)
fun parseManualPairingCode(manualPairingCodeString: String): OnboardingPayload {
return parsePayloadFromManualPairingCode(manualPairingCodeString, false)
}

/**
* Returns [OnboardingPayload] parsed from the Manual Pairing Code string.
*
* @param manualPairingCodeString the manual Pairing Code for commissioning device.
* @param skipPayloadValidation If this value is true, payload element validation is not checked.
* Consider saying that the payload must still parse correctly, but this skips validation of the
* content past parsing (i.e. it does not validate ranges for individual elements).
* Refer to [OnboardingPayload] for the description of the invalid element.
*/
@Throws(InvalidManualPairingCodeFormatException::class, OnboardingPayloadException::class)
fun parseManualPairingCode(manualPairingCodeString: String, skipPayloadValidation: Boolean): OnboardingPayload {
return parsePayloadFromManualPairingCode(manualPairingCodeString, skipPayloadValidation)
}

/** Get QR code string from [OnboardingPayload]. */
@Throws(OnboardingPayloadException::class)
external fun getQrCodeFromPayload(payload: OnboardingPayload): String?

/** Get Manual Pairing Code string from [OnboardingPayload]. */
@Throws(OnboardingPayloadException::class)
external fun getManualPairingCodeFromPayload(payload: OnboardingPayload): String?

@Throws(UnrecognizedQrCodeException::class, OnboardingPayloadException::class)
private external fun fetchPayloadFromQrCode(
qrCodeString: String, skipPayloadValidation: Boolean
): OnboardingPayload

@Throws(InvalidManualPairingCodeFormatException::class, OnboardingPayloadException::class)
private external fun parsePayloadFromManualPairingCode(
manualPairingCodeString: String, skipPayloadValidation: Boolean
): OnboardingPayload

class UnrecognizedQrCodeException(qrCode: String) :
Exception(String.format("Invalid QR code string: %s", qrCode), null) {
companion object {
private const val serialVersionUID = 1L
}
}

class InvalidManualPairingCodeFormatException(manualPairingCode: String) :
Exception(String.format("Invalid format for manual pairing code string: %s", manualPairingCode), null) {
companion object {
private const val serialVersionUID = 1L
}
}

class OnboardingPayloadException(var errorCode: Int, message: String?) :
Exception(message ?: String.format("Error Code %d", errorCode)) {
companion object {
private const val serialVersionUID = 1L
}
}

companion object {
private val LOGGER: Logger = Logger.getLogger(OnboardingPayloadParser::class.java.getSimpleName())

init {
try {
System.loadLibrary("OnboardingPayload")
} catch (e: UnsatisfiedLinkError) {
LOGGER.log(Level.SEVERE, "Cannot load library.", e)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package chip.onboardingpayload

class OptionalQRCodeInfo {
enum class OptionalQRCodeInfoType {
TYPE_UNKNOWN,
TYPE_STRING,
TYPE_INT32,
TYPE_INT64,
TYPE_UINT32,
TYPE_UINT64
}

var tag = 0
var type: OptionalQRCodeInfoType? = null
var data: String? = null
var int32 = 0
}

0 comments on commit 3471109

Please sign in to comment.