mirror of
https://github.com/bckelley/tconnectsync.git
synced 2026-08-28 05:34:10 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dc479c84b | ||
|
|
0417fb9fd8 | ||
|
|
b80d52662b | ||
|
|
51ac469f00 | ||
|
|
81b13f236a | ||
|
|
d57b3872f1 | ||
|
|
0609a46ed2 | ||
|
|
e63d725c2b | ||
|
|
fec964e767 | ||
|
|
366182f65b | ||
|
|
d9d09dddb3 | ||
|
|
04643255fe | ||
|
|
c2f7070f3b | ||
|
|
9c35f850b9 | ||
|
|
a7383b0796 | ||
|
|
4f52927d2f | ||
|
|
5b938c010d | ||
|
|
3e50c7018d | ||
|
|
32f3639eb0 | ||
|
|
9a7cb1bdfd | ||
|
|
ead7ab883b | ||
|
|
ff395ffa3e | ||
|
|
8f2ad586fd |
@@ -18,57 +18,60 @@ jobs:
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install flake8 pytest pipenv
|
||||
pipenv install --system
|
||||
- name: Run pipenv check
|
||||
run: |
|
||||
# DDoS attacks in wheel and setuptools packages, not relevant
|
||||
# root certificate store, not relevant
|
||||
pipenv check \
|
||||
--ignore 51499 \
|
||||
--ignore 52495 \
|
||||
--ignore 52365 \
|
||||
--ignore 59956 \
|
||||
--ignore 58755 \
|
||||
--ignore 67895 \
|
||||
--ignore 61893 \
|
||||
--ignore 61601 \
|
||||
--ignore 62044 \
|
||||
--ignore 67599 \
|
||||
--ignore 72083 \
|
||||
--ignore 71064 \
|
||||
--ignore 71608 \
|
||||
--ignore 72236
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest
|
||||
- name: Check codecov configuration
|
||||
run: |
|
||||
curl -X POST --data-binary @.codecov.yml https://codecov.io/validate
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install flake8 pytest pipenv
|
||||
pipenv install --system
|
||||
- name: Run pipenv check
|
||||
run: |
|
||||
# DDoS attacks in wheel and setuptools packages, not relevant
|
||||
# root certificate store, not relevant
|
||||
pipenv check \
|
||||
--ignore 51499 \
|
||||
--ignore 52495 \
|
||||
--ignore 52365 \
|
||||
--ignore 59956 \
|
||||
--ignore 58755 \
|
||||
--ignore 67895 \
|
||||
--ignore 61893 \
|
||||
--ignore 61601 \
|
||||
--ignore 62044 \
|
||||
--ignore 67599 \
|
||||
--ignore 72083 \
|
||||
--ignore 71064 \
|
||||
--ignore 71608 \
|
||||
--ignore 72236
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
- name: Run tconnectsync --help
|
||||
run: |
|
||||
tconnectsync --help
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pytest
|
||||
- name: Check codecov configuration
|
||||
run: |
|
||||
curl -X POST --data-binary @.codecov.yml https://codecov.io/validate
|
||||
|
||||
if [[ "$(curl -s -o /dev/null -w "%{http_code}" -X POST --data-binary @.codecov.yml https://codecov.io/validate)" != "200" ]]; then
|
||||
echo Error parsing codecov file
|
||||
exit 1
|
||||
fi
|
||||
- name: Generate Coverage Report
|
||||
run: |
|
||||
pip install coverage
|
||||
coverage run -m unittest
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
if [[ "$(curl -s -o /dev/null -w "%{http_code}" -X POST --data-binary @.codecov.yml https://codecov.io/validate)" != "200" ]]; then
|
||||
echo Error parsing codecov file
|
||||
exit 1
|
||||
fi
|
||||
- name: Generate Coverage Report
|
||||
run: |
|
||||
pip install coverage
|
||||
coverage run -m unittest
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
fail_ci_if_error: false
|
||||
|
||||
@@ -17,10 +17,11 @@ pysocks = "*"
|
||||
urllib3 = "==1.26.6"
|
||||
requests = {extras = ["socks"], version = "==2.31.0"}
|
||||
requests-oidc = "*"
|
||||
pyjwt = "==2.8.0"
|
||||
PyJWT = "==2.8.0"
|
||||
cryptography = "*"
|
||||
dataclasses-json = "*"
|
||||
cffi = ">=1.15.1"
|
||||
typing-extensions = "*"
|
||||
|
||||
[scripts]
|
||||
tconnectsync = "python3 main.py"
|
||||
|
||||
Generated
+2
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "43ccd3f3cf27bb4b8b2c890cf45fd6af1f532ebc524a1db82700e8ad35625124"
|
||||
"sha256": "1d28c5104c37e390b88704d1453eec15e5c6df241ca85f82a88973f8aee2d1d1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -590,6 +590,7 @@
|
||||
"sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d",
|
||||
"sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.12.2"
|
||||
},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[metadata]
|
||||
name = tconnectsync
|
||||
version = 2.0.6
|
||||
version = 2.1.4
|
||||
author = James Woglom
|
||||
author_email = j@wogloms.net
|
||||
description = Syncs Tandem t:connect pump data to Nightscout for the t:slim X2
|
||||
description = Syncs Tandem Source (formerly t:connect) insulin pump data to Nightscout for the t:slim X2
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
url = https://github.com/jwoglom/tconnectsync
|
||||
@@ -30,10 +30,11 @@ install_requires =
|
||||
urllib3
|
||||
requests
|
||||
requests-oidc
|
||||
pyjwt
|
||||
PyJWT
|
||||
cryptography
|
||||
dataclasses-json
|
||||
cffi
|
||||
typing-extensions
|
||||
|
||||
[options.packages.find]
|
||||
where = .
|
||||
|
||||
@@ -4,6 +4,12 @@ import arrow
|
||||
import argparse
|
||||
import logging
|
||||
import pkg_resources
|
||||
import typing
|
||||
|
||||
# Required for cryptography lib in python 3.7
|
||||
if sys.version_info < (3, 8):
|
||||
import typing_extensions
|
||||
typing.Protocol = typing_extensions.Protocol
|
||||
|
||||
from .api import TConnectApi
|
||||
from .process import process_time_range
|
||||
@@ -111,13 +117,10 @@ def main(*args, **kwargs):
|
||||
|
||||
if args.auto_update:
|
||||
u = TandemSourceAutoupdate(secret)
|
||||
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)
|
||||
sys.exit(u.process(tconnect, nightscout, time_start, time_end, args.pretend, features=args.features))
|
||||
else:
|
||||
tconnectDevice = TandemSourceChooseDevice(secret, tconnect).choose()
|
||||
added = TandemSourceProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend=args.pretend, features=args.features).process(time_start, time_end)
|
||||
added, last_event_id = TandemSourceProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend=args.pretend, features=args.features).process(time_start, time_end)
|
||||
|
||||
# return exit code 0 if processed events
|
||||
sys.exit(0 if added>0 else 1)
|
||||
|
||||
@@ -38,4 +38,4 @@ class RawEvent:
|
||||
# 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)
|
||||
return arrow.get(TANDEM_EPOCH + self.timestampRaw, tzinfo='UTC').replace(tzinfo=TIMEZONE_NAME)
|
||||
|
||||
@@ -54,6 +54,7 @@ if not get('NS_SECRET') and get('API_SECRET'):
|
||||
NS_SKIP_TLS_VERIFY = get_bool('NS_SKIP_TLS_VERIFY', 'false')
|
||||
NS_IGNORE_CONN_ERRORS = get_bool('NS_IGNORE_CONN_ERRORS', 'false')
|
||||
|
||||
# This should be the timezone your pump is set to.
|
||||
TIMEZONE_NAME = get('TIMEZONE_NAME', 'America/New_York')
|
||||
|
||||
if not get('TIMEZONE_NAME') and get('TZ'):
|
||||
@@ -78,6 +79,7 @@ NIGHTSCOUT_PROFILE_UPLOAD_MODE = get_one_of('NIGHTSCOUT_PROFILE_UPLOAD_MODE', 'a
|
||||
# Default Nightscout profile segment fields which aren't stored by Tandem
|
||||
NIGHTSCOUT_PROFILE_CARBS_HR_VALUE = get('NIGHTSCOUT_PROFILE_CARBS_HR_VALUE', '20')
|
||||
NIGHTSCOUT_PROFILE_DELAY_VALUE = get('NIGHTSCOUT_PROFILE_DELAY_VALUE', '20')
|
||||
IGNORE_ZERO_UNIT_BASAL = get_bool('IGNORE_ZERO_UNIT_BASAL', 'false')
|
||||
|
||||
ENABLE_TESTING_MODES = get_bool('ENABLE_TESTING_MODES', 'false')
|
||||
SKIP_NS_LAST_UPLOADED_CHECK = get_bool('SKIP_NS_LAST_UPLOADED_CHECK', 'false')
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
from ...features import DEFAULT_FEATURES
|
||||
from .choose_device import ChooseDevice
|
||||
from .process import ProcessTimeRange
|
||||
from ... import secret
|
||||
|
||||
import datetime
|
||||
|
||||
def run_oneshot(tconnect, nightscout, pretend=False, features=DEFAULT_FEATURES, secret_arg=None, time_start=None, time_end=None):
|
||||
if not time_start and not time_end:
|
||||
time_end = datetime.datetime.now()
|
||||
time_start = time_end - datetime.timedelta(days=1)
|
||||
|
||||
if not secret_arg:
|
||||
secret_arg = secret
|
||||
|
||||
tconnectDevice = ChooseDevice(secret_arg, tconnect).choose()
|
||||
return ProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend, features).process(time_start, time_end)
|
||||
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
import arrow
|
||||
|
||||
from ...secret import IGNORE_ZERO_UNIT_BASAL
|
||||
from ...features import DEFAULT_FEATURES
|
||||
from ... import features
|
||||
from ...eventparser.generic import Events, decode_raw_events, EVENT_LEN
|
||||
@@ -54,7 +55,9 @@ class ProcessBasal:
|
||||
|
||||
ns_entries = []
|
||||
for item in with_duration:
|
||||
ns_entries.append(self.basal_to_nsentry(*item))
|
||||
ns = self.basal_to_nsentry(*item)
|
||||
if ns:
|
||||
ns_entries.append(ns)
|
||||
|
||||
return ns_entries
|
||||
|
||||
@@ -73,16 +76,24 @@ class ProcessBasal:
|
||||
|
||||
def basal_to_nsentry(self, start, duration, event):
|
||||
if type(event) == eventtypes.LidBasalRateChange:
|
||||
value = insulin_float_round(event.commandedbasalrate)
|
||||
if IGNORE_ZERO_UNIT_BASAL and value < 0.01:
|
||||
logger.info("Ignoring basal entry with %.2f unit basal because IGNORE_ZERO_UNIT_BASAL=true: %s" % (value, event))
|
||||
return None
|
||||
return NightscoutEntry.basal(
|
||||
value = insulin_float_round(event.commandedbasalrate),
|
||||
value = value,
|
||||
duration_mins = duration.seconds / 60,
|
||||
created_at = start.format(),
|
||||
reason = ', '.join(bitmask_to_list(event.changetype)),
|
||||
pump_event_id = "%s" % event.eventId
|
||||
)
|
||||
if type(event) == eventtypes.LidBasalDelivery:
|
||||
value = insulin_milliunits_to_real(event.commandedRate)
|
||||
if IGNORE_ZERO_UNIT_BASAL and value < 0.01:
|
||||
logger.info("Ignoring basal entry with %.2f unit basal because IGNORE_ZERO_UNIT_BASAL=true: %s" % (value, event))
|
||||
return None
|
||||
return NightscoutEntry.basal(
|
||||
value = insulin_milliunits_to_real(event.commandedRate),
|
||||
value = value,
|
||||
duration_mins = duration.seconds / 60,
|
||||
created_at = start.format(),
|
||||
reason = ', '.join(bitmask_to_list(event.commandedRateSource)),
|
||||
|
||||
@@ -198,13 +198,13 @@ class ProcessUserMode:
|
||||
if start.exercisechoice == eventtypes.LidAaUserModeChange.ExercisechoiceEnum.Timed:
|
||||
reason = "Exercise (Timed)"
|
||||
|
||||
duration_mins = (time_end.eventTimestamp - start.eventTimestamp).seconds / 60
|
||||
duration_mins = (time_end - start.eventTimestamp).seconds / 60
|
||||
return NightscoutEntry.activity(
|
||||
created_at=start.eventTimestamp.format(),
|
||||
reason=reason + " - " + NOT_ENDED,
|
||||
duration=duration_mins,
|
||||
event_type=EXERCISE_EVENTTYPE,
|
||||
pump_event_id = "%s,%s" % (start.eventId, stop.eventId)
|
||||
pump_event_id = "%s" % start.eventId
|
||||
)
|
||||
|
||||
def process_unended_sleep_stop(self, event, sleep_last_upload):
|
||||
|
||||
Reference in New Issue
Block a user