Skip to content

Commit

Permalink
[WIP][darwin-framework-tool] Add supports for force-write
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple committed Feb 19, 2024
1 parent 37078f2 commit 1256304
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@
#import "MTRError_Utils.h"
#import <Matter/Matter.h>

inline constexpr char kWriteCommandKey[] = "write";
inline constexpr char kWriteByIdCommandKey[] = "write-by-id";
inline constexpr char kForceWriteCommandKey[] = "force-write";

enum class WriteCommandType {
kWrite, // regular, writable attributes
kForceWrite, // forced writes, send a write command on something expected to fail
};

class WriteAttribute : public ModelCommand {
public:
WriteAttribute()
: ModelCommand("write-by-id")
: ModelCommand(kWriteByIdCommandKey)
{
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
Expand All @@ -37,7 +46,7 @@ class WriteAttribute : public ModelCommand {
}

WriteAttribute(chip::ClusterId clusterId)
: ModelCommand("write-by-id")
: ModelCommand(kWriteByIdCommandKey)
, mClusterId(clusterId)
{
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
Expand Down Expand Up @@ -84,6 +93,7 @@ class WriteAttribute : public ModelCommand {
queue:callbackQueue
completion:^(NSArray<NSDictionary<NSString *, id> *> * _Nullable values, NSError * _Nullable error) {
if (error != nil) {
RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
LogNSError("Error writing attribute", error);
}
if (values) {
Expand All @@ -97,8 +107,8 @@ class WriteAttribute : public ModelCommand {
}

protected:
WriteAttribute(const char * _Nonnull attributeName)
: ModelCommand("write")
WriteAttribute(const char * _Nonnull attributeName, WriteCommandType commandType)
: ModelCommand(commandType == WriteCommandType::kWrite ? kWriteCommandKey : kForceWriteCommandKey)
{
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
// Subclasses are responsible for calling AddArguments.
Expand All @@ -115,6 +125,55 @@ class WriteAttribute : public ModelCommand {
chip::Optional<uint16_t> mTimedInteractionTimeoutMs;
chip::Optional<uint32_t> mDataVersion;

NSDictionary * _Nullable NSDictionaryFromValue(id _Nullable value, const char * _Nullable numberType)
{
NSLog(@"%@ - %@", [value class], value);
if (nil == value) {
return @ { MTRTypeKey : MTRNullValueType, MTRValueKey : value };
} else if ([value isKindOfClass:[NSString class]]) {
return @ { MTRTypeKey : MTRUTF8StringValueType, MTRValueKey : value };
} else if ([value isKindOfClass:[NSData class]]) {
return @ { MTRTypeKey : MTROctetStringValueType, MTRValueKey : value };
} else if ([value isKindOfClass:[NSArray class]]) {
return @ { MTRTypeKey : MTRArrayValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Bool") == 0) {
return @ { MTRTypeKey : MTRBooleanValueType, MTRValueKey : value };
} else if (strcmp(numberType, "UnsignedChar") == 0) {
return @ { MTRTypeKey : MTRUnsignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "UnsignedShort") == 0) {
return @ { MTRTypeKey : MTRUnsignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "UnsignedInt") == 0) {
return @ { MTRTypeKey : MTRUnsignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "UnsignedLongLong") == 0) {
return @ { MTRTypeKey : MTRUnsignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Char") == 0) {
return @ { MTRTypeKey : MTRSignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Short") == 0) {
return @ { MTRTypeKey : MTRSignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Long") == 0) {
return @ { MTRTypeKey : MTRSignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "LongLong") == 0) {
return @ { MTRTypeKey : MTRSignedIntegerValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Float") == 0) {
return @ { MTRTypeKey : MTRFloatValueType, MTRValueKey : value };
} else if (strcmp(numberType, "Double") == 0) {
return @ { MTRTypeKey : MTRDoubleValueType, MTRValueKey : value };
} else {
// TODO: Add suppots for MTRStructureValueType element. In short, we should convert the
// mValue to a MTRDataValueDictionaryDecodableType and the main issue is to map
// TLV tags to the property key.
// return @ { MTRTypeKey : MTRStructureValueType, MTRValueKey : value };
return @ { MTRTypeKey : @"Unsupported", MTRValueKey : value };
}

return nil;
}

NSDictionary * _Nullable NSDictionaryFromValue(id _Nullable value)
{
return NSDictionaryFromValue(value, nil);
}

private:
chip::ClusterId mClusterId;
chip::AttributeId mAttributeId;
Expand Down
23 changes: 18 additions & 5 deletions examples/darwin-framework-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,12 @@ public:

};

{{#if isWritableAttribute}}
{{! No list support for writing yet. Need to figure out how to represent the
values. }}
class Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public WriteAttribute
{
public:
Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): WriteAttribute("{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}"){{#if_chip_complex}}, mComplex(&mValue){{/if_chip_complex}}
Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(): WriteAttribute("{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", WriteCommandType::k{{#unless isWritable}}Force{{/unless}}Write){{#if_chip_complex}}, mComplex(&mValue){{/if_chip_complex}}
{
AddArgument("attr-name", "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}");
{{#if_chip_complex}}
Expand All @@ -217,11 +216,13 @@ public:
constexpr chip::AttributeId attributeId = chip::app::Clusters::{{asUpperCamelCase parent.name}}::Attributes::{{asUpperCamelCase name}}::Id;

ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") WriteAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId);
{{#if isWritable}}
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
__auto_type * cluster = [[MTRBase{{>cluster}} alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
__auto_type * params = [[MTRWriteParams alloc] init];
params.timedWriteTimeout = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
{{/if}}
{{#if_chip_complex}}
{{asObjectiveCType type parent.name}} value;
{{>decodable_value target="value" source="mValue" cluster=parent.name errorCode="return err;" depth=0}}
Expand All @@ -248,6 +249,7 @@ public:
{{/if}}
{{/if_chip_complex}}

{{#if isWritable}}
[cluster write{{>attribute}}WithValue:value params:params completion:^(NSError * _Nullable error) {
if (error != nil) {
LogNSError("{{asUpperCamelCase parent.name preserveAcronyms=true}} {{asUpperCamelCase name preserveAcronyms=true}} write Error", error);
Expand All @@ -256,6 +258,20 @@ public:
SetCommandExitStatus(error);
}];
return CHIP_NO_ERROR;
{{else}}
{{#if_chip_complex}}
auto * dictValue = NSDictionaryFromValue(value);
{{else}}
{{#if (isOctetString type)}}
auto * dictValue = NSDictionaryFromValue(value);
{{else if (isString type)}}
auto * dictValue = NSDictionaryFromValue(value);
{{else}}
auto * dictValue = NSDictionaryFromValue(value, "{{asObjectiveCNumberType "" type false}}");
{{/if}}
{{/if_chip_complex}}
return WriteAttribute::SendCommand(device, endpointId, clusterId, attributeId, dictValue);
{{/if}}
}

private:
Expand All @@ -271,7 +287,6 @@ private:
{{/if_chip_complex}}
};

{{/if}}
{{#if isReportableAttribute}}
class SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public SubscribeAttribute
{
Expand Down Expand Up @@ -370,9 +385,7 @@ void registerCluster{{asUpperCamelCase name}}(Commands & commands)
#if MTR_ENABLE_PROVISIONAL
{{/if}}
make_unique<Read{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{#if isWritableAttribute}}
make_unique<Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{/if}}
{{#if isReportableAttribute}}
make_unique<SubscribeAttribute{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(), //
{{/if}}
Expand Down

0 comments on commit 1256304

Please sign in to comment.