Skip to content

Commit

Permalink
[YAML] Add _ById commands support for darwin-framework-tool (#35996)
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple authored and pull[bot] committed Nov 29, 2024
1 parent dc5e9ba commit d833656
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class Converter():
def __init__(self, specifications):
self.__specs = specifications
self.__converters = [
DarwinAnyFormatConverter(),
StructFieldsNameConverter(),
FloatConverter(),
OctetStringConverter()
Expand Down Expand Up @@ -252,6 +253,43 @@ def maybe_convert(self, typename: str, value):
return value


class DarwinAnyFormatConverter(BaseConverter):
"""
Darwin payloads format for *ById commands is different from the base
format used for other commands.
"""

def run(self, specs, value, cluster_name: str, typename: str, array: bool):
if isinstance(value, list) and len(value) >= 1 and isinstance(value[0], dict) and value[0].get('data') is not None:
value = [self.__convert(item_value) for item_value in value]
return value

def __convert(self, value):
if not isinstance(value, dict):
return value

data = value.get('data')
if not isinstance(data, dict):
return value

value = data.get('value')
if not isinstance(value, list):
return value

value_type = data.get('type')

if value_type == 'Structure':
struct = {}
for field in value:
context_tag = field.get('contextTag')
struct[str(context_tag)] = self.__convert(field)
value = struct
elif value_type == 'Array':
value = [self.__convert(item_value) for item_value in value]

return value


class FloatConverter(BaseConverter):
"""
Jsoncpp stores floats as double.
Expand Down Expand Up @@ -348,7 +386,7 @@ def run(self, specs, value, cluster_name: str, typename: str, array: bool):
del value[key_name]

elif isinstance(value, list) and array:
value = [self.run(specs, v, cluster_name, typename, False)
value = [self.run(specs, v, cluster_name, typename, isinstance(v, list))
for v in value]

return value
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,16 @@ def __get_alias(self, cluster_name: str, command_name: str = None, argument_name
if aliases is None or aliases.get(argument_name) is None:
return None

return aliases.get(argument_name)
value = aliases.get(argument_name)

if cluster_name == '*' and self.__is_darwin_framework_tool:
if argument_name == 'AttributeId':
return 'attribute-id'
elif argument_name == 'ClusterId':
return 'cluster-id'
elif argument_name == 'Value':
return 'attribute-value'
return value

def _supports_endpoint(self, request):
return self._has_support(request, 'has_endpoint')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ class ClusterCommand : public ModelCommand {
uint16_t __block responsesNeeded = repeatCount;
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);

__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(clusterId);
__auto_type * command = @(commandId);
while (repeatCount--) {
[device invokeCommandWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
clusterID:[NSNumber numberWithUnsignedInteger:clusterId]
commandID:[NSNumber numberWithUnsignedInteger:commandId]
[device invokeCommandWithEndpointID:endpoint
clusterID:cluster
commandID:command
commandFields:commandFields
timedInvokeTimeout:mTimedInteractionTimeoutMs.HasValue()
? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()]
Expand All @@ -88,6 +91,9 @@ class ClusterCommand : public ModelCommand {
if (error != nil) {
mError = error;
LogNSError("Error", error);
RemoteDataModelLogger::LogCommandErrorAsJSON(endpoint, cluster, command, error);
} else {
RemoteDataModelLogger::LogCommandAsJSON(endpoint, cluster, command, values);
}
if (responsesNeeded == 0) {
SetCommandExitStatus(mError);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,26 @@ class ReadAttribute : public ModelCommand {
if (mFabricFiltered.HasValue()) {
params.filterByFabric = mFabricFiltered.Value();
}

__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(mClusterId);
__auto_type * attribute = @(mAttributeId);
[device
readAttributesWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
clusterID:[NSNumber numberWithUnsignedInteger:mClusterId]
attributeID:[NSNumber numberWithUnsignedInteger:mAttributeId]
readAttributesWithEndpointID:endpoint
clusterID:cluster
attributeID:attribute
params:params
queue:callbackQueue
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (error != nil) {
LogNSError("Error reading attribute", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(endpoint, cluster, attribute, error);
}
if (values) {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
RemoteDataModelLogger::LogAttributeAsJSON(endpoint, cluster, attribute, values);
}
SetCommandExitStatus(error);
}];
Expand Down Expand Up @@ -137,16 +143,23 @@ class SubscribeAttribute : public ModelCommand {
params.resubscribeAutomatically = mAutoResubscribe.Value();
}

[device subscribeToAttributesWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
clusterID:[NSNumber numberWithUnsignedInteger:mClusterId]
attributeID:[NSNumber numberWithUnsignedInteger:mAttributeId]
__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(mClusterId);
__auto_type * attribute = @(mAttributeId);
[device subscribeToAttributesWithEndpointID:endpoint
clusterID:cluster
attributeID:attribute
params:params
queue:callbackQueue
reportHandler:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (error != nil) {
RemoteDataModelLogger::LogAttributeErrorAsJSON(endpoint, cluster, attribute, error);
}
if (values) {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
RemoteDataModelLogger::LogAttributeAsJSON(endpoint, cluster, attribute, values);
}
SetCommandExitStatus(error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,13 @@ class WriteAttribute : public ModelCommand {
{
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);

__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(mClusterId);
__auto_type * attribute = @(mAttributeId);
[device
writeAttributeWithEndpointID:[NSNumber numberWithUnsignedShort:endpointId]
clusterID:[NSNumber numberWithUnsignedInteger:clusterId]
attributeID:[NSNumber numberWithUnsignedInteger:attributeId]
writeAttributeWithEndpointID:endpoint
clusterID:cluster
attributeID:attribute
value:value
timedWriteTimeout:mTimedInteractionTimeoutMs.HasValue()
? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()]
Expand All @@ -86,11 +89,13 @@ class WriteAttribute : public ModelCommand {
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (error != nil) {
LogNSError("Error writing attribute", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(endpoint, cluster, attribute, error);
}
if (values) {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
RemoteDataModelLogger::LogAttributeAsJSON(endpoint, cluster, attribute, values);
}
SetCommandExitStatus(error);
}];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

#include <string>

constexpr char kAttributePathKey[] = "attributePath";
constexpr char kCommandPathKey[] = "commandPath";
constexpr char kClusterIdKey[] = "clusterId";
constexpr char kEndpointIdKey[] = "endpointId";
constexpr char kAttributeIdKey[] = "attributeId";
Expand Down Expand Up @@ -142,8 +144,45 @@ CHIP_ERROR LogAttributeAsJSON(NSNumber * endpointId, NSNumber * clusterId, NSNum

Json::Value jsonValue;
VerifyOrDie(CHIP_NO_ERROR == AsJsonValue(result, jsonValue));
value[kValueKey] = jsonValue;

// When using the *-by-id commands, the return format is always encapsulated
// within an array. If the attribute itself is an empty array, the result will
// appear as follows:
//
//[
// {
// attributePath = "<MTRAttributePath endpoint 0 cluster 0x41 (65, UserLabel) 0x0 (0, LabelList)>";
// data = {
// type = Array;
// value = (
// );
// };
// }
//]
bool hasData = false;
if (jsonValue.isArray() && !jsonValue.empty()) {
for (Json::ArrayIndex i = 0; i < jsonValue.size(); i++) {
if (jsonValue[i].isObject()) {
if (jsonValue[i].isMember(kAttributePathKey)) {
jsonValue[i].removeMember(kAttributePathKey);
}

if (!jsonValue[i].empty()) {
hasData = true;
}
} else {
hasData = true;
}
}
} else {
hasData = true;
}

if (!hasData) {
return CHIP_NO_ERROR;
}

value[kValueKey] = jsonValue;
auto valueStr = JsonToString(value);
return gDelegate->LogJSON(valueStr.c_str());
}
Expand All @@ -159,8 +198,31 @@ CHIP_ERROR LogCommandAsJSON(NSNumber * endpointId, NSNumber * clusterId, NSNumbe

Json::Value jsonValue;
VerifyOrDie(CHIP_NO_ERROR == AsJsonValue(result, jsonValue));
value[kValueKey] = jsonValue;

bool hasData = false;
if (jsonValue.isArray()) {
for (Json::ArrayIndex i = 0; i < jsonValue.size(); i++) {
if (jsonValue[i].isObject()) {
if (jsonValue[i].isMember(kCommandPathKey)) {
jsonValue[i].removeMember(kCommandPathKey);
}

if (!jsonValue[i].empty()) {
hasData = true;
}
} else {
hasData = true;
}
}
} else {
hasData = true;
}

if (!hasData) {
return CHIP_NO_ERROR;
}

value[kValueKey] = jsonValue;
auto valueStr = JsonToString(value);
return gDelegate->LogJSON(valueStr.c_str());
}
Expand Down

0 comments on commit d833656

Please sign in to comment.