Skip to content

Commit

Permalink
[Android]add json support for invoke and write using latest json/tlv …
Browse files Browse the repository at this point in the history
…conversion
  • Loading branch information
yunhanw-google committed Aug 18, 2023
1 parent a167c71 commit 642f8c3
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import chip.devicecontroller.model.InvokeElement
import chip.tlv.AnonymousTag
import chip.tlv.ContextSpecificTag
import chip.tlv.TlvWriter
import chip.tlv.TlvReader
import com.matter.controller.commands.common.CredentialsIssuer
import java.util.logging.Level
import java.util.logging.Logger
Expand All @@ -50,16 +51,29 @@ class PairOnNetworkLongImInvokeCommand(
private inner class InternalInvokeCallback : InvokeCallback {
override fun onError(e: Exception) {
logger.log(Level.INFO, "Invoke receive onError" + e.message)
setFailure("write failure")
setFailure("invoke failure")
}

override fun onResponse(element: InvokeElement?, successCode: Long) {
logger.log(Level.INFO, "Invoke receive OnResponse on ")
if (element != null) {
logger.log(Level.INFO, element.toString())
logger.log(Level.INFO, element.toString() + element.getJsonString())
val clusterId = element.getClusterId().getId()
if (clusterId == CLUSTER_ID_IDENTIFY)
{
logger.log(Level.INFO, "success code is $successCode")
setSuccess()
return
}
else if (clusterId == CLUSTER_ID_TEST && element.getJsonString().equals("""{"0:UINT":2}"""))
{
logger.log(Level.INFO, "success code is $successCode")
setSuccess()
return
}
}
logger.log(Level.INFO, "success code is$successCode")
setSuccess()

setFailure("invoke failure")
}
}

Expand All @@ -76,20 +90,44 @@ class PairOnNetworkLongImInvokeCommand(

override fun runCommand() {
val number: UShort = 1u
val tlvWriter = TlvWriter()
tlvWriter.startStructure(AnonymousTag)
tlvWriter.put(ContextSpecificTag(0), number)
tlvWriter.endStructure()
val tlvWriter1 = TlvWriter()
tlvWriter1.startStructure(AnonymousTag)
tlvWriter1.put(ContextSpecificTag(0), number)
tlvWriter1.endStructure()

val element: InvokeElement =
val element1: InvokeElement =
InvokeElement.newInstance(
/* endpointId= */ 0,
CLUSTER_ID_IDENTIFY,
IDENTIFY_COMMAND,
tlvWriter.getEncoded(),
tlvWriter1.getEncoded(),
null
)

val tlvWriter2 = TlvWriter()
tlvWriter2.startStructure(AnonymousTag)
tlvWriter2.put(ContextSpecificTag(0), number)
tlvWriter2.put(ContextSpecificTag(1), number)
tlvWriter2.endStructure()

val element2: InvokeElement =
InvokeElement.newInstance(
/* endpointId= */ 1,
CLUSTER_ID_TEST,
TEST_ADD_ARGUMENT_COMMAND,
tlvWriter2.getEncoded(),
null
)

val element3: InvokeElement =
InvokeElement.newInstance(
/* endpointId= */ 1,
CLUSTER_ID_IDENTIFY,
IDENTIFY_COMMAND,
null,
"""{"0:UINT":1}"""
)

currentCommissioner()
.pairDeviceWithAddress(
getNodeId(),
Expand All @@ -104,7 +142,13 @@ class PairOnNetworkLongImInvokeCommand(
currentCommissioner()
.getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback())
clear()
currentCommissioner().invoke(InternalInvokeCallback(), devicePointer, element, 0, 0)
currentCommissioner().invoke(InternalInvokeCallback(), devicePointer, element1, 0, 0)
waitCompleteMs(getTimeoutMillis())
clear()
currentCommissioner().invoke(InternalInvokeCallback(), devicePointer, element2, 0, 0)
waitCompleteMs(getTimeoutMillis())
clear()
currentCommissioner().invoke(InternalInvokeCallback(), devicePointer, element3, 0, 0)
waitCompleteMs(getTimeoutMillis())
}

Expand All @@ -114,5 +158,7 @@ class PairOnNetworkLongImInvokeCommand(
private const val MATTER_PORT = 5540
private const val CLUSTER_ID_IDENTIFY = 0x0003L
private const val IDENTIFY_COMMAND = 0L
private const val CLUSTER_ID_TEST = 0xFFF1FC05L
private const val TEST_ADD_ARGUMENT_COMMAND = 0X04L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class PairOnNetworkLongImWriteCommand(
}

override fun onResponse(attributePath: ChipAttributePath?) {
logger.log(Level.INFO, "Write receve OnResponse on ")
logger.log(Level.INFO, "Write receive OnResponse on ")
if (attributePath != null) {
logger.log(Level.INFO, attributePath.toString())
}
Expand All @@ -72,18 +72,28 @@ class PairOnNetworkLongImWriteCommand(
}

override fun runCommand() {
val tlvWriter = TlvWriter()
tlvWriter.put(AnonymousTag, true)
val attributeList =
val tlvWriter1 = TlvWriter()
tlvWriter1.put(AnonymousTag, true)
val attributeList1 =
listOf(
AttributeWriteRequest.newInstance(
/* endpointId= */ 0,
CLUSTER_ID_BASIC,
ATTR_ID_LOCAL_CONFIG_DISABLED,
tlvWriter.getEncoded(),
tlvWriter1.getEncoded()
)
)

val attributeList2 =
listOf(
AttributeWriteRequest.newInstance(
/* endpointId= */ 0,
CLUSTER_ID_BASIC,
ATTR_ID_LOCAL_CONFIG_DISABLED,
"""{"40:BOOL":false}"""
)
)

currentCommissioner()
.pairDeviceWithAddress(
getNodeId(),
Expand All @@ -99,7 +109,11 @@ class PairOnNetworkLongImWriteCommand(
.getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback())
clear()
currentCommissioner()
.write(InternalWriteAttributesCallback(), devicePointer, attributeList, 0, 0)
.write(InternalWriteAttributesCallback(), devicePointer, attributeList1, 0, 0)
waitCompleteMs(getTimeoutMillis())
clear()
currentCommissioner()
.write(InternalWriteAttributesCallback(), devicePointer, attributeList2, 0, 0)
waitCompleteMs(getTimeoutMillis())
}

Expand Down
80 changes: 50 additions & 30 deletions src/controller/java/AndroidCallbacks.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2020-2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,7 +28,8 @@
#include <lib/support/ErrorStr.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>
#include <lib/support/jsontlv/TlvJson.h>
#include <lib/support/jsontlv/JsonToTlv.h>
#include <lib/support/jsontlv/TlvToJson.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/PlatformManager.h>
#include <type_traits>
Expand Down Expand Up @@ -249,11 +250,6 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat
return;
}

TLV::TLVReader readerForJavaTLV;
TLV::TLVReader readerForJson;
readerForJavaTLV.Init(*apData);
readerForJson.Init(*apData);

jobject value = nullptr;
#if USE_JAVA_TLV_ENCODE_DECODE
TLV::TLVReader readerForJavaObject;
Expand All @@ -271,25 +267,40 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat
ReportError(attributePathObj, nullptr, CHIP_JNI_ERROR_EXCEPTION_THROWN));
#endif
// Create TLV byte array to pass to Java layer
TLV::TLVReader readerForJavaTLV;
readerForJavaTLV.Init(*apData);
size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
uint32_t size = 0;
// The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
// a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
// at the end.)

TLV::TLVWriter writer;
writer.Init(buffer.get(), bufferLen);
err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
TLV::TLVType outer;

err = writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err));
TLV::Tag tag;
err = ConvertTlvTag(aPath.mAttributeId, tag);

VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err));
err = writer.CopyElement(tag, readerForJavaTLV);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err));
err = writer.EndContainer(outer);

VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, attributePathObj, err));
size = writer.GetLengthWritten();
chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), size);

TLV::TLVReader readerForJson;
readerForJson.Init(buffer.get(), size);
err = readerForJson.Next();
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, attributePathObj, err));
// Convert TLV to JSON
Json::Value json;
std::string json;
err = TlvToJson(readerForJson, json);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err));

UtfString jsonString(env, JsonToString(json).c_str());
UtfString jsonString(env, json.c_str());

// Create AttributeState object
jclass attributeStateCls;
Expand Down Expand Up @@ -363,11 +374,6 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV
return;
}

TLV::TLVReader readerForJavaTLV;
TLV::TLVReader readerForJson;
readerForJavaTLV.Init(*apData);
readerForJson.Init(*apData);

jlong eventNumber = static_cast<jlong>(aEventHeader.mEventNumber);
jint priorityLevel = static_cast<jint>(aEventHeader.mPriorityLevel);
jlong timestampValue = static_cast<jlong>(aEventHeader.mTimestamp.mValue);
Expand Down Expand Up @@ -404,6 +410,8 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV
#endif

// Create TLV byte array to pass to Java layer
TLV::TLVReader readerForJavaTLV;
readerForJavaTLV.Init(*apData);
size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
uint32_t size = 0;
Expand All @@ -412,17 +420,29 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV
// at the end.)
TLV::TLVWriter writer;
writer.Init(buffer.get(), bufferLen);
err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
TLV::TLVType outer;
err = writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));
TLV::Tag tag;
err = ConvertTlvTag(aEventHeader.mPath.mEventId, tag);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));
err = writer.CopyElement(tag, readerForJavaTLV);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));
err = writer.EndContainer(outer);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));
size = writer.GetLengthWritten();
chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), size);

