Skip to content

Commit

Permalink
Add initial kotlin setuppayload implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
yufengwangca committed May 19, 2023
1 parent 2affb17 commit 9ac113b
Show file tree
Hide file tree
Showing 8 changed files with 614 additions and 2 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:setup_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/SetupPayload.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

34 changes: 34 additions & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,40 @@ kotlin_library("json_to_tlv_to_json_test") {
kotlinc_flags = [ "-Xlint:deprecation" ]
}

shared_library("jni_for_setup_payload") {
output_name = "libSetupPayloadParser"
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 = [ "SetupPayloadParser-JNI.cpp" ]

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

kotlin_library("setup_payload") {
output_name = "SetupPayload.jar"

data_deps = [ ":jni_for_setup_payload" ]

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

sources = [
"src/chip/setuppayload/DiscoveryCapability.kt",
"src/chip/setuppayload/OptionalQRCodeInfo.kt",
"src/chip/setuppayload/SetupPayload.kt",
"src/chip/setuppayload/SetupPayloadParser.kt",
]
}

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

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

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/controller/java/src/chip/setuppayload/DiscoveryCapability.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package chip.setuppayload

/**
* Enum values for possible bits in the onboarding paylod's discovery capabilities bitmask.
*/
enum class DiscoveryCapability {
SOFT_AP,
BLE,
ON_NETWORK
}
17 changes: 17 additions & 0 deletions src/controller/java/src/chip/setuppayload/OptionalQRCodeInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package chip.setuppayload

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
}
67 changes: 67 additions & 0 deletions src/controller/java/src/chip/setuppayload/SetupPayload.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package chip.setuppayload

/** Class to hold the data from the scanned QR code or manual entry code. */
class SetupPayload(
/** Version info of the SetupPayload: 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
}
}
108 changes: 108 additions & 0 deletions src/controller/java/src/chip/setuppayload/SetupPayloadParser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package chip.setuppayload

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

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

/**
* Returns [SetupPayload] parsed from the QR code string.
*
* @param qrCodeString the QRCode for commissioning device.
* @param allowInvalidPayload Allow invalid payload components. 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 [SetupPayload] for the description of the
* invalid element.
*/
@Throws(UnrecognizedQrCodeException::class, SetupPayloadException::class)
fun parseQrCode(qrCodeString: String, allowInvalidPayload: Boolean): SetupPayload {
return fetchPayloadFromQrCode(qrCodeString, allowInvalidPayload)
}

/**
* Returns [SetupPayload] parsed from the manual entry code string. If an SetupPINCode has
* invalid value, SetupPayloadException occurs. Refer to [SetupPayload] for the description
* of the invalid element.
*/
@Throws(InvalidEntryCodeFormatException::class, SetupPayloadException::class)
fun parseManualEntryCode(entryCodeString: String): SetupPayload {
return fetchPayloadFromManualEntryCode(entryCodeString, false)
}

/**
* Returns [SetupPayload] parsed from the manual entry code string.
*
* @param entryCodeString the manual Pairing Code for commissioning device.
* @param allowInvalidPayload Allow invalid payload components. 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 [SetupPayload] for the description of the
* invalid element.
*/
@Throws(InvalidEntryCodeFormatException::class, SetupPayloadException::class)
fun parseManualEntryCode(entryCodeString: String, allowInvalidPayload: Boolean): SetupPayload {
return fetchPayloadFromManualEntryCode(entryCodeString, allowInvalidPayload)
}

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

/** Get manual entry code string from [SetupPayload]. */
@Throws(SetupPayloadException::class)
external fun getManualEntryCodeFromPayload(payload: SetupPayload): String?

@Throws(UnrecognizedQrCodeException::class, SetupPayloadException::class)
private external fun fetchPayloadFromQrCode(
qrCodeString: String, isAllowInvalidPayload: Boolean
): SetupPayload

@Throws(InvalidEntryCodeFormatException::class, SetupPayloadException::class)
private external fun fetchPayloadFromManualEntryCode(
entryCodeString: String, isAllowInvalidPayload: Boolean
): SetupPayload

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

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

class SetupPayloadException(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(SetupPayloadParser::class.java.getSimpleName())

init {
try {
System.loadLibrary("SetupPayloadParser")
} catch (e: UnsatisfiedLinkError) {
LOGGER.log(Level.SEVERE, "Cannot load library.", e)
}
}
}
}

0 comments on commit 9ac113b

Please sign in to comment.