def getBasicDemographicInformation(self): tree = self.getThings('bf516a61-5252-4c28-a979-27f45f62f78d') for id in [t.text for t in csss('thing-id')(tree)]: tree = self.getThingById(id) self.person.gender = csss('gender')(tree)[0].text self.person.birth_year = csss('birthyear')(tree)[0].text
def _authenticate(self): content_tmpl = string.Template(""" <content> <app-id>$APP_ID</app-id> <hmac>HMACSHA256</hmac> <signing-time>$NOW</signing-time> </content> """) content_str = content_tmpl.substitute({ 'APP_ID': settings.APP_ID, 'NOW': self._now_in_iso() }).translate(None, '\n ') t = string.Template(""" <wc-request:request xmlns:wc-request="urn:com.microsoft.wc.request"> <header> <method>CreateAuthenticatedSessionToken</method> <method-version>2</method-version> <app-id>$APP_ID</app-id> <msg-time>$NOW</msg-time> <msg-ttl>$MSG_TTL</msg-ttl> <version>$VERSION</version> </header> <info> <auth-info> <app-id>$APP_ID</app-id> <credential> <appserver2> <sig digestMethod="SHA1" sigMethod="RSA-SHA1" thumbprint="$APP_THUMBPRINT"> $SIGNATURE </sig> $CONTENT </appserver2> </credential> </auth-info> </info> </wc-request:request>""") payload = t.substitute({ 'APP_ID': settings.APP_ID, 'NOW': self._now_in_iso(), 'MSG_TTL': self._ttl, 'VERSION': self._version, 'APP_THUMBPRINT': settings.APP_THUMBPRINT, 'SIGNATURE': self._sign(content_str), 'CONTENT': content_str }).translate(None, '\n') tree = self._send_request_and_get_tree(payload) self._auth_token = csss('token')(tree)[0].text self._shared_secret = csss('shared-secret')(tree)[0].text
def getAuthorizedConnectRequests(self): tree = self._send_request_and_get_tree( self._create_request('<info></info>', 'GetAuthorizedConnectRequests') ) reqs = [] for e in csss('connect-request')(tree): person_id = csss('person-id')(e)[0].text record_id = csss('record-id')(e)[0].text external_id = csss('external-id')(e)[0].text reqs.append((person_id, record_id, external_id)) return reqs
class HVConn(object): _user_auth_token = None _offline_person_id = None _auth_token = None _record_id = None _app_specific_record_id = None _shared_secret = None _private_key = None _version = '2.0.0.0' _language = 'en' _country = 'US' _ttl = '1800' person = HVPerson() def _now_in_iso(self): return datetime.datetime.utcnow().isoformat() def _init_private_key(self): self._private_key = RSA.construct(( long(settings.APP_PUBLIC_KEY, 16), long(65537), long(settings.APP_PRIVATE_KEY, 16) )) def _sign(self, data): signer = PKCS1_v1_5.new(self._private_key) return base64.encodestring(signer.sign(SHA.new(data))) def _send_request(self, payload): pass def _send_request_and_get_tree(self, payload): conn = httplib.HTTPSConnection(settings.HV_SERVICE_SERVER, 443) conn.putrequest('POST', '/platform/wildcat.ashx') conn.putheader('Content-Type', 'text/xml') conn.putheader('Content-Length', '%d' % len(payload)) conn.endheaders() logging.debug('\nsending:\n'+payload) try: conn.send(payload) except socket.error, v: if v[0] == 32: # Broken pipe conn.close() raise resp = conn.getresponse() if resp.status != 200: raise else: tree = etree.fromstring(resp.read()) logging.debug('\ngot:\n'+etree.tostring(tree, pretty_print=True)) if csss('code')(tree)[0].text != '0': # FIXME: the re-auth case raise ('_send_request_and_get_tree: non-zero return code ' 'Re-auth may be required.') else: return tree
def getGlucoseMeasurements(self): tree = self.getThings('879e7c04-4e8a-4707-9ad3-b054df467ce4') self.person.glucoses = [] for thing in csss('thing')(tree): date = csss('date')(thing)[0] time = csss('time')(thing)[0] y = int(csss('y')(date)[0].text) m = int(csss('m')(date)[0].text) d = int(csss('d')(date)[0].text) h = int(csss('h')(time)[0].text) min = int(csss('m')(time)[0].text) s = int(csss('s')(time)[0].text) dt = datetime.datetime(y, m, d, h, min, s).isoformat() g = float(csss('mmolPerL')(thing)[0].text) self.person.glucoses.append((dt, round(g, 2)))
def getWeightMeasurements(self): tree = self.getThings('3d34d87e-7fc1-4153-800f-f56592cb0d17') self.person.weights = [] # clear weights for id in [t.text for t in csss('thing-id')(tree)]: tree = self.getThingById(id) date = csss('date')(tree)[0] time = csss('time')(tree)[0] y = int(csss('y')(date)[0].text) m = int(csss('m')(date)[0].text) d = int(csss('d')(date)[0].text) h = int(csss('h')(time)[0].text) min = int(csss('m')(time)[0].text) s = int(csss('s')(time)[0].text) dt = datetime.datetime(y, m, d, h, min, s).isoformat() weight_in_kg = float(csss('kg')(tree)[0].text) self.person.weights.append((dt, round(weight_in_kg, 2)))
def getPersonInfo(self): # TODO: extract more record data # <record app-record-auth-action="NoActionRequired" # app-specific-record-id="218697" # auth-expires="9999-12-31T23:59:59.999Z" # date-created="2012-09-19T16:07:52.507Z" # date-updated="2012-09-24T19:22:00.877Z" display-name="Arjun" # id="f9982b79-4369-4357-8268-0b344941ab02" location-country="US" # max-size-bytes="4294967296" record-custodian="true" rel-name="Self" # rel-type="1" size-bytes="3167" state="Active"> tree = self._send_request_and_get_tree( self._create_request('<info></info>', 'GetPersonInfo') ) self.person.person_id = csss('person-id')(tree)[0].text self.person.name = csss('name')(tree)[0].text self.person.selected_record_id = \ csss('selected-record-id')(tree)[0].text self._record_id = self.person.selected_record_id
def createConnectRequest(self, external_id, friendly_name, secret_q, secret_a): info_tmpl = string.Template( '<info>' '<friendly-name>$FRIENDLY_NAME</friendly-name>' '<question>$QUESTION</question>' '<answer>$ANSWER</answer>' '<external-id>$EXTERNAL_ID</external-id>' '</info>') info = info_tmpl.substitute({ 'FRIENDLY_NAME': friendly_name, 'QUESTION': secret_q, 'ANSWER': secret_a, 'EXTERNAL_ID': external_id }) tree = self._send_request_and_get_tree( self._create_request(info, 'CreateConnectRequest') ) return csss('identity-code')(tree)[0].text