// Convert TLV to JSON
Json::Value json;
std::string json;
TLV::TLVReader readerForJson;
readerForJson.Init(buffer.get(), size);
err = readerForJson.Next();
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));
err = TlvToJson(readerForJson, json);
VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err));

UtfString jsonString(env, JsonToString(json).c_str());
UtfString jsonString(env, json.c_str());

// Create EventState object
jclass eventStateCls;
Expand Down Expand Up @@ -488,15 +508,12 @@ CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath &
TLV::TLVReader readerForJavaTLV;
TLV::TLVReader readerForJson;
readerForJavaTLV.Init(*apData);
readerForJson.Init(*apData);

// Create TLV byte array to pass to Java layer
size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
uint32_t size = 0;
// The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
// a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
// at the end.)

TLV::TLVWriter writer;
writer.Init(buffer.get(), bufferLen);
err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
Expand All @@ -505,11 +522,13 @@ CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath &
chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), size);

// Convert TLV to JSON
Json::Value json;
std::string json;
readerForJson.Init(buffer.get(), size);
err = readerForJson.Next();
ReturnErrorOnFailure(err);
err = TlvToJson(readerForJson, json);
ReturnErrorOnFailure(err);

UtfString jsonString(env, JsonToString(json).c_str());
UtfString jsonString(env, json.c_str());
outObj = env->CallStaticObjectMethod(invokeElementCls, invokeElementCtor, static_cast<jint>(aPath.mEndpointId),
static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mCommandId),
jniByteArray.jniValue(), jsonString.jniValue());
Expand Down Expand Up @@ -614,6 +633,7 @@ void ReportCallback::ReportError(jobject attributePath, jobject eventPath, const
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

ChipLogError(Controller, "ReportCallback::ReportError is called with %u", errorCode);
jthrowable exception;
err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
VerifyOrReturn(
Expand Down Expand Up @@ -722,7 +742,7 @@ void WriteAttributesCallback::ReportError(jobject attributePath, const char * me
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

ChipLogError(Controller, "WriteAttributesCallback ReportError is called");
ChipLogError(Controller, "WriteAttributesCallback::ReportError is called with %u", errorCode);
jthrowable exception;
err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
VerifyOrReturn(err == CHIP_NO_ERROR,
Expand Down Expand Up @@ -825,7 +845,7 @@ void InvokeCallback::ReportError(const char * message, ChipError::StorageType er
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();

ChipLogError(Controller, "InvokeCallback ReportError is called");
ChipLogError(Controller, "InvokeCallback::ReportError is called with %u", errorCode);
jthrowable exception;
err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
VerifyOrReturn(
Expand Down
Loading

0 comments on commit 642f8c3

Please sign in to comment.