Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

query correlation type should specify more than one unit type #81

Open
ghost opened this issue Nov 22, 2016 · 2 comments
Open

query correlation type should specify more than one unit type #81

ghost opened this issue Nov 22, 2016 · 2 comments

Comments

@ghost
Copy link

ghost commented Nov 22, 2016

correlations don't have always one unit of measurement. The example comes with food, where a correlation can have weights (like for sugar, or vitamins) as well as energy (calories) and volumes (litres of water). A solution could be, instead of passing one unit, to pass an array of units.

Here is how the implementation would look like:

- (void)queryCorrelationType:(CDVInvokedUrlCommand *)command {
    NSDictionary *args = command.arguments[0];
    NSDate *startDate = [NSDate dateWithTimeIntervalSince1970:[args[HKPluginKeyStartDate] longValue]];
    NSDate *endDate = [NSDate dateWithTimeIntervalSince1970:[args[HKPluginKeyEndDate] longValue]];
    NSString *correlationTypeString = args[HKPluginKeyCorrelationType];
    NSArray<NSString *> *unitsString = args[HKPluginKeyUnits];

    HKCorrelationType *type = (HKCorrelationType *) [HealthKit getHKSampleType:correlationTypeString];
    if (type == nil) {
        [HealthKit triggerErrorCallbackWithMessage:@"sampleType was invalid" command:command delegate:self.commandDelegate];
        return;
    }
    NSMutableArray *units = [[NSMutableArray alloc] init];
    for (NSString *unitString in unitsString) {
        HKUnit *unit = ((unitString != nil) ? [HKUnit unitFromString:unitString] : nil);
        [units addObject:unit];
    }
    
    // TODO check that unit is compatible with sampleType if sample type of HKQuantityType
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];

    HKCorrelationQuery *query = [[HKCorrelationQuery alloc] initWithType:type predicate:predicate samplePredicates:nil completion:^(HKCorrelationQuery *correlationQuery, NSArray *correlations, NSError *error) {
        __block HealthKit *bSelf = self;
        if (error) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                [HealthKit triggerErrorCallbackWithMessage:error.localizedDescription command:command delegate:bSelf.commandDelegate];
            });
        } else {
            NSMutableArray *finalResults = [[NSMutableArray alloc] initWithCapacity:correlations.count];
            for (HKSample *sample in correlations) {
                NSDate *startSample = sample.startDate;
                NSDate *endSample = sample.endDate;

                NSMutableDictionary *entry = [NSMutableDictionary dictionary];
                entry[HKPluginKeyStartDate] = [HealthKit stringFromDate:startSample];
                entry[HKPluginKeyEndDate] = [HealthKit stringFromDate:endSample];

                // common indices
                entry[HKPluginKeyUUID] = sample.UUID.UUIDString;
                if (sample.metadata == nil || ![NSJSONSerialization isValidJSONObject:sample.metadata]) {
                    entry[HKPluginKeyMetadata] = @{};
                } else {
                    entry[HKPluginKeyMetadata] = sample.metadata;
                }


                if ([sample isKindOfClass:[HKCategorySample class]]) {

                    HKCategorySample *csample = (HKCategorySample *) sample;
                    entry[HKPluginKeyValue] = @(csample.value);
                    entry[@"categoryType.identifier"] = csample.categoryType.identifier;
                    entry[@"categoryType.description"] = csample.categoryType.description;

                } else if ([sample isKindOfClass:[HKCorrelation class]]) {

                    HKCorrelation *correlation = (HKCorrelation *) sample;
                    entry[HKPluginKeyCorrelationType] = correlation.correlationType.identifier;

                    NSMutableArray *samples = [NSMutableArray arrayWithCapacity:correlation.objects.count];
                    for (HKQuantitySample *quantitySample in correlation.objects) {
                        for (int i=0; i<[units count]; i++) {
                            HKUnit *unit = units[i];
                            NSString *unitS = unitsString[i];
                            if ([quantitySample.quantity isCompatibleWithUnit:unit]) {
                                [samples addObject:@{
                                                     HKPluginKeyStartDate: [HealthKit stringFromDate:quantitySample.startDate],
                                                     HKPluginKeyEndDate: [HealthKit stringFromDate:quantitySample.endDate],
                                                     HKPluginKeySampleType: quantitySample.sampleType.identifier,
                                                     HKPluginKeyValue: @([quantitySample.quantity doubleValueForUnit:unit]),
                                                     HKPluginKeyUnit: unitS,
                                                     HKPluginKeyMetadata: ((quantitySample.metadata != nil) ? quantitySample.metadata : @{}),
                                                     HKPluginKeyUUID: quantitySample.UUID.UUIDString
                                                     }
                                 ];
                                break;
                            }
                        }
                    }
                    entry[HKPluginKeyObjects] = samples;

                } else if ([sample isKindOfClass:[HKQuantitySample class]]) {

                    HKQuantitySample *qsample = (HKQuantitySample *) sample;
                    for (int i=0; i<[units count]; i++) {
                        HKUnit *unit = units[i];
                        if ([qsample.quantity isCompatibleWithUnit:unit]) {
                            double quantity = [qsample.quantity doubleValueForUnit:unit];
                            entry[@"quantity"] = [NSString stringWithFormat:@"%f", quantity];
                            break;
                        }
                    }

                } else if ([sample isKindOfClass:[HKWorkout class]]) {

                    HKWorkout *wsample = (HKWorkout *) sample;
                    entry[@"duration"] = @(wsample.duration);

                } else if ([sample isKindOfClass:[HKCorrelationType class]]) {
                    // TODO
                    // wat do?
                }

                [finalResults addObject:entry];
            }

            dispatch_sync(dispatch_get_main_queue(), ^{
                CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:finalResults];
                [bSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
            });
        }
    }];
    [[HealthKit sharedHealthStore] executeQuery:query];
}

you will also need to define HKPluginKeyUnits at the beginning as:

static NSString *const HKPluginKeyUnits = @"units";

I am using this code myself and it's working good!

@EddyVerbruggen
Copy link
Owner

Interesting change! Is this something you can easily submit as a PR?

@ghost
Copy link
Author

ghost commented Nov 22, 2016

done. Let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant