precisely / curious2

0 stars 0 forks source link

Investigate integration with HumanAPI #137

Closed syntheticzero closed 10 years ago

syntheticzero commented 10 years ago

Hi Mitsu,

I setup a developer account for you on HumanAPI for you today. You can log in with the following information.

https://user.humanapi.co Username: mitsu.hadeishi@gmail.com Password: aZ98QCqd

Let me know if you have any questions regarding the API.

Regards,

Ola Wiberg HumanAPI

visheshd commented 10 years ago

Wow this is something I was going to bring up with you as another revenue channel. Didn't know somebody was doing already doing it.

So, they are aggregating all API's to provide one standard interface. But this will add a tiered flow. A user on Curious will first have to authenticate their HumanAPI account for us to access the api (if they don't have one they will prompted to create one) but they will also have authenticate for a device vendor (eg: FitBit, Withings) on the HumanAPI end so that HumanAPI can access the data from those vendors. This seems like a cumbersome flow.

The integration itself is going to be straightforward as they also support authentication using oAuth 2.0 and have a well documented JSON API. It will be very similar to FitBit. There are numerous data endpoints and each endpoint's availability depends on the capability of the device(s) connected to the HumanAPI account.

They seem like they could be competition but may be I am not seeing the entire picture

syntheticzero commented 10 years ago

From a market standpoint we are intending to be as open as possible but we're not going to rely on any third party aggregator exclusively. HumanAPI has the advantage that they have integrations with devices we can't access right now (like Nike Fuelband). Ultimately if someone is already aggregated at HumanAPI that means they can in one step integrate with us --- which is definitely what we want (we want to make it as easy as possible for people to use Curious). They won't have to re-integrate all their devices with us, one at a time, they can just integrate once. But we'll continue to offer integrations on our own.

It would help to refactor the device integration code so we don't have to rewrite all the tag mapping code every time we want to import data from an aggregator like HumanAPI as opposed to directly. We're also going to support OpenMHealth which will have a similar situation with a well-documented JSON API and multiple endpoints.

But yes, we're not going to rely on HumanAPI or any other aggregator. But since we're devoted to open data and the idea of free flows of information under user control, we do want to integrate with as many viable services as possible.

syntheticzero commented 10 years ago

Regarding refactoring the code: another integrator we should look at is:

http://openmhealth.org

We should support this API both on the client and server side. In some ways their data is more structured than the data in our system, so we're going to have to think through how best to support their API and store metadata about the tag streams in our system.

The refactor might be along the lines of using the Facade pattern or something similar (dependency injection?) to abstract away some of the details of the specific data source so we can put common code for a given data stream together in one place. Let me know what you have in mind before you implement so we can discuss (i.e. let's do a design review before implementing this). We can make this a separate ticket if you want.

visheshd commented 10 years ago

Any device data coming in from HumanAPI would be in the same format with an additional field indicating the source.


 {
      id: "52867cbdde3155565f0002dd",
      userId: "52867cbbde3155565f000001",
      timestamp: "2013-11-15T11:57:49.086Z",
      value: 21,
      unit: "percent",
      source: "fitbit"
    }

With the current implementation to add HumanAPI we would have to implement a TagUnitMap for it and add another endpoint notify/human-api

Refactor: We could manage this better using DI (Google Guice?) based on the integrationType Have one common notification endpoint /home/notifiy/{integrationType} based on the integration type we inject the corresponding implementation

Eg: if integrationType is FitBit bind(IntegrationDataService.class) .toProvider(Class.forName(params.integrationType+DataService));

Interfaces which we would eventually implement for each integration IntegrationDataService

IntegrationParser

AbstractIntegrationParser implements IntegrationParser

A common converter Converter

Even with this approach we would have to implement these classes for HumanAPI once. But things would be little more cleaner. Thoughts?

syntheticzero commented 10 years ago

Okay, so you're saying that HumanAPI abstracts all the different formats into the format you wrote above? I.e., so it parses the various formats and turns it into the format above?

If that's the case it seems like it's already parsing it into a format that's pretty close to what we use in Curious. But in that format, how do you tell what the measurement is of? I.e., 21 percent of what? Does it have a field that indicates what's being measured? For instance for Withings how can you tell whether it is blood pressure or weight?

The refactor I'm thinking about is more along the lines of trying to abstract Withings tag unit mapping for Withings data that has come via different sources. For instance, if the data came in via a direct integration, via OpenMHealth, via Human API, etc., is there enough shared code between these three integrations so that we can share code? What I'd like to avoid is having to write three or more integrations every time we integrate with a new service, depending on how many different paths we are bringing in the data.

visheshd commented 10 years ago

Yes, it abstracts all different formats into one format. The above is the response we get for their "body_fat" endpoint.

The have endpoints for Profile Activities Blood Glucose Blood Pressure Body Mass Index Body Fat Genetics Height Locations Sleeps Weight

In the current setup we only have to write integration for each device once if we are doing a direct integration. If we add an aggregator like HumanAPI we have to write one additional UnitMap and DataService for HumanAPI (since it has its own abstracted format) regardless of the variety of devices that are coming through it.

For eg: FitBit and Withings have direct integrations for which we wrote a TagUnit and Dataservice for each. Once we write another TagUnit and DataService for the HumanAPI it would enable us to get data for any device supported by HumanAPI without writing additional code including FitBit and Withings

syntheticzero commented 10 years ago

Okay. Let's not do any major refactoring for now, then.

syntheticzero commented 10 years ago

One thing to check --- what we'd like to have happen is that the tag maps for Human API should result in the same (or as close to the same as possible) tags when importing data from a given device (say, FitBit) via Human API as it would if we import the data directly. If there is a difference, let's talk about it here and try to resolve the differences.

On testing, since you guys have some devices, let's get some testing set up with these devices and check the output for syncing via Human API and directly. Note: I believe Human API has access to more data than we can get directly. As you test these devices please post here the results so I can take a look.

syntheticzero commented 10 years ago

Deployed