blob: 3440a251b98bbec0fba9a4c9485bd0f2ba667bad [file] [log] [blame]
/**
*
* Copyright (c) 2020 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "DefaultsUtils.h"
#import "FabricKeys.h"
NSString * const MTRToolDefaultsDomain = @"com.matter.CHIPTool";
NSString * const kNetworkSSIDDefaultsKey = @"networkSSID";
NSString * const kNetworkPasswordDefaultsKey = @"networkPassword";
NSString * const MTRNextAvailableDeviceIDKey = @"nextDeviceID";
NSString * const kFabricIdKey = @"fabricId";
NSString * const kDevicePairedKey = @"Paired";
id MTRGetDomainValueForKey(NSString * domain, NSString * key)
{
id value = (id) CFBridgingRelease(CFPreferencesCopyAppValue((CFStringRef) key, (CFStringRef) domain));
if (value) {
return value;
}
return nil;
}
BOOL MTRSetDomainValueForKey(NSString * domain, NSString * key, id value)
{
CFPreferencesSetAppValue((CFStringRef) key, (__bridge CFPropertyListRef _Nullable)(value), (CFStringRef) domain);
return CFPreferencesAppSynchronize((CFStringRef) domain) == true;
}
void MTRRemoveDomainValueForKey(NSString * domain, NSString * key)
{
CFPreferencesSetAppValue((CFStringRef) key, NULL, (CFStringRef) domain);
CFPreferencesAppSynchronize((CFStringRef) domain);
}
uint64_t MTRGetNextAvailableDeviceID(void)
{
uint64_t nextAvailableDeviceIdentifier = 1;
NSNumber * value = MTRGetDomainValueForKey(MTRToolDefaultsDomain, MTRNextAvailableDeviceIDKey);
if (!value) {
MTRSetDomainValueForKey(MTRToolDefaultsDomain, MTRNextAvailableDeviceIDKey,
[NSNumber numberWithUnsignedLongLong:nextAvailableDeviceIdentifier]);
} else {
nextAvailableDeviceIdentifier = [value unsignedLongLongValue];
}
return nextAvailableDeviceIdentifier;
}
void MTRSetNextAvailableDeviceID(uint64_t id)
{
MTRSetDomainValueForKey(MTRToolDefaultsDomain, MTRNextAvailableDeviceIDKey, [NSNumber numberWithUnsignedLongLong:id]);
}
static CHIPToolPersistentStorageDelegate * storage = nil;
static uint16_t kTestVendorId = 0xFFF1u;
static MTRDeviceController * sController = nil;
MTRDeviceController * InitializeMTR(void)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CHIPToolPersistentStorageDelegate * storage = [[CHIPToolPersistentStorageDelegate alloc] init];
__auto_type * factory = [MTRControllerFactory sharedInstance];
__auto_type * factoryParams = [[MTRControllerFactoryParams alloc] initWithStorage:storage];
if (![factory startup:factoryParams]) {
return;
}
__auto_type * keys = [[FabricKeys alloc] init];
if (keys == nil) {
return;
}
__auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithSigningKeypair:keys fabricId:1 ipk:keys.ipk];
params.vendorId = @(kTestVendorId);
// We're not sure whether we have a fabric configured already; try as if
// we did, and if not fall back to creating a new one.
sController = [factory startControllerOnExistingFabric:params];
if (sController == nil) {
sController = [factory startControllerOnNewFabric:params];
}
});
return sController;
}
MTRDeviceController * MTRRestartController(MTRDeviceController * controller)
{
__auto_type * keys = [[FabricKeys alloc] init];
if (keys == nil) {
NSLog(@"No keys, can't restart controller");
return controller;
}
NSLog(@"Shutting down the stack");
[controller shutdown];
NSLog(@"Starting up the stack");
__auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithSigningKeypair:keys fabricId:1 ipk:keys.ipk];
sController = [[MTRControllerFactory sharedInstance] startControllerOnExistingFabric:params];
return sController;
}
uint64_t MTRGetLastPairedDeviceId(void)
{
uint64_t deviceId = MTRGetNextAvailableDeviceID();
if (deviceId > 1) {
deviceId--;
}
return deviceId;
}
BOOL MTRGetConnectedDevice(MTRDeviceConnectionCallback completionHandler)
{
MTRDeviceController * controller = InitializeMTR();
// Let's use the last device that was paired
uint64_t deviceId = MTRGetLastPairedDeviceId();
return [controller getBaseDevice:deviceId queue:dispatch_get_main_queue() completionHandler:completionHandler];
}
MTRBaseDevice * MTRGetDeviceBeingCommissioned(void)
{
NSError * error;
MTRDeviceController * controller = InitializeMTR();
MTRBaseDevice * device = [controller getDeviceBeingCommissioned:MTRGetLastPairedDeviceId() error:&error];
if (error) {
NSLog(@"Error retrieving device being commissioned for deviceId %llu", MTRGetLastPairedDeviceId());
return nil;
}
return device;
}
BOOL MTRGetConnectedDeviceWithID(uint64_t deviceId, MTRDeviceConnectionCallback completionHandler)
{
MTRDeviceController * controller = InitializeMTR();
return [controller getBaseDevice:deviceId queue:dispatch_get_main_queue() completionHandler:completionHandler];
}
BOOL MTRIsDevicePaired(uint64_t deviceId)
{
NSString * PairedString = MTRGetDomainValueForKey(MTRToolDefaultsDomain, KeyForPairedDevice(deviceId));
return [PairedString boolValue];
}
void MTRSetDevicePaired(uint64_t deviceId, BOOL paired)
{
MTRSetDomainValueForKey(MTRToolDefaultsDomain, KeyForPairedDevice(deviceId), paired ? @"YES" : @"NO");
}
NSString * KeyForPairedDevice(uint64_t deviceId) { return [NSString stringWithFormat:@"%@%llu", kDevicePairedKey, deviceId]; }
void MTRUnpairDeviceWithID(uint64_t deviceId)
{
MTRSetDevicePaired(deviceId, NO);
MTRGetConnectedDeviceWithID(deviceId, ^(MTRBaseDevice * _Nullable device, NSError * _Nullable error) {
if (error) {
NSLog(@"Failed to unpair device %llu still removing from CHIPTool. %@", deviceId, error);
return;
}
NSLog(@"Attempting to unpair device %llu", deviceId);
MTRBaseClusterOperationalCredentials * opCredsCluster =
[[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:0 queue:dispatch_get_main_queue()];
[opCredsCluster
readAttributeCurrentFabricIndexWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
if (error) {
NSLog(@"Failed to get current fabric index for device %llu still removing from CHIPTool. %@", deviceId, error);
return;
}
MTROperationalCredentialsClusterRemoveFabricParams * params =
[[MTROperationalCredentialsClusterRemoveFabricParams alloc] init];
params.fabricIndex = value;
[opCredsCluster removeFabricWithParams:params
completionHandler:^(MTROperationalCredentialsClusterNOCResponseParams * _Nullable data,
NSError * _Nullable error) {
if (error) {
NSLog(@"Failed to remove current fabric index %@ for device %llu. %@",
params.fabricIndex, deviceId, error);
return;
}
NSLog(@"Successfully unpaired deviceId %llu", deviceId);
}];
}];
});
}
@implementation CHIPToolPersistentStorageDelegate
// MARK: MTRPersistentStorageDelegate
- (nullable NSData *)storageDataForKey:(NSString *)key
{
NSData * value = MTRGetDomainValueForKey(MTRToolDefaultsDomain, key);
NSLog(@"MTRPersistentStorageDelegate Get Value for Key: %@, value %@", key, value);
return value;
}
- (BOOL)setStorageData:(NSData *)value forKey:(NSString *)key
{
return MTRSetDomainValueForKey(MTRToolDefaultsDomain, key, value);
}
- (BOOL)removeStorageDataForKey:(NSString *)key
{
if (MTRGetDomainValueForKey(MTRToolDefaultsDomain, key) == nil) {
return NO;
}
MTRRemoveDomainValueForKey(MTRToolDefaultsDomain, key);
return YES;
}
@end