Skip to content

Instantly share code, notes, and snippets.

@alisterburt
Last active December 12, 2022 12:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alisterburt/15280eae3d03ccb28e45713c3e10aeed to your computer and use it in GitHub Desktop.
Save alisterburt/15280eae3d03ccb28e45713c3e10aeed to your computer and use it in GitHub Desktop.
xbar nightscout plugin
#!/Users/alisterburt/mambaforge/envs/py/bin/python
from datetime import datetime
import requests
import timeago
from pydantic import BaseModel, validator
from pytz import timezone
NIGHTSCOUT_URL = "https://ab-nightscout.undo.cl/"
ENDPOINT = "api/v1/entries"
TIMEZONE = 'Europe/London'
ARROWS = {
'Flat': '→',
'SingleUp': '↑',
'FortyFiveUp': '↗',
'FortyFiveDown': '↘',
'SingleDown': '↓',
}
request_url = NIGHTSCOUT_URL + ENDPOINT
response = requests.get(request_url, timeout=5)
if not response.ok:
print('bad request')
exit(0)
class NightscoutEntry(BaseModel):
time: datetime
blood_glucose: float
trend: str
source: str
@validator('trend', 'source')
def remove_quotes(cls, value):
return value.strip('"')
@property
def trend_arrow(self):
return ARROWS.get(self.trend, self.trend)
@property
def value_trend_string(self):
return f'{self.blood_glucose} {self.trend_arrow}'
@property
def local_time(self):
return self.time.astimezone(tz=timezone(TIMEZONE))
@property
def local_time_string(self):
return self.local_time.strftime('%H:%M')
@property
def time_ago_string(self):
now = datetime.now(tz=timezone('UTC'))
return timeago.format(self.time, now)
@property
def summary(self):
bg = self.blood_glucose
entry_time = self.local_time_string
time_ago = self.time_ago_string
return f'{bg} @ {entry_time} ({time_ago})'
@classmethod
def from_item(cls, item: str):
_, time, blood_glucose, trend, source = item.split('\t')
return cls(
time=time, blood_glucose=blood_glucose, trend=trend, source=source
)
entries = [
NightscoutEntry.from_item(item)
for item
in response.text.split('\n')
]
# entries = list(filter(lambda entry: 'xDrip' in entry.source, entries))
# xbar section
nightscout_link = f'View on Nightscout | href={NIGHTSCOUT_URL}'
# is the last entry up to date?
current_entry = entries[0]
last_entry = entries[1]
now = datetime.now().astimezone(tz=timezone(TIMEZONE))
time_since_last_entry = now - current_entry.time
seconds_since_last_entry = time_since_last_entry.total_seconds()
seconds_since_last_entry_threshold = 15 * 60
entry_is_outdated = seconds_since_last_entry > seconds_since_last_entry_threshold
# calculate rate of change
d_bg = current_entry.blood_glucose - last_entry.blood_glucose
dt = current_entry.time - last_entry.time
dt_minutes = dt.total_seconds() / 60
delta_bg_mg_dl_per_minute = d_bg / dt_minutes
delta_str = f'(Δ{delta_bg_mg_dl_per_minute:.1f})'
if -1 < delta_bg_mg_dl_per_minute < 1:
trend = ARROWS['Flat']
elif 1 <= delta_bg_mg_dl_per_minute < 2:
trend = ARROWS['FortyFiveUp']
elif delta_bg_mg_dl_per_minute >= 2:
trend = ARROWS['SingleUp']
elif -2 < delta_bg_mg_dl_per_minute <= -1:
trend = ARROWS['FortyFiveDown']
elif delta_bg_mg_dl_per_minute <= -2:
trend = ARROWS['SingleDown']
else:
trend = delta_str
if entry_is_outdated:
main_item = current_entry.summary
else:
main_item = f'{current_entry.blood_glucose:.0f} {trend} {delta_str}'
summaries = '\n'.join(entry.summary for entry in entries)
xbar_string = f"""{main_item}
---
{summaries}
{nightscout_link}"""
print(xbar_string)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment