HealthKitReporter icon indicating copy to clipboard operation
HealthKitReporter copied to clipboard

Support for non-String fields in metadata like HKMetadataKeySyncVersion

Open umangsh opened this issue 3 years ago • 15 comments

Is your feature request related to a problem? Please describe. Harmonized.metadata uses [String: String] map for field representation. This fails for metadata fields like HKMetadataKeySyncVersion which expect an NSNumber. Presumably affects other NSNumber fields like HKMetadataKeyReferenceRangeLowerLimit, etc.

Describe the solution you'd like Quantity.Harmonized.metadata should not fail when setting {'HKMetadataKeySyncVersion': 123} and writing to healthKit on device.

umangsh avatar Jun 23 '22 23:06 umangsh

Hi, following up to see if the problem description is clear. There are more details in https://github.com/VictorKachalov/health_kit_reporter/issues/46 - it reads like a debug log, but I'm happy to clarify any details you'd like.

In the meantime, is there is a workaround to write HKMetadataKeySyncVersion to apple health in quantity samples ?

umangsh avatar Jun 25 '22 22:06 umangsh

Hi, just checking in: were you able to look at this bug ? @VictorKachalov

umangsh avatar Jul 03 '22 20:07 umangsh

Hi @umangsh

Thank you for your message. Unfortunately I didn't yet have time to take a look at the issue.

Have you tried to provide any local fixes? If so It could be a good opportunity to open a PR, if not I will try this week

kvs-coder avatar Jul 04 '22 06:07 kvs-coder

Thanks! My local fixes didn't work unfortunately.

umangsh avatar Jul 06 '22 19:07 umangsh

@VictorKachalov were you able to look at this bug last week?

umangsh avatar Jul 18 '22 17:07 umangsh

@VictorKachalov checking in, any luck with this bug?

umangsh avatar Oct 10 '22 20:10 umangsh

Hi @umangsh

Please sorry for my late response, unfortunately couldn't make it for the deeper investigation due to the lack of time last months.

The original HK metadata expects one of the three possible types: NSString, NSDate, NSNumber and these Obj-C types unfortunately are not Codable friendly. But I can use Swift's String, Date, Double instead.

I am seeking the possibility to bring a clean solution combining these types in one metadata property, but currently don't have any ideas.

As a fallback solution, I could extend the amount of metadata properties like:

let metadataString: [String: String]?
let metadataDate: [String: Date]?
let metadataDouble: [String: Double]?

kvs-coder avatar Oct 11 '22 07:10 kvs-coder

@VictorKachalov Makes sense, thanks for the explanation. Fallback solution sounds reasonable as a short term fix.

umangsh avatar Oct 11 '22 15:10 umangsh

Hi @umangsh

please check the latest 2.0.0 version (Metadata revamp potentially introduces breaking change, but I prepared a fallback solution to avoid errors because ExpressibleByDictionaryLiteral)

kvs-coder avatar Oct 29 '22 19:10 kvs-coder

@VictorKachalov Awesome, thank you! I'm using the API through health_kit_reporter (https://github.com/VictorKachalov/health_kit_reporter), which is still at 2.0.4. Mind updating the flutter plugin?

umangsh avatar Oct 29 '22 22:10 umangsh

@VictorKachalov Thanks! I was able to update the plugin version (2.1.0) and pod version (2.0.0) - I think it's improved, but doesn't work quite yet - HKMetadataKeySyncIdentifier and HKMetadataKeySyncVersion values aren't written to Apple Health.

  1. Code that initiates the writes in flutter: https://github.com/umangsh/famnom_flutter/blob/main/packages/healthkit/lib/src/healthkit.dart#L108

  2. Printing the values in Quantity.swift shows the metadata values as nil:

extension Quantity.Harmonized: Payload {
    public static func make(from dictionary: [String: Any]) throws -> Quantity.Harmonized {
        guard
            let value = dictionary["value"] as? NSNumber,
            let unit = dictionary["unit"] as? String
        else {
            throw HealthKitError.invalidValue("Invalid dictionary: \(dictionary)")
        }
        print("dict")
        print(dictionary["metadata"])
        let metadata = dictionary["metadata"] as? [String: Any]
        print("converted")
        print(metadata)
        print("cast")
        print(metadata?.asMetadata)
        return Quantity.Harmonized(
            value: Double(truncating: value),
            unit: unit,
            metadata: metadata?.asMetadata
        )

Sample outputs:

dict
Optional({
    HKMetadataKeySyncIdentifier = "FAMNOM-2022-10-30-1087";
    HKMetadataKeySyncVersion = 1667147391558;
})
converted
Optional(["HKMetadataKeySyncIdentifier": FAMNOM-2022-10-30-1087, "HKMetadataKeySyncVersion": 1667147391558])
cast
nil ---> Didn't expect this to be nil

umangsh avatar Oct 30 '22 16:10 umangsh

@VictorKachalov was the previous message helpful? Let me know if I can provide any more info.

umangsh avatar Nov 08 '22 16:11 umangsh

hi @umangsh I will check this, thank you for the input. Have you tried to do this with this native HealthKitReporter? Does HealthKit also ignore the data during writing?

kvs-coder avatar Nov 10 '22 16:11 kvs-coder

@VictorKachalov Just the two fields - HKMetadataKeySyncIdentifier and HKMetadataKeySyncVersion, other values are written fine.

umangsh avatar Nov 10 '22 18:11 umangsh

@kvs-coder still an issue. I wonder if Double and NSNumber are causing issues. Here's a small snippet to reproduce in flutter:

 final data = Quantity(
        '',
        QuantityType.dietaryEnergyConsumed.identifier,
        1676048055148,
        1676048055148,
        null,
        const SourceRevision(
          Source('appTitle', 'appBundle'),
          null,
          null,
          '',
          OperatingSystem(0, 0, 0),
        ),
        QuantityHarmonized(1504, 'kcal', <String, dynamic>{
          'HKMetadataKeySyncVersion':
              DateTime.now().millisecondsSinceEpoch,
          'HKMetadataKeySyncIdentifier':
              'appTitle-2023-02-09-100',
        }),
      );
await HealthKitReporter.save(data);

HKMetadataKeySyncVersion and HKMetadataKeySyncIdentifier are not written to apple health. These fields are required for de-duping:

Screenshot 2023-02-10 at 9 45 56 AM

umangsh avatar Feb 10 '23 17:02 umangsh