How to Build an Indivo X Personal Health App

4,220 views

Published on

Details on building an app for the Indivo X Personally Controlled Health Record

Published in: Health & Medicine
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
4,220
On SlideShare
0
From Embeds
0
Number of Embeds
159
Actions
Shares
0
Downloads
99
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

How to Build an Indivo X Personal Health App

  1. 1. How to build an Indivo X Personal Health App Ben Adida Indivo X Users Meeting 15 April 2010
  2. 2. Demo
  3. 3. Four Steps 1. Scope and framing of your app 2. Authentication and Authorization 3. REST API calls 4. UI widgets
  4. 4. Basic Terminology • Account • Record • PHA / User App • Admin App • (Chrome App)
  5. 5. 1. Scope Screen Real-Estate controlled by PHA
  6. 6. For Example
  7. 7. Anatomy of a PHA • name • start URL “Problems” http://problems/auth/start • description • post-auth URL “track your problems” http://problems/auth/after • principal email • consumer key problems@apps.indivo.org 838xdnwk-sdf-werkj34 • data use agreement: • consumer secret what the app intends to do 23lnbls-235lnsdf-2343 with the data it reads from the record.
  8. 8. 2. Auth
  9. 9. Components Access Token Indivo Server PHA User's Browser
  10. 10. OAuth Protocol consumer_token consumer_secret Indivo Server signed PHA (Data Service) HTTP+POX (Consumer) authentication HMAC-SHA1 RSA-SHA1 .... User's Browser
  11. 11. With the first click...
  12. 12. begin the auth process IFRAME directed to the PHA’s start URL with parameter record_id
  13. 13. User's Indivo PHA Browser Server add GET request_token Connection Step (1) token REDIRECT authorize
  14. 14. authorize the app
  15. 15. User's Indivo PHA Browser Server REDIRECT authorize Authorization Process Connection Step (2) post-add
  16. 16. redirect to app IFRAME directed to the PHA’s post-auth URL which finishes the oAuth process
  17. 17. User's Indivo PHA Browser Server post-add GET access_token Connection token Step (3)
  18. 18. User's Indivo PHA Browser Server token GET data Interaction Phase data
  19. 19. OAuth Request Authorization: OAuth realm="https://indivohealth.org/", oauth_consumer_key="0685bd9184jfhq22", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176", oauth_version="1.0"
  20. 20. The code must be awfully complicated ...
  21. 21. def get_indivo_client(request, with_token=True): client = IndivoClient(CONSUMER_KEY, CONSUMER_SECRET, INDIVO_SERVER_LOCATION) if with_token: client.update_token(request.session['token']) return client
  22. 22. def start_auth(request): client = get_indivo_client(request, with_token=False) # do we have a record_id? record_id = request.GET.get('record_id', None) # prepare request token parameters params = {‘record_id’: record_id} # request a request token request_token = parse_token_from_response( client.post_request_token(data=params)) # store the request token in the session request.session['token'] = request_token # redirect to the UI server return HttpResponseRedirect (settings.INDIVO_UI_SERVER_BASE + '/oauth/authorize? oauth_token=%s' % request_token['oauth_token'])
  23. 23. def after_auth(request): # get the token and verifier from the URL parameters # retrieve request token stored in the session client = get_indivo_client(...) # exchange request token for access token access_token = parse_token_from_response (client.post_access_token(data={'oauth_verifier' : oauth_verifier})) # store stuff in the session request.session['access_token'] = access_token # get record ID that came back with token request.session['record_id'] = access_token['xoauth_indivo_record_id'] # go to list of problems return HttpResponseRedirect(reverse(problem_list))
  24. 24. 3. REST API Calls
  25. 25. get data, e.g. problem list
  26. 26. web platform model Access Token Indivo Server PHA User's Browser
  27. 27. def problem_list(request): client = get_indivo_client(request) record_id = request.session['record_id'] # get record information record_xml = client.read_record(record_id = record_id) # get problem list from most recent to oldest problems_xml = client.read_problems(record_id = record_id, parameters={'order_by': '-date_onset'})
  28. 28. def new_problem(request): # get the variables and create a problem XML params = ... problem_xml = render_raw('problem', params, type='xml') # add the problem client = get_indivo_client(request) client.post_document(record_id = request.session ['record_id'], data=problem_xml) # add a notification client.record_notify(record_id = request.session ['record_id'], data={'content':'a new problem has been added to your problem list'}) return HttpResponseRedirect(reverse(problem_list))
  29. 29. Other API calls • get reports on labs, medications, allergies, immunizations, etc. • get basic record information • add documents, version them, etc. • store application-specific data not visible to other apps (bookkeeping)
  30. 30. What about sharing? • Carenets: a space for sharing, including documents, apps, and people • An app can be started with a carenet_id instead of a record_id. • The same API calls are available with a carenet_id, but may see only a subset of the data.
  31. 31. 4. UI Widgets
  32. 32. Auto-Complete
  33. 33. Auto-Complete def code_lookup(request): client = get_indivo_client(request) query = request.GET['query'] # reformat this for the jQuery autocompleter codes = simplejson.loads( client.lookup_code( coding_system='umls-snomed', parameters= {'q' : query})) formatted_codes = {'query': query, 'suggestions': [c ['full_value'] for c in codes], 'data': codes} return HttpResponse(simplejson.dumps (formatted_codes), mimetype="text/plain")
  34. 34. Auto-Complete <script src="jquery.js"></script> <script src="jquery-ui.js"></script> <script src="jquery.autocomplete.js"></script> <script> $('#problem_fullname').autocomplete({ serviceUrl: 'codelookup', minChars: 2, onSelect: function(value, data) { $('#problem_code').val(data.code); } }); </script>
  35. 35. Sharing & Audit def one_problem(request, problem_id): ... surl_credentials = client.get_surl_credentials() ...
  36. 36. Sharing & Audit <script src="{{SERVER_BASE}}/lib/widgets.js"></script> <script> Indivo.setup('{{INDIVO_UI_SERVER_BASE}}'); </script> <script> Indivo.Auth.setToken("{{token}}","{{secret}}"); Indivo.Widget.DocumentAccess.add('{{record_id}}', '{{problem_id}}'); </script>
  37. 37. Upcoming Features...
  38. 38. Background Apps - most apps don’t need access beyond the user session - we tie the oAuth token to the web session ... unless the user authorizes more
  39. 39. Summary - your app is activated for each record - do the oAuth dance, get an access token - write to the input of the data pipeline, read from the end of the data pipeline, all simple REST+oAuth calls - use built-in widgets to get advanced functionality

×