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

Support for non-String fields in metadata like HKMetadataKeySyncVersion #17

Open
umangsh opened this issue Jun 23, 2022 · 15 comments
Open

Comments

@umangsh
Copy link

umangsh commented Jun 23, 2022

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
Copy link
Author

umangsh commented Jun 25, 2022

Hi, following up to see if the problem description is clear. There are more details in kvs-coder/health_kit_reporter#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
Copy link
Author

umangsh commented Jul 3, 2022

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

@kvs-coder
Copy link
Owner

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

@umangsh
Copy link
Author

umangsh commented Jul 6, 2022

Thanks! My local fixes didn't work unfortunately.

@umangsh
Copy link
Author

umangsh commented Jul 18, 2022

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

@umangsh
Copy link
Author

umangsh commented Oct 10, 2022

@VictorKachalov checking in, any luck with this bug?

@kvs-coder
Copy link
Owner

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]?

@umangsh
Copy link
Author

umangsh commented Oct 11, 2022

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

@kvs-coder
Copy link
Owner

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)

@umangsh
Copy link
Author

umangsh commented Oct 29, 2022

@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
Copy link
Author

umangsh commented Oct 30, 2022

@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
Copy link
Author

umangsh commented Nov 8, 2022

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

@kvs-coder
Copy link
Owner

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?

@umangsh
Copy link
Author

umangsh commented Nov 10, 2022

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

@umangsh
Copy link
Author

umangsh commented Feb 10, 2023

@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

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

2 participants