nightscout.py: move methods into class, initialize NightscoutApi in main

Changes all code which interacts with the nightscout api to
invoke it via a NightscoutApi object which is passed to it
and defined in the main, rather than having utility methods
in nightscout.py which rely on the global secret file state
of nightscout url/secret.
This commit is contained in:
James Woglom
2021-04-20 00:26:18 -04:00
parent 1efe532a2f
commit 4b8ddd0cec
8 changed files with 102 additions and 93 deletions
+8 -3
View File
@@ -9,11 +9,14 @@ from tconnectsync.api import TConnectApi
from tconnectsync.process import process_time_range
from tconnectsync.autoupdate import process_auto_update
from tconnectsync.check import check_login
from tconnectsync.nightscout import NightscoutApi
try:
from tconnectsync.secret import (
TCONNECT_EMAIL,
TCONNECT_PASSWORD
TCONNECT_PASSWORD,
NS_URL,
NS_SECRET
)
except Exception:
print('Unable to read secret.py')
@@ -49,15 +52,17 @@ def main():
tconnect = TConnectApi(TCONNECT_EMAIL, TCONNECT_PASSWORD)
nightscout = NightscoutApi(NS_URL, NS_SECRET)
if args.check_login:
return check_login(tconnect, time_start, time_end)
if args.auto_update:
print("Starting auto-update between", time_start, "and", time_end, "(PRETEND)" if args.pretend else "")
process_auto_update(tconnect, time_start, time_end, args.pretend)
process_auto_update(tconnect, nightscout, time_start, time_end, args.pretend)
else:
print("Processing data between", time_start, "and", time_end, "(PRETEND)" if args.pretend else "")
added = process_time_range(tconnect, time_start, time_end, args.pretend)
added = process_time_range(tconnect, nightscout, time_start, time_end, args.pretend)
print("Added", added, "items")
if __name__ == '__main__':
+2 -2
View File
@@ -12,7 +12,7 @@ from .secret import (
Performs the auto-update functionality. Runs indefinitely in a loop
until stopped (ctrl+c).
"""
def process_auto_update(tconnect, time_start, time_end, pretend):
def process_auto_update(tconnect, nightscout, time_start, time_end, pretend):
# Read from android api, find exact interval to cut down on API calls
# Refresh API token. If failure, die, have wrapper script re-run.
@@ -28,7 +28,7 @@ def process_auto_update(tconnect, time_start, time_end, pretend):
if pretend:
print('Would update now')
else:
added = process_time_range(tconnect, time_start, time_end, pretend)
added = process_time_range(tconnect, nightscout, time_start, time_end, pretend)
print('Added', added, 'items')
if last_event_index:
+10 -5
View File
@@ -1,7 +1,4 @@
from .nightscout import api_status
from .secret import PUMP_SERIAL_NUMBER
from .nightscout import NightscoutApi
"""
Attempts to authenticate with each t:connect API,
@@ -32,16 +29,24 @@ def check_login(tconnect, time_start, time_end):
summary = tconnect.android.user_profile()
print("Android user profile: %s" % summary)
from .secret import PUMP_SERIAL_NUMBER
event = tconnect.android.last_event_uploaded(PUMP_SERIAL_NUMBER)
print("\nAndroid last uploaded event: %s" % event)
except ImportError:
print("Error: Unable to load config file.")
except Exception as e:
print("Error occurred querying Android API: %s" % e)
errors += 1
print("\nLogging in to Nightscout...")
try:
status = api_status()
from .secret import NS_URL, NS_SECRET
status = NightscoutApi(NS_URL, NS_SECRET).api_status()
print("\nNightscout status: %s" % status)
except ImportError:
print("Error: Unable to load config file.")
except Exception as e:
print("Error occurred querying Nightscout API: %s" % e)
errors += 1
+67 -52
View File
@@ -6,64 +6,79 @@ import urllib.parse
from urllib.parse import urljoin
from .api.common import ApiException
from .parser.nightscout import ENTERED_BY
try:
from .secret import NS_URL, NS_SECRET, TIMEZONE_NAME
except Exception:
print('Unable to import Nightscout secrets from secret.py')
sys.exit(1)
# try:
# from .secret import NS_URL, NS_SECRET
# except Exception:
# print('Unable to import Nightscout secrets from secret.py')
# sys.exit(1)
class NightscoutApi:
def __init__(self, url, secret):
self.url = url
self.secret = secret
def upload_nightscout(ns_format, entity='treatments'):
upload = requests.post(urljoin(NS_URL, 'api/v1/' + entity + '?api_secret=' + NS_SECRET), json=ns_format, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
print("Nightscout upload status:", upload.status_code, upload.text)
def upload_entry(self, ns_format, entity='treatments'):
r = requests.post(urljoin(self.url, 'api/v1/' + entity + '?api_secret=' + self.secret), json=ns_format, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if r.status_code != 200:
raise ApiException(r.status_code, "Nightscout upload response: %s" % r.text)
def delete_nightscout(entity):
upload = requests.delete(urljoin(NS_URL, 'api/v1/' + entity + '?api_secret=' + NS_SECRET), json={}, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
print("Nightscout delete status:", upload.status_code, upload.text)
def delete_entry(self, entity):
r = requests.delete(urljoin(self.url, 'api/v1/' + entity + '?api_secret=' + self.secret), json={}, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if r.status_code != 200:
raise ApiException(r.status_code, "Nightscout delete response: %s" % r.text)
def put_nightscout(ns_format, entity):
upload = requests.put(urljoin(NS_URL, 'api/v1/' + entity + '?api_secret=' + NS_SECRET), json=ns_format, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
print("Nightscout put status:", upload.status_code, upload.text)
def put_entry(self, ns_format, entity):
r = requests.put(urljoin(self.url, 'api/v1/' + entity + '?api_secret=' + self.secret), json=ns_format, headers={
'Accept': 'application/json',
'Content-Type': 'application/json',
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if r.status_code != 200:
raise ApiException(r.status_code, "Nightscout put response: %s" % r.text)
def last_uploaded_nightscout_entry(eventType):
latest = requests.get(urljoin(NS_URL, 'api/v1/treatments?count=1&find[enteredBy]=' + urllib.parse.quote(ENTERED_BY) + '&find[eventType]=' + urllib.parse.quote(eventType) + '&ts=' + str(time.time())), headers={
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
j = latest.json()
if j and len(j) > 0:
return j[0]
return None
def last_uploaded_entry(self, eventType):
latest = requests.get(urljoin(self.url, 'api/v1/treatments?count=1&find[enteredBy]=' + urllib.parse.quote(ENTERED_BY) + '&find[eventType]=' + urllib.parse.quote(eventType) + '&ts=' + str(time.time())), headers={
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if latest.status_code != 200:
raise ApiException(latest.status_code, "Nightscout treatments response: %s" % latest.text)
def last_uploaded_nightscout_activity(activityType):
latest = requests.get(urljoin(NS_URL, 'api/v1/activity?find[enteredBy]=' + urllib.parse.quote(ENTERED_BY) + '&find[activityType]=' + urllib.parse.quote(activityType) + '&ts=' + str(time.time())), headers={
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
j = latest.json()
if j and len(j) > 0:
return j[0]
return None
j = latest.json()
if j and len(j) > 0:
return j[0]
return None
"""
Returns general status information about the Nightscout server.
"""
def api_status():
status = requests.get(urljoin(NS_URL, 'api/v1/status.json'), headers={
'api-secret': hashlib.sha1(NS_SECRET.encode()).hexdigest()
})
if status.status_code != 200:
raise Exception('HTTP error status code (%d) from Nightscout: %s' % (status.status_code, status.text))
return status.json()
def last_uploaded_activity(self, activityType):
latest = requests.get(urljoin(self.url, 'api/v1/activity?find[enteredBy]=' + urllib.parse.quote(ENTERED_BY) + '&find[activityType]=' + urllib.parse.quote(activityType) + '&ts=' + str(time.time())), headers={
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if latest.status_code != 200:
raise ApiException(latest.status_code, "Nightscout activity response: %s" % latest.text)
j = latest.json()
if j and len(j) > 0:
return j[0]
return None
"""
Returns general status information about the Nightscout server.
"""
def api_status(self):
status = requests.get(urljoin(self.url, 'api/v1/status.json'), headers={
'api-secret': hashlib.sha1(self.secret.encode()).hexdigest()
})
if status.status_code != 200:
raise Exception('HTTP error status code (%d) from Nightscout: %s' % (status.status_code, status.text))
return status.json()
+4 -5
View File
@@ -20,7 +20,7 @@ Given a TConnectApi object and start/end range, performs a single
cycle of synchronizing data within the time range.
If pretend is true, then doesn't actually write data to Nightscout.
"""
def process_time_range(tconnect, time_start, time_end, pretend):
def process_time_range(tconnect, nightscout, time_start, time_end, pretend):
print("Downloading t:connect ControlIQ data")
try:
ciqTherapyTimelineData = tconnect.controliq.therapy_timeline(time_start, time_end)
@@ -51,13 +51,12 @@ def process_time_range(tconnect, time_start, time_end, pretend):
if csvBasalData:
add_csv_basal_events(basalEvents, csvBasalData)
added += ns_write_basal_events(basalEvents, pretend=pretend)
added += ns_write_basal_events(nightscout, basalEvents, pretend=pretend)
bolusEvents = process_bolus_events(bolusData)
added += ns_write_bolus_events(bolusEvents, pretend=pretend)
added += ns_write_bolus_events(nightscout, bolusEvents, pretend=pretend)
iobEvents = process_iob_events(iobData)
added += ns_write_iob_events(iobEvents, pretend=pretend)
added += ns_write_iob_events(nightscout, iobEvents, pretend=pretend)
return added
+4 -9
View File
@@ -4,11 +4,6 @@ from ..parser.nightscout import (
BASAL_EVENTTYPE,
NightscoutEntry
)
from ..nightscout import (
last_uploaded_nightscout_entry,
put_nightscout,
upload_nightscout
)
from ..parser.tconnect import TConnectEntry
@@ -64,8 +59,8 @@ def add_csv_basal_events(basalEvents, data):
"""
Given processed basal data, adds basal events to Nightscout.
"""
def ns_write_basal_events(basalEvents, pretend=False):
last_upload = last_uploaded_nightscout_entry(BASAL_EVENTTYPE)
def ns_write_basal_events(nightscout, basalEvents, pretend=False):
last_upload = nightscout.last_uploaded_entry(BASAL_EVENTTYPE)
last_upload_time = None
if last_upload:
last_upload_time = arrow.get(last_upload["created_at"])
@@ -102,8 +97,8 @@ def ns_write_basal_events(basalEvents, pretend=False):
print("Replacing last uploaded entry:", last_upload)
if not pretend:
entry['_id'] = last_upload['_id']
put_nightscout(entry, entity='treatments')
nightscout.put_entry(entry, entity='treatments')
elif not pretend:
upload_nightscout(entry)
nightscout.upload_entry(entry)
return add_count
+3 -8
View File
@@ -4,11 +4,6 @@ from ..parser.nightscout import (
BOLUS_EVENTTYPE,
NightscoutEntry
)
from ..nightscout import (
last_uploaded_nightscout_entry,
put_nightscout,
upload_nightscout
)
from ..parser.tconnect import TConnectEntry
"""
@@ -35,8 +30,8 @@ def process_bolus_events(bolusdata):
"""
Given processed bolus data, adds bolus events to Nightscout.
"""
def ns_write_bolus_events(bolusEvents, pretend=False):
last_upload = last_uploaded_nightscout_entry(BOLUS_EVENTTYPE)
def ns_write_bolus_events(nightscout, bolusEvents, pretend=False):
last_upload = nightscout.last_uploaded_entry(BOLUS_EVENTTYPE)
last_upload_time = None
if last_upload:
last_upload_time = arrow.get(last_upload["created_at"])
@@ -60,6 +55,6 @@ def ns_write_bolus_events(bolusEvents, pretend=False):
print(" Processing bolus:", event, "entry:", entry)
if not pretend:
upload_nightscout(entry)
nightscout.upload_entry(entry)
return add_count
+4 -9
View File
@@ -4,11 +4,6 @@ from ..parser.nightscout import (
IOB_ACTIVITYTYPE,
NightscoutEntry
)
from ..nightscout import (
last_uploaded_nightscout_activity,
delete_nightscout,
upload_nightscout
)
from ..parser.tconnect import TConnectEntry
"""
@@ -26,8 +21,8 @@ def process_iob_events(iobdata):
"""
Given processed IOB data, creates a single Nightscout activity definition to store IOB.
"""
def ns_write_iob_events(iobEvents, pretend=False):
last_upload = last_uploaded_nightscout_activity(IOB_ACTIVITYTYPE)
def ns_write_iob_events(nightscout, iobEvents, pretend=False):
last_upload = nightscout.last_uploaded_activity(IOB_ACTIVITYTYPE)
last_upload_time = None
if last_upload:
last_upload_time = arrow.get(last_upload["created_at"])
@@ -49,12 +44,12 @@ def ns_write_iob_events(iobEvents, pretend=False):
print(" Processing iob:", event, "entry:", entry)
if not pretend:
upload_nightscout(entry, entity='activity')
nightscout.upload_entry(entry, entity='activity')
# Delete the previous activity
if last_upload and '_id' in last_upload:
print(" Deleting old iob entry:", last_upload)
if not pretend:
delete_nightscout('activity/{}'.format(last_upload['_id']))
nightscout.delete_entry('activity/{}'.format(last_upload['_id']))
return 1