mirror of
https://github.com/jwoglom/tconnectsync.git
synced 2026-08-25 10:13:40 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae26102df2 | ||
|
|
152c263fe0 | ||
|
|
38c933a257 | ||
|
|
d507e47e7a | ||
|
|
8c2f41c2d5 | ||
|
|
018c6d2228 | ||
|
|
32ba49dc8a | ||
|
|
a5cbc5d612 | ||
|
|
ef515021cc | ||
|
|
4af54bf7cb |
@@ -17,7 +17,7 @@ pysocks = "*"
|
||||
urllib3 = "==1.26.6"
|
||||
requests = {extras = ["socks"], version = "==2.31.0"}
|
||||
requests-oidc = "*"
|
||||
pyjwt = "*"
|
||||
pyjwt = "==2.8.0"
|
||||
cryptography = "*"
|
||||
dataclasses-json = "*"
|
||||
cffi = ">=1.15.1"
|
||||
|
||||
Generated
+5
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "74ba9aa4c7c93f3533b986f868b63bea54995dbd8d37bde4745bc9023de66dc7"
|
||||
"sha256": "43ccd3f3cf27bb4b8b2c890cf45fd6af1f532ebc524a1db82700e8ad35625124"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -471,12 +471,12 @@
|
||||
},
|
||||
"pyjwt": {
|
||||
"hashes": [
|
||||
"sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850",
|
||||
"sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"
|
||||
"sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de",
|
||||
"sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.9.0"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.8.0"
|
||||
},
|
||||
"pypng": {
|
||||
"hashes": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = tconnectsync
|
||||
version = 2.0.2
|
||||
version = 2.0.5
|
||||
author = James Woglom
|
||||
author_email = j@wogloms.net
|
||||
description = Syncs Tandem t:connect pump data to Nightscout for the t:slim X2
|
||||
|
||||
@@ -111,9 +111,14 @@ def main(*args, **kwargs):
|
||||
|
||||
if args.auto_update:
|
||||
u = TandemSourceAutoupdate(secret)
|
||||
sys.exit(u.process(tconnect, nightscout, time_start, time_end, args.pretend, features=args.features))
|
||||
changed, last_event_id = u.process(tconnect, nightscout, time_start, time_end, args.pretend, features=args.features)
|
||||
|
||||
# return exit code 0 if processed events
|
||||
sys.exit(0 if changed>0 else 1)
|
||||
else:
|
||||
tconnectDevice = TandemSourceChooseDevice(secret, tconnect).choose()
|
||||
added = TandemSourceProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend=args.pretend, features=args.features).process(time_start, time_end)
|
||||
sys.exit(added)
|
||||
|
||||
# return exit code 0 if processed events
|
||||
sys.exit(0 if added>0 else 1)
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import struct
|
||||
import arrow
|
||||
|
||||
from ..secret import TIMEZONE_NAME
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
EVENT_LEN = 26
|
||||
@@ -29,7 +31,11 @@ class RawEvent:
|
||||
seqNum = seqNum,
|
||||
raw = raw
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def timestamp(self):
|
||||
return arrow.get(TANDEM_EPOCH + self.timestampRaw)
|
||||
# Event timestamps do not have TZ data attached to them when parsed,
|
||||
# but represent the user's time zone setting. So we keep the time
|
||||
# referenced on them, but force the timezone to what the user
|
||||
# requests via the TZ secret.
|
||||
return arrow.get(TANDEM_EPOCH + self.timestampRaw, tzinfo=TIMEZONE_NAME)
|
||||
|
||||
@@ -18,6 +18,7 @@ class TandemSourceAutoupdate:
|
||||
self.last_max_date_with_events = None
|
||||
self.last_event_time = 0
|
||||
self.last_attempt_time = 0
|
||||
self.last_event_index = None
|
||||
self.time_diffs_between_attempts = []
|
||||
self.time_diffs_between_updates = []
|
||||
|
||||
@@ -41,15 +42,17 @@ class TandemSourceAutoupdate:
|
||||
|
||||
tconnectDevice = ChooseDevice(self.secret, tconnect).choose()
|
||||
|
||||
cur_max_date_with_events = arrow.get(tconnectDevice['maxDateWithEvents'])
|
||||
if not self.last_max_date_with_events or cur_max_date_with_events > self.cur_max_date_with_events:
|
||||
event_id = None
|
||||
cur_max_date_with_events = arrow.get(tconnectDevice['maxDateWithEvents']).float_timestamp
|
||||
if not self.last_max_date_with_events or cur_max_date_with_events > self.last_max_date_with_events:
|
||||
logger.info('New reported tandemsource data. (cur_max_date: %s last_max_date: %s)' % (cur_max_date_with_events, self.last_max_date_with_events))
|
||||
|
||||
if pretend:
|
||||
logger.info('Would update now if not in pretend mode')
|
||||
else:
|
||||
added = ProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend, features=features).process(time_start, time_end)
|
||||
added, event_id = ProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend, features=features).process(time_start, time_end)
|
||||
logger.info('Added %d items from ProcessTimeRange' % added)
|
||||
self.last_successful_process_time_range = now
|
||||
|
||||
# Track the time it took to find a new event between runs,
|
||||
# but skip this calculation the first process cycle (since
|
||||
@@ -59,8 +62,10 @@ class TandemSourceAutoupdate:
|
||||
logger.debug('Updating tracking of time since last update: %s' % self.time_diffs_between_updates)
|
||||
|
||||
# Mark the last event index uploaded from the pump and timestamp
|
||||
if event_id:
|
||||
self.last_event_index = event_id
|
||||
self.last_event_time = now
|
||||
self.last_max_date_with_events = cur_max_date_with_events
|
||||
self.last_event_time = now
|
||||
self.last_attempt_time = now
|
||||
self.time_diffs_between_attempts = []
|
||||
else:
|
||||
|
||||
@@ -55,14 +55,18 @@ class ProcessTimeRange:
|
||||
|
||||
events_first_time = None
|
||||
events_last_time = None
|
||||
last_event_id = None # aka seqnum
|
||||
for_eventclass = collections.defaultdict(list)
|
||||
for event in events:
|
||||
if not events_first_time:
|
||||
events_first_time = event.eventTimestamp
|
||||
if not events_last_time:
|
||||
events_last_time = event.eventTimestamp
|
||||
if not last_event_id:
|
||||
last_event_id = event.eventId
|
||||
events_first_time = min(events_first_time, event.eventTimestamp)
|
||||
events_last_time = max(events_last_time, event.eventTimestamp)
|
||||
last_event_id = max(event.eventId, last_event_id)
|
||||
|
||||
clazz = EventClass.for_event(event)
|
||||
if clazz:
|
||||
@@ -91,6 +95,6 @@ class ProcessTimeRange:
|
||||
else:
|
||||
logger.info("Skipping %s, is not enabled from features %s" % (updater_class.__name__, self.features))
|
||||
|
||||
logger.info("Processed %d events" % processed_count)
|
||||
return processed_count
|
||||
logger.info("Processed %d events. Last event ID seen: %d" % (processed_count, last_event_id))
|
||||
return processed_count, last_event_id
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ class ProcessAlarm:
|
||||
|
||||
ns_entries = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping Alarm event before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
logger.info("Skipping Alarm event not after last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
ns_entries.append(self.alarm_to_nsentry(event))
|
||||
|
||||
@@ -36,13 +36,17 @@ class ProcessBasal:
|
||||
|
||||
with_duration = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping basal event before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
logger.info("Skipping basal event not after last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
with_duration.append([event.eventTimestamp, None, event])
|
||||
|
||||
if not with_duration:
|
||||
logger.info("No basal events found to process")
|
||||
return []
|
||||
|
||||
for i in range(len(with_duration)-1):
|
||||
with_duration[i][1] = with_duration[i+1][0] - with_duration[i][0]
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ class ProcessBasalResume:
|
||||
|
||||
ns_entries = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping BasalResume event before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
logger.info("Skipping BasalResume event not after last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
ns_entries.append(self.resume_to_nsentry(event))
|
||||
|
||||
@@ -35,9 +35,9 @@ class ProcessBasalSuspension:
|
||||
|
||||
ns_entries = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping basalsuspension event before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
logger.info("Skipping basalsuspension event not after last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
ns_entries.append(self.suspension_to_nsentry(event))
|
||||
|
||||
@@ -44,7 +44,7 @@ class ProcessBolus:
|
||||
bolusEventsForId[event.bolusid][type(event)] = event
|
||||
|
||||
if type(event) == eventtypes.LidBolusCompleted:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping bolusCompletedEvent before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
@@ -37,9 +37,9 @@ class ProcessCartridge:
|
||||
cannulaFilledEvents = []
|
||||
tubingFilledEvents = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping %s before last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
logger.info("Skipping %s not after last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
continue
|
||||
|
||||
if type(event) == eventtypes.LidCartridgeFilled:
|
||||
|
||||
@@ -35,9 +35,9 @@ class ProcessCGMAlert:
|
||||
|
||||
alertEvents = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("Skipping %s before last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
logger.info("Skipping %s not after last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
continue
|
||||
|
||||
alertEvents.append(event)
|
||||
|
||||
@@ -38,9 +38,9 @@ class ProcessCGMReading:
|
||||
|
||||
readings = []
|
||||
for event in sorted(events, key=lambda x: self.timestamp_for(x)):
|
||||
if last_upload_time and self.timestamp_for(event) < last_upload_time:
|
||||
if last_upload_time and self.timestamp_for(event) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("ProcessCGMReading: Skipping %s before last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
logger.info("ProcessCGMReading: Skipping %s not after last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
continue
|
||||
|
||||
readings.append(event)
|
||||
|
||||
@@ -48,9 +48,9 @@ class ProcessCGMStartJoinStop:
|
||||
|
||||
allEvents = []
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("ProcessCGMStartJoinStop: Skipping %s before last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
logger.info("ProcessCGMStartJoinStop: Skipping %s not after last upload time: %s (time range: %s - %s)" % (type(event), event, time_start, time_end))
|
||||
continue
|
||||
|
||||
allEvents.append(event)
|
||||
|
||||
@@ -72,9 +72,9 @@ class ProcessUserMode:
|
||||
start_sleep = None
|
||||
start_exercise = None
|
||||
for event in sorted(events, key=lambda x: x.eventTimestamp):
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) < last_upload_time:
|
||||
if last_upload_time and arrow.get(event.eventTimestamp) <= last_upload_time:
|
||||
if self.pretend:
|
||||
logger.info("ProcessUserMode: Skipping usermode event before last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
logger.info("ProcessUserMode: Skipping usermode event not after last upload time: %s (time range: %s - %s)" % (event, time_start, time_end))
|
||||
continue
|
||||
|
||||
if self.is_start_sleep(event):
|
||||
|
||||
Reference in New Issue
Block a user