mirror of
https://github.com/jwoglom/tconnectsync.git
synced 2026-08-25 10:13:40 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0609a46ed2 | ||
|
|
e63d725c2b | ||
|
|
fec964e767 | ||
|
|
366182f65b | ||
|
|
d9d09dddb3 | ||
|
|
04643255fe | ||
|
|
c2f7070f3b | ||
|
|
9c35f850b9 | ||
|
|
a7383b0796 | ||
|
|
4f52927d2f | ||
|
|
5b938c010d | ||
|
|
3e50c7018d | ||
|
|
32f3639eb0 | ||
|
|
9a7cb1bdfd | ||
|
|
ead7ab883b | ||
|
|
ff395ffa3e | ||
|
|
8f2ad586fd | ||
|
|
828cccaf10 | ||
|
|
ae26102df2 | ||
|
|
152c263fe0 | ||
|
|
38c933a257 | ||
|
|
d507e47e7a | ||
|
|
8c2f41c2d5 | ||
|
|
018c6d2228 | ||
|
|
32ba49dc8a | ||
|
|
a5cbc5d612 | ||
|
|
ef515021cc | ||
|
|
4af54bf7cb | ||
|
|
d9d1b8a8fb | ||
|
|
29ed755356 | ||
|
|
b862ea9d0d | ||
|
|
2677fc86be | ||
|
|
1ae40e3cdb | ||
|
|
90c63c8211 | ||
|
|
60c2e08dcf | ||
|
|
d6f08c61b8 | ||
|
|
784387dcb8 | ||
|
|
84092e1de6 | ||
|
|
bb3094869d | ||
|
|
ec497d7d00 |
@@ -15,60 +15,63 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.7', '3.8', '3.9', '3.10']
|
||||
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
|
||||
|
||||
@@ -9,17 +9,19 @@ ptpython = "*"
|
||||
[packages]
|
||||
tconnectsync = {path = "."}
|
||||
bs4 = "*"
|
||||
arrow = "*"
|
||||
arrow = "==1.2.3"
|
||||
lxml = "*"
|
||||
python-dotenv = "*"
|
||||
python-dotenv = "==0.21.1"
|
||||
requests-mock = "*"
|
||||
pysocks = "*"
|
||||
urllib3 = "==1.26.6"
|
||||
requests = {extras = ["socks"], version = "*"}
|
||||
requests = {extras = ["socks"], version = "==2.31.0"}
|
||||
requests-oidc = "*"
|
||||
pyjwt = "*"
|
||||
PyJWT = "==2.8.0"
|
||||
cryptography = "*"
|
||||
dataclasses-json = "*"
|
||||
cffi = ">=1.15.1"
|
||||
typing-extensions = "*"
|
||||
|
||||
[scripts]
|
||||
tconnectsync = "python3 main.py"
|
||||
|
||||
Generated
+20
-26
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "586b477d4c73da1d1034f852a536bf3c20a1a358406bfb5dfc1b1164f606441b"
|
||||
"sha256": "1d28c5104c37e390b88704d1453eec15e5c6df241ca85f82a88973f8aee2d1d1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -16,12 +16,12 @@
|
||||
"default": {
|
||||
"arrow": {
|
||||
"hashes": [
|
||||
"sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80",
|
||||
"sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"
|
||||
"sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1",
|
||||
"sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.3.0"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.2.3"
|
||||
},
|
||||
"beautifulsoup4": {
|
||||
"hashes": [
|
||||
@@ -117,7 +117,8 @@
|
||||
"sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87",
|
||||
"sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"
|
||||
],
|
||||
"markers": "platform_python_implementation != 'PyPy'",
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.17.1"
|
||||
},
|
||||
"charset-normalizer": {
|
||||
@@ -470,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": [
|
||||
@@ -504,12 +505,12 @@
|
||||
},
|
||||
"python-dotenv": {
|
||||
"hashes": [
|
||||
"sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca",
|
||||
"sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"
|
||||
"sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49",
|
||||
"sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==1.0.1"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.21.1"
|
||||
},
|
||||
"qrcode": {
|
||||
"hashes": [
|
||||
@@ -524,11 +525,11 @@
|
||||
"socks"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
|
||||
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
|
||||
"sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f",
|
||||
"sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.32.3"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.31.0"
|
||||
},
|
||||
"requests-mock": {
|
||||
"hashes": [
|
||||
@@ -584,19 +585,12 @@
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.9.4"
|
||||
},
|
||||
"types-python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:27c8cc2d058ccb14946eebcaaa503088f4f6dbc4fb6093d3d456a49aef2753f6",
|
||||
"sha256:9706c3b68284c25adffc47319ecc7947e5bb86b3773f843c73906fd598bc176e"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.9.0.20240906"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"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.0
|
||||
version = 2.1.1
|
||||
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
|
||||
@@ -25,6 +25,16 @@ install_requires =
|
||||
arrow
|
||||
lxml
|
||||
python-dotenv
|
||||
requests-mock
|
||||
pysocks
|
||||
urllib3
|
||||
requests
|
||||
requests-oidc
|
||||
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
|
||||
@@ -114,6 +120,8 @@ def main(*args, **kwargs):
|
||||
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)
|
||||
sys.exit(added)
|
||||
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)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ def parse_date(date):
|
||||
|
||||
def parse_ymd_date(date):
|
||||
if type(date) == str:
|
||||
return date
|
||||
date = arrow.get(date)
|
||||
return (date or datetime.datetime.now()).strftime('%Y-%m-%d')
|
||||
|
||||
def parsed_date_to_arrow(date):
|
||||
@@ -122,11 +122,11 @@ def split_days_range(start_a, end_a, days: int = 5) -> List[Tuple[str, str]]:
|
||||
if (cur - cur_s).days >= days-1:
|
||||
ranges.append((cur_s, cur))
|
||||
cur_s = cur + datetime.timedelta(days=1)
|
||||
|
||||
|
||||
cur += datetime.timedelta(days=1)
|
||||
if len(ranges) > 0 and (end - ranges[-1][-1]).days > 0:
|
||||
ranges.append((cur_s, end))
|
||||
|
||||
|
||||
return ranges
|
||||
|
||||
class ApiException(Exception):
|
||||
|
||||
@@ -58,7 +58,8 @@ class LidBasalRateChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def changetype(self):
|
||||
try: return self.ChangetypeBitmask(self.changetypeRaw)
|
||||
try:
|
||||
return self.ChangetypeBitmask(self.changetypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid changetypeRaw in ChangetypeBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -235,7 +236,8 @@ class LidAlertActivated(BaseEvent):
|
||||
|
||||
@property
|
||||
def alertid(self):
|
||||
try: return self.AlertidEnum(self.alertidRaw)
|
||||
try:
|
||||
return self.AlertidEnum(self.alertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid alertidRaw in Alertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -412,7 +414,8 @@ class LidAlarmActivated(BaseEvent):
|
||||
|
||||
@property
|
||||
def alarmid(self):
|
||||
try: return self.AlarmidEnum(self.alarmidRaw)
|
||||
try:
|
||||
return self.AlarmidEnum(self.alarmidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid alarmidRaw in Alarmid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -506,7 +509,8 @@ class LidPumpingSuspended(BaseEvent):
|
||||
|
||||
@property
|
||||
def suspendreason(self):
|
||||
try: return self.SuspendreasonEnum(self.suspendreasonRaw)
|
||||
try:
|
||||
return self.SuspendreasonEnum(self.suspendreasonRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid suspendreasonRaw in Suspendreason for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -662,7 +666,8 @@ class LidBgReadingTaken(BaseEvent):
|
||||
|
||||
@property
|
||||
def selectediob(self):
|
||||
try: return self.SelectediobEnum(self.selectediobRaw)
|
||||
try:
|
||||
return self.SelectediobEnum(self.selectediobRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid selectediobRaw in Selectediob for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -679,7 +684,8 @@ class LidBgReadingTaken(BaseEvent):
|
||||
|
||||
@property
|
||||
def bgentrytype(self):
|
||||
try: return self.BgentrytypeEnum(self.bgentrytypeRaw)
|
||||
try:
|
||||
return self.BgentrytypeEnum(self.bgentrytypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bgentrytypeRaw in Bgentrytype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -696,7 +702,8 @@ class LidBgReadingTaken(BaseEvent):
|
||||
|
||||
@property
|
||||
def bgsourcetype(self):
|
||||
try: return self.BgsourcetypeEnum(self.bgsourcetypeRaw)
|
||||
try:
|
||||
return self.BgsourcetypeEnum(self.bgsourcetypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bgsourcetypeRaw in Bgsourcetype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -713,7 +720,8 @@ class LidBgReadingTaken(BaseEvent):
|
||||
|
||||
@property
|
||||
def cgmcalibration(self):
|
||||
try: return self.CgmcalibrationEnum(self.cgmcalibrationRaw)
|
||||
try:
|
||||
return self.CgmcalibrationEnum(self.cgmcalibrationRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid cgmcalibrationRaw in Cgmcalibration for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -786,7 +794,8 @@ class LidBolusCompleted(BaseEvent):
|
||||
|
||||
@property
|
||||
def completionstatus(self):
|
||||
try: return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
try:
|
||||
return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid completionstatusRaw in Completionstatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -853,7 +862,8 @@ class LidBolexCompleted(BaseEvent):
|
||||
|
||||
@property
|
||||
def completionstatus(self):
|
||||
try: return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
try:
|
||||
return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid completionstatusRaw in Completionstatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1028,7 +1038,8 @@ class LidAlertCleared(BaseEvent):
|
||||
|
||||
@property
|
||||
def alertid(self):
|
||||
try: return self.AlertidEnum(self.alertidRaw)
|
||||
try:
|
||||
return self.AlertidEnum(self.alertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid alertidRaw in Alertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1198,7 +1209,8 @@ class LidAlarmCleared(BaseEvent):
|
||||
|
||||
@property
|
||||
def alarmid(self):
|
||||
try: return self.AlarmidEnum(self.alarmidRaw)
|
||||
try:
|
||||
return self.AlarmidEnum(self.alarmidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid alarmidRaw in Alarmid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1319,7 +1331,8 @@ class LidBolusActivated(BaseEvent):
|
||||
|
||||
@property
|
||||
def selectediob(self):
|
||||
try: return self.SelectediobEnum(self.selectediobRaw)
|
||||
try:
|
||||
return self.SelectediobEnum(self.selectediobRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid selectediobRaw in Selectediob for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1372,7 +1385,8 @@ class LidBolexActivated(BaseEvent):
|
||||
|
||||
@property
|
||||
def selectediob(self):
|
||||
try: return self.SelectediobEnum(self.selectediobRaw)
|
||||
try:
|
||||
return self.SelectediobEnum(self.selectediobRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid selectediobRaw in Selectediob for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1458,7 +1472,8 @@ class LidCannulaFilled(BaseEvent):
|
||||
|
||||
@property
|
||||
def completionstatus(self):
|
||||
try: return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
try:
|
||||
return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid completionstatusRaw in Completionstatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1510,7 +1525,8 @@ class LidTubingFilled(BaseEvent):
|
||||
|
||||
@property
|
||||
def completionstatus(self):
|
||||
try: return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
try:
|
||||
return self.CompletionstatusEnum(self.completionstatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid completionstatusRaw in Completionstatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1568,7 +1584,8 @@ class LidBolusRequestedMsg1(BaseEvent):
|
||||
|
||||
@property
|
||||
def bolustype(self):
|
||||
try: return self.BolustypeEnum(self.bolustypeRaw)
|
||||
try:
|
||||
return self.BolustypeEnum(self.bolustypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bolustypeRaw in Bolustype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1585,7 +1602,8 @@ class LidBolusRequestedMsg1(BaseEvent):
|
||||
|
||||
@property
|
||||
def correctionbolusincluded(self):
|
||||
try: return self.CorrectionbolusincludedEnum(self.correctionbolusincludedRaw)
|
||||
try:
|
||||
return self.CorrectionbolusincludedEnum(self.correctionbolusincludedRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid correctionbolusincludedRaw in Correctionbolusincluded for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1653,7 +1671,8 @@ class LidBolusRequestedMsg2(BaseEvent):
|
||||
|
||||
@property
|
||||
def selectediob(self):
|
||||
try: return self.SelectediobEnum(self.selectediobRaw)
|
||||
try:
|
||||
return self.SelectediobEnum(self.selectediobRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid selectediobRaw in Selectediob for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1682,7 +1701,8 @@ class LidBolusRequestedMsg2(BaseEvent):
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
try: return self.OptionsEnum(self.optionsRaw)
|
||||
try:
|
||||
return self.OptionsEnum(self.optionsRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid optionsRaw in Options for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1699,7 +1719,8 @@ class LidBolusRequestedMsg2(BaseEvent):
|
||||
|
||||
@property
|
||||
def useroverride(self):
|
||||
try: return self.UseroverrideEnum(self.useroverrideRaw)
|
||||
try:
|
||||
return self.UseroverrideEnum(self.useroverrideRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid useroverrideRaw in Useroverride for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1716,7 +1737,8 @@ class LidBolusRequestedMsg2(BaseEvent):
|
||||
|
||||
@property
|
||||
def declinedcorrection(self):
|
||||
try: return self.DeclinedcorrectionEnum(self.declinedcorrectionRaw)
|
||||
try:
|
||||
return self.DeclinedcorrectionEnum(self.declinedcorrectionRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid declinedcorrectionRaw in Declinedcorrection for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1901,7 +1923,8 @@ class LidPlgsPeriodic(BaseEvent):
|
||||
|
||||
@property
|
||||
def fmrstatus(self):
|
||||
try: return self.FmrstatusEnum(self.fmrstatusRaw)
|
||||
try:
|
||||
return self.FmrstatusEnum(self.fmrstatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid fmrstatusRaw in Fmrstatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1918,7 +1941,8 @@ class LidPlgsPeriodic(BaseEvent):
|
||||
|
||||
@property
|
||||
def pgvvalid(self):
|
||||
try: return self.PgvvalidEnum(self.pgvvalidRaw)
|
||||
try:
|
||||
return self.PgvvalidEnum(self.pgvvalidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid pgvvalidRaw in Pgvvalid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1937,7 +1961,8 @@ class LidPlgsPeriodic(BaseEvent):
|
||||
|
||||
@property
|
||||
def rulestate(self):
|
||||
try: return self.RulestateBitmask(self.rulestateRaw)
|
||||
try:
|
||||
return self.RulestateBitmask(self.rulestateRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid rulestateRaw in RulestateBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1958,7 +1983,8 @@ class LidPlgsPeriodic(BaseEvent):
|
||||
|
||||
@property
|
||||
def hominstate(self):
|
||||
try: return self.HominstateEnum(self.hominstateRaw)
|
||||
try:
|
||||
return self.HominstateEnum(self.hominstateRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid hominstateRaw in Hominstate for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -1996,7 +2022,8 @@ class LidPlgsPeriodic(BaseEvent):
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
try: return self.StatusBitmask(self.statusRaw)
|
||||
try:
|
||||
return self.StatusBitmask(self.statusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid statusRaw in StatusBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2053,7 +2080,8 @@ class LidCgmAlertActivated(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -2064,10 +2092,12 @@ class LidCgmAlertActivated(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2113,7 +2143,8 @@ class LidCgmAlertCleared(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -2124,10 +2155,12 @@ class LidCgmAlertCleared(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2214,7 +2247,8 @@ class LidUpdateStatus(BaseEvent):
|
||||
|
||||
@property
|
||||
def updatesuccessful(self):
|
||||
try: return self.UpdatesuccessfulEnum(self.updatesuccessfulRaw)
|
||||
try:
|
||||
return self.UpdatesuccessfulEnum(self.updatesuccessfulRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid updatesuccessfulRaw in Updatesuccessful for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2329,7 +2363,8 @@ class LidCgmJoinSessionGx(BaseEvent):
|
||||
|
||||
@property
|
||||
def sessionjoinreason(self):
|
||||
try: return self.SessionjoinreasonEnum(self.sessionjoinreasonRaw)
|
||||
try:
|
||||
return self.SessionjoinreasonEnum(self.sessionjoinreasonRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sessionjoinreasonRaw in Sessionjoinreason for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2405,7 +2440,8 @@ class LidCgmStopSessionGx(BaseEvent):
|
||||
|
||||
@property
|
||||
def sessionstopreason(self):
|
||||
try: return self.SessionstopreasonEnum(self.sessionstopreasonRaw)
|
||||
try:
|
||||
return self.SessionstopreasonEnum(self.sessionstopreasonRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sessionstopreasonRaw in Sessionstopreason for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2465,7 +2501,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def exercisechoice(self):
|
||||
try: return self.ExercisechoiceEnum(self.exercisechoiceRaw)
|
||||
try:
|
||||
return self.ExercisechoiceEnum(self.exercisechoiceRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid exercisechoiceRaw in Exercisechoice for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2486,7 +2523,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def currentusermode(self):
|
||||
try: return self.CurrentusermodeEnum(self.currentusermodeRaw)
|
||||
try:
|
||||
return self.CurrentusermodeEnum(self.currentusermodeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid currentusermodeRaw in Currentusermode for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2507,7 +2545,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def previoususermode(self):
|
||||
try: return self.PrevioususermodeEnum(self.previoususermodeRaw)
|
||||
try:
|
||||
return self.PrevioususermodeEnum(self.previoususermodeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid previoususermodeRaw in Previoususermode for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2536,7 +2575,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def requestedaction(self):
|
||||
try: return self.RequestedactionEnum(self.requestedactionRaw)
|
||||
try:
|
||||
return self.RequestedactionEnum(self.requestedactionRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid requestedactionRaw in Requestedaction for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2553,7 +2593,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def sleepstartedbygui(self):
|
||||
try: return self.SleepstartedbyguiEnum(self.sleepstartedbyguiRaw)
|
||||
try:
|
||||
return self.SleepstartedbyguiEnum(self.sleepstartedbyguiRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sleepstartedbyguiRaw in Sleepstartedbygui for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2570,7 +2611,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def exercisestoppedbytimer(self):
|
||||
try: return self.ExercisestoppedbytimerEnum(self.exercisestoppedbytimerRaw)
|
||||
try:
|
||||
return self.ExercisestoppedbytimerEnum(self.exercisestoppedbytimerRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid exercisestoppedbytimerRaw in Exercisestoppedbytimer for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2591,7 +2633,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def activesleepschedule(self):
|
||||
try: return self.ActivesleepscheduleBitmask(self.activesleepscheduleRaw)
|
||||
try:
|
||||
return self.ActivesleepscheduleBitmask(self.activesleepscheduleRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid activesleepscheduleRaw in ActivesleepscheduleBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2608,7 +2651,8 @@ class LidAaUserModeChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def eatingsoonstoppedbytimer(self):
|
||||
try: return self.EatingsoonstoppedbytimerEnum(self.eatingsoonstoppedbytimerRaw)
|
||||
try:
|
||||
return self.EatingsoonstoppedbytimerEnum(self.eatingsoonstoppedbytimerRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid eatingsoonstoppedbytimerRaw in Eatingsoonstoppedbytimer for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2678,7 +2722,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def currentpcm(self):
|
||||
try: return self.CurrentpcmEnum(self.currentpcmRaw)
|
||||
try:
|
||||
return self.CurrentpcmEnum(self.currentpcmRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid currentpcmRaw in Currentpcm for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2699,7 +2744,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def previouspcm(self):
|
||||
try: return self.PreviouspcmEnum(self.previouspcmRaw)
|
||||
try:
|
||||
return self.PreviouspcmEnum(self.previouspcmRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid previouspcmRaw in Previouspcm for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2716,7 +2762,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def pumpsuspended(self):
|
||||
try: return self.PumpsuspendedEnum(self.pumpsuspendedRaw)
|
||||
try:
|
||||
return self.PumpsuspendedEnum(self.pumpsuspendedRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid pumpsuspendedRaw in Pumpsuspended for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2733,7 +2780,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def calculationavailable(self):
|
||||
try: return self.CalculationavailableEnum(self.calculationavailableRaw)
|
||||
try:
|
||||
return self.CalculationavailableEnum(self.calculationavailableRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid calculationavailableRaw in Calculationavailable for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2750,7 +2798,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def cgmavailable(self):
|
||||
try: return self.CgmavailableEnum(self.cgmavailableRaw)
|
||||
try:
|
||||
return self.CgmavailableEnum(self.cgmavailableRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid cgmavailableRaw in Cgmavailable for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2767,7 +2816,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def closedlooppreferred(self):
|
||||
try: return self.ClosedlooppreferredEnum(self.closedlooppreferredRaw)
|
||||
try:
|
||||
return self.ClosedlooppreferredEnum(self.closedlooppreferredRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid closedlooppreferredRaw in Closedlooppreferred for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2784,7 +2834,8 @@ class LidAaPcmChange(BaseEvent):
|
||||
|
||||
@property
|
||||
def sufficientclosedloopparams(self):
|
||||
try: return self.SufficientclosedloopparamsEnum(self.sufficientclosedloopparamsRaw)
|
||||
try:
|
||||
return self.SufficientclosedloopparamsEnum(self.sufficientclosedloopparamsRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sufficientclosedloopparamsRaw in Sufficientclosedloopparams for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2850,7 +2901,8 @@ class LidCgmDataGxb(BaseEvent):
|
||||
|
||||
@property
|
||||
def glucosevaluestatus(self):
|
||||
try: return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
try:
|
||||
return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid glucosevaluestatusRaw in Glucosevaluestatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2873,7 +2925,8 @@ class LidCgmDataGxb(BaseEvent):
|
||||
|
||||
@property
|
||||
def cgmDataType(self):
|
||||
try: return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
try:
|
||||
return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid cgmDataTypeRaw in CgmdatatypeBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2908,7 +2961,8 @@ class LidCgmDataGxb(BaseEvent):
|
||||
|
||||
@property
|
||||
def egvInfoBitmask(self):
|
||||
try: return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
try:
|
||||
return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid egvInfoBitmaskRaw in EgvinfobitmaskBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -2978,7 +3032,8 @@ class LidBasalDelivery(BaseEvent):
|
||||
|
||||
@property
|
||||
def commandedRateSource(self):
|
||||
try: return self.CommandedratesourceEnum(self.commandedRateSourceRaw)
|
||||
try:
|
||||
return self.CommandedratesourceEnum(self.commandedRateSourceRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid commandedRateSourceRaw in Commandedratesource for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3039,7 +3094,8 @@ class LidBolusDelivery(BaseEvent):
|
||||
|
||||
@property
|
||||
def bolusDeliveryStatus(self):
|
||||
try: return self.BolusdeliverystatusEnum(self.bolusDeliveryStatusRaw)
|
||||
try:
|
||||
return self.BolusdeliverystatusEnum(self.bolusDeliveryStatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bolusDeliveryStatusRaw in Bolusdeliverystatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3064,7 +3120,8 @@ class LidBolusDelivery(BaseEvent):
|
||||
|
||||
@property
|
||||
def bolusType(self):
|
||||
try: return self.BolustypeBitmask(self.bolusTypeRaw)
|
||||
try:
|
||||
return self.BolustypeBitmask(self.bolusTypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bolusTypeRaw in BolustypeBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3093,7 +3150,8 @@ class LidBolusDelivery(BaseEvent):
|
||||
|
||||
@property
|
||||
def bolusSource(self):
|
||||
try: return self.BolussourceEnum(self.bolusSourceRaw)
|
||||
try:
|
||||
return self.BolussourceEnum(self.bolusSourceRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid bolusSourceRaw in Bolussource for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3198,7 +3256,8 @@ class LidAaDailyStatus(BaseEvent):
|
||||
|
||||
@property
|
||||
def pumpcontrolstate(self):
|
||||
try: return self.PumpcontrolstateEnum(self.pumpcontrolstateRaw)
|
||||
try:
|
||||
return self.PumpcontrolstateEnum(self.pumpcontrolstateRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid pumpcontrolstateRaw in Pumpcontrolstate for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3217,7 +3276,8 @@ class LidAaDailyStatus(BaseEvent):
|
||||
|
||||
@property
|
||||
def usermode(self):
|
||||
try: return self.UsermodeEnum(self.usermodeRaw)
|
||||
try:
|
||||
return self.UsermodeEnum(self.usermodeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid usermodeRaw in Usermode for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3238,7 +3298,8 @@ class LidAaDailyStatus(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3286,7 +3347,8 @@ class LidCgmAlertActivatedDex(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -3297,10 +3359,12 @@ class LidCgmAlertActivatedDex(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3319,7 +3383,8 @@ class LidCgmAlertActivatedDex(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3368,7 +3433,8 @@ class LidCgmAlertClearedDex(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -3379,10 +3445,12 @@ class LidCgmAlertClearedDex(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3401,7 +3469,8 @@ class LidCgmAlertClearedDex(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3445,7 +3514,8 @@ class LidCgmAlertAckDex(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -3456,10 +3526,12 @@ class LidCgmAlertAckDex(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3478,7 +3550,8 @@ class LidCgmAlertAckDex(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3495,7 +3568,8 @@ class LidCgmAlertAckDex(BaseEvent):
|
||||
|
||||
@property
|
||||
def acksource(self):
|
||||
try: return self.AcksourceEnum(self.acksourceRaw)
|
||||
try:
|
||||
return self.AcksourceEnum(self.acksourceRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid acksourceRaw in Acksource for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3553,7 +3627,8 @@ class LidCgmDataFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def glucosevaluestatus(self):
|
||||
try: return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
try:
|
||||
return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid glucosevaluestatusRaw in Glucosevaluestatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3576,7 +3651,8 @@ class LidCgmDataFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def cgmDataType(self):
|
||||
try: return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
try:
|
||||
return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid cgmDataTypeRaw in CgmdatatypeBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3609,7 +3685,8 @@ class LidCgmDataFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def algorithmstate(self):
|
||||
try: return self.AlgorithmstateEnum(self.algorithmstateRaw)
|
||||
try:
|
||||
return self.AlgorithmstateEnum(self.algorithmstateRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid algorithmstateRaw in Algorithmstate for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3644,7 +3721,8 @@ class LidCgmDataFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def egvInfoBitmask(self):
|
||||
try: return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
try:
|
||||
return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid egvInfoBitmaskRaw in EgvinfobitmaskBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3747,7 +3825,8 @@ class LidCgmDataG7(BaseEvent):
|
||||
|
||||
@property
|
||||
def glucosevaluestatus(self):
|
||||
try: return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
try:
|
||||
return self.GlucosevaluestatusEnum(self.glucosevaluestatusRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid glucosevaluestatusRaw in Glucosevaluestatus for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3770,7 +3849,8 @@ class LidCgmDataG7(BaseEvent):
|
||||
|
||||
@property
|
||||
def cgmDataType(self):
|
||||
try: return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
try:
|
||||
return self.CgmdatatypeBitmask(self.cgmDataTypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid cgmDataTypeRaw in CgmdatatypeBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3809,7 +3889,8 @@ class LidCgmDataG7(BaseEvent):
|
||||
|
||||
@property
|
||||
def algorithmstate(self):
|
||||
try: return self.AlgorithmstateEnum(self.algorithmstateRaw)
|
||||
try:
|
||||
return self.AlgorithmstateEnum(self.algorithmstateRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid algorithmstateRaw in Algorithmstate for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -3842,7 +3923,8 @@ class LidCgmDataG7(BaseEvent):
|
||||
|
||||
@property
|
||||
def egvInfoBitmask(self):
|
||||
try: return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
try:
|
||||
return self.EgvinfobitmaskBitmask(self.egvInfoBitmaskRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid egvInfoBitmaskRaw in EgvinfobitmaskBitmask for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -4050,7 +4132,8 @@ class LidCgmAlertActivatedFsl2(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -4061,10 +4144,12 @@ class LidCgmAlertActivatedFsl2(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -4081,7 +4166,8 @@ class LidCgmAlertActivatedFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -4130,7 +4216,8 @@ class LidCgmAlertClearedFsl2(BaseEvent):
|
||||
"20": "CGM Transmitter Error",
|
||||
"26": "CGM Temperature",
|
||||
"27": "CGM Failed Connection",
|
||||
"39": "CGM Transmitter Expired"
|
||||
"39": "CGM Transmitter Expired",
|
||||
"40": "Pump Bluetooth Error"
|
||||
}
|
||||
|
||||
class DalertidEnum(Enum):
|
||||
@@ -4141,10 +4228,12 @@ class LidCgmAlertClearedFsl2(BaseEvent):
|
||||
CgmTemperature = 26
|
||||
CgmFailedConnection = 27
|
||||
CgmTransmitterExpired = 39
|
||||
PumpBluetoothError = 40
|
||||
|
||||
@property
|
||||
def dalertid(self):
|
||||
try: return self.DalertidEnum(self.dalertidRaw)
|
||||
try:
|
||||
return self.DalertidEnum(self.dalertidRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid dalertidRaw in Dalertid for "+str(self))
|
||||
logger.error(e)
|
||||
@@ -4161,7 +4250,8 @@ class LidCgmAlertClearedFsl2(BaseEvent):
|
||||
|
||||
@property
|
||||
def sensortype(self):
|
||||
try: return self.SensortypeEnum(self.sensortypeRaw)
|
||||
try:
|
||||
return self.SensortypeEnum(self.sensortypeRaw)
|
||||
except ValueError as e:
|
||||
logger.error("Invalid sensortypeRaw in Sensortype for "+str(self))
|
||||
logger.error(e)
|
||||
|
||||
@@ -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='UTC').replace(tzinfo=TIMEZONE_NAME)
|
||||
|
||||
@@ -53,7 +53,7 @@ def transform_enum(event_def, name, name_fmt, field, tx):
|
||||
out += [
|
||||
'@property',
|
||||
f'def {name_fmt}(self):',
|
||||
f' try:'
|
||||
f' try:',
|
||||
f' return self.{enumNameFormat(name_fmt)}Enum(self.{name_fmt}Raw)',
|
||||
f' except ValueError as e:',
|
||||
f' logger.error("Invalid {name_fmt}Raw in {enumNameFormat(name_fmt)} for "+str(self))',
|
||||
@@ -89,7 +89,7 @@ def transform_bitmask(event_def, name, name_fmt, field, tx):
|
||||
out += [
|
||||
'@property',
|
||||
f'def {name_fmt}(self):',
|
||||
f' try:'
|
||||
f' try:',
|
||||
f' return self.{enumNameFormat(name_fmt)}Bitmask(self.{name_fmt}Raw)',
|
||||
f' except ValueError as e:',
|
||||
f' logger.error("Invalid {name_fmt}Raw in {enumNameFormat(name_fmt)}Bitmask for "+str(self))',
|
||||
|
||||
@@ -16,9 +16,9 @@ EXERCISE_EVENTTYPE = "Exercise"
|
||||
SLEEP_EVENTTYPE = "Sleep"
|
||||
ALARM_EVENTTYPE = "Alarm"
|
||||
CGM_ALERT_EVENTTYPE = "CGM Alert"
|
||||
CGM_START_EVENTTYPE = "CGM Start Session"
|
||||
CGM_JOIN_EVENTTYPE = "CGM Join Session"
|
||||
CGM_STOP_EVENTTYPE = "CGM Stop Session"
|
||||
CGM_START_EVENTTYPE = "Sensor Start"
|
||||
CGM_JOIN_EVENTTYPE = "Sensor Start"
|
||||
CGM_STOP_EVENTTYPE = "Sensor Stop"
|
||||
|
||||
IOB_ACTIVITYTYPE = "tconnect_iob"
|
||||
|
||||
@@ -52,7 +52,7 @@ class NightscoutEntry:
|
||||
data = {
|
||||
"eventType": BOLUS_EVENTTYPE,
|
||||
"created_at": created_at,
|
||||
"carbs": int(carbs) if carbs else None,
|
||||
"carbs": int(carbs) if carbs else 0,
|
||||
"insulin": float(bolus),
|
||||
"notes": notes,
|
||||
"enteredBy": ENTERED_BY,
|
||||
|
||||
@@ -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'):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
def insulin_float_round(amt):
|
||||
if type(amt) != float:
|
||||
return amt
|
||||
return round(amt, 2)
|
||||
|
||||
def insulin_milliunits_to_real(amtMilli):
|
||||
return insulin_float_round(amtMilli / 1000)
|
||||
@@ -0,0 +1,17 @@
|
||||
from ...features import DEFAULT_FEATURES
|
||||
from .choose_device import TandemSourceChooseDevice
|
||||
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 = TandemSourceChooseDevice(secret_arg, tconnect).choose()
|
||||
return ProcessTimeRange(tconnect, nightscout, tconnectDevice, pretend, features).process(time_start, time_end)
|
||||
@@ -46,23 +46,27 @@ class ProcessTimeRange:
|
||||
]
|
||||
|
||||
def process(self, time_start, time_end):
|
||||
logger.info(f"ProcessTimeRange {time_start=} {time_end=} {self.tconnect_device_id=} {self.features=}")
|
||||
logger.info(f"ProcessTimeRange time_start={time_start} time_end={time_end} tconnect_device_id={self.tconnect_device_id} features={self.features}")
|
||||
|
||||
pump_events_raw = self.tconnect.tandemsource.pump_events_raw(self.tconnect_device_id, time_start, time_end)
|
||||
pump_events_decoded = decode_raw_events(pump_events_raw)
|
||||
logger.info(f"Read {len(pump_events_decoded)=} (est. {len(pump_events_decoded)/EVENT_LEN} events)")
|
||||
logger.info(f"Read {len(pump_events_decoded)} bytes (est. {len(pump_events_decoded)/EVENT_LEN} events)")
|
||||
events = Events(pump_events_decoded)
|
||||
|
||||
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))
|
||||
|
||||
|
||||
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))
|
||||
@@ -62,7 +62,7 @@ class ProcessAlarm:
|
||||
if type(event) == eventtypes.LidAlarmActivated:
|
||||
return NightscoutEntry.alarm(
|
||||
created_at = event.eventTimestamp.format(),
|
||||
reason = event.alarmid,
|
||||
reason = "%s" % event.alarmid.name,
|
||||
pump_event_id = "%s" % event.eventId
|
||||
)
|
||||
elif type(event) == eventtypes.LidMalfunctionActivated:
|
||||
|
||||
@@ -6,6 +6,7 @@ from ... import features
|
||||
from ...eventparser.generic import Events, decode_raw_events, EVENT_LEN
|
||||
from ...eventparser.utils import bitmask_to_list
|
||||
from ...eventparser import events as eventtypes
|
||||
from .helpers import insulin_float_round, insulin_milliunits_to_real
|
||||
from ...domain.tandemsource.event_class import EventClass
|
||||
from ...parser.nightscout import (
|
||||
BASAL_EVENTTYPE,
|
||||
@@ -35,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]
|
||||
|
||||
@@ -69,7 +74,7 @@ class ProcessBasal:
|
||||
def basal_to_nsentry(self, start, duration, event):
|
||||
if type(event) == eventtypes.LidBasalRateChange:
|
||||
return NightscoutEntry.basal(
|
||||
value = event.commandedbasalrate,
|
||||
value = insulin_float_round(event.commandedbasalrate),
|
||||
duration_mins = duration.seconds / 60,
|
||||
created_at = start.format(),
|
||||
reason = ', '.join(bitmask_to_list(event.changetype)),
|
||||
@@ -77,7 +82,7 @@ class ProcessBasal:
|
||||
)
|
||||
if type(event) == eventtypes.LidBasalDelivery:
|
||||
return NightscoutEntry.basal(
|
||||
value = event.commandedRate,
|
||||
value = insulin_milliunits_to_real(event.commandedRate),
|
||||
duration_mins = duration.seconds / 60,
|
||||
created_at = start.format(),
|
||||
reason = ', '.join(bitmask_to_list(event.commandedRateSource)),
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -7,6 +7,7 @@ from ...eventparser.generic import Events, decode_raw_events, EVENT_LEN
|
||||
from ...eventparser.utils import bitmask_to_list
|
||||
from ...eventparser import events as eventtypes
|
||||
from ...domain.tandemsource.event_class import EventClass
|
||||
from .helpers import insulin_float_round
|
||||
from ...parser.nightscout import (
|
||||
BOLUS_EVENTTYPE,
|
||||
NightscoutEntry
|
||||
@@ -43,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
|
||||
@@ -101,10 +102,11 @@ class ProcessBolus:
|
||||
|
||||
|
||||
return NightscoutEntry.bolus(
|
||||
bolus = bolusCompleted.insulindelivered,
|
||||
bolus = insulin_float_round(bolusCompleted.insulindelivered),
|
||||
carbs = bolusRequested1.carbamount if bolusRequested1 and bolusRequested1.carbamount>0 else None,
|
||||
created_at = bolusCompleted.eventTimestamp.format(),
|
||||
notes = notes + suffix,
|
||||
bg = bolusRequested1.BG if bolusRequested1 and bolusRequested1.BG > 0 else None,
|
||||
pump_event_id = ",".join(event_ids)
|
||||
)
|
||||
|
||||
|
||||
@@ -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:
|
||||
@@ -88,7 +88,7 @@ class ProcessCartridge:
|
||||
def cannula_to_nsentry(self, cannulaFilled):
|
||||
return NightscoutEntry.sitechange(
|
||||
created_at = cannulaFilled.eventTimestamp.format(),
|
||||
reason = "Cannula Filled" + (" (%du primed)" % round(cannulaFilled.primesize) if cannulaFilled.primesize else ""),
|
||||
reason = "Cannula Filled" + (" (%du primed)" % round(cannulaFilled.primesize, 2) if cannulaFilled.primesize else ""),
|
||||
pump_event_id = "%s" % cannulaFilled.eventId
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -46,7 +46,9 @@ class ProcessCGMAlert:
|
||||
|
||||
ns_entries = []
|
||||
for event in alertEvents:
|
||||
ns_entries.append(self.alert_to_nsentry(event))
|
||||
e = self.alert_to_nsentry(event)
|
||||
if e:
|
||||
ns_entries.append(e)
|
||||
|
||||
return ns_entries
|
||||
|
||||
@@ -63,21 +65,28 @@ class ProcessCGMAlert:
|
||||
return count
|
||||
|
||||
def alert_to_nsentry(self, alert):
|
||||
if not alert.dalertid:
|
||||
logger.info("ProcessCGMAlert: Skipping alert with unknown dalertid %d: %s" % (alert.dalertidRaw, alert))
|
||||
return None
|
||||
|
||||
if type(alert) == eventtypes.LidCgmAlertActivated:
|
||||
return NightscoutEntry.cgm_alert(
|
||||
created_at = alert.eventTimestamp.format(),
|
||||
reason = ("CGM Alert (%s)" % alert.dalertid) if alert.dalertid else "CGM Alert (Unknown)",
|
||||
reason = ("CGM Alert (%s)" % alert.dalertid.name) if alert.dalertid else "CGM Alert (Unknown)",
|
||||
pump_event_id = "%s" % alert.eventId
|
||||
)
|
||||
elif type(alert) == eventtypes.LidCgmAlertActivatedDex:
|
||||
if alert.dalertid == eventtypes.LidCgmAlertActivatedDex.DalertidEnum.CgmOutOfRange:
|
||||
logger.info("ProcessCGMAlert: Skipping alert with CgmOutOfRange dalertid %d: %s" % (alert.dalertidRaw, alert))
|
||||
return None
|
||||
return NightscoutEntry.cgm_alert(
|
||||
created_at = alert.eventTimestamp.format(),
|
||||
reason = ("Dexcom CGM Alert (%s)" % alert.dalertid) if alert.dalertid else "Dexcom CGM Alert (Unknown)",
|
||||
reason = ("Dexcom CGM Alert (%s)" % alert.dalertid.name) if alert.dalertid else "Dexcom CGM Alert (Unknown)",
|
||||
pump_event_id = "%s" % alert.eventId
|
||||
)
|
||||
elif type(alert) == eventtypes.LidCgmAlertActivatedFsl2:
|
||||
return NightscoutEntry.cgm_alert(
|
||||
created_at = alert.eventTimestamp.format(),
|
||||
reason = ("Libre CGM Alert (%s)" % alert.dalertid) if alert.dalertid else "Libre CGM Alert (Unknown)",
|
||||
reason = ("Libre CGM Alert (%s)" % alert.dalertid.name) if alert.dalertid else "Libre CGM Alert (Unknown)",
|
||||
pump_event_id = "%s" % alert.eventId
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,6 +9,8 @@ from ...eventparser import events as eventtypes
|
||||
from ...domain.tandemsource.event_class import EventClass
|
||||
from ...parser.nightscout import (
|
||||
CGM_START_EVENTTYPE,
|
||||
CGM_JOIN_EVENTTYPE,
|
||||
CGM_STOP_EVENTTYPE,
|
||||
NightscoutEntry
|
||||
)
|
||||
|
||||
@@ -26,18 +28,29 @@ class ProcessCGMStartJoinStop:
|
||||
return features.PUMP_EVENTS in self.features or features.CGM_ALERTS in self.features
|
||||
|
||||
def process(self, events, time_start, time_end):
|
||||
logger.debug("ProcessCGMStartJoinStop: querying for last uploaded entry")
|
||||
last_upload = self.nightscout.last_uploaded_entry(CGM_START_EVENTTYPE, time_start=time_start, time_end=time_end)
|
||||
last_upload = None
|
||||
last_upload_time = None
|
||||
if last_upload:
|
||||
last_upload_time = arrow.get(last_upload["created_at"])
|
||||
logger.info("ProcessCGMStartJoinStop: Last Nightscout cgmstart upload: %s" % last_upload_time)
|
||||
for eventtype in [CGM_START_EVENTTYPE, CGM_JOIN_EVENTTYPE, CGM_STOP_EVENTTYPE]:
|
||||
logger.debug("ProcessCGMStartJoinStop: querying for last uploaded entry for %s" % eventtype)
|
||||
_last_upload = self.nightscout.last_uploaded_entry(eventtype, time_start=time_start, time_end=time_end)
|
||||
_last_upload_time = None
|
||||
if _last_upload:
|
||||
_last_upload_time = arrow.get(_last_upload["created_at"])
|
||||
|
||||
if not last_upload_time:
|
||||
last_upload = _last_upload
|
||||
last_upload_time = _last_upload_time
|
||||
elif _last_upload_time > last_upload_time:
|
||||
last_upload = _last_upload
|
||||
last_upload_time = _last_upload_time
|
||||
logger.info("ProcessCGMStartJoinStop: Last Nightscout %s upload: %s" % (eventtype, _last_upload_time))
|
||||
logger.info("ProcessCGMStartJoinStop: Overall last Nightscout upload: %s %s" % (last_upload_time, last_upload))
|
||||
|
||||
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):
|
||||
@@ -198,7 +198,7 @@ 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,
|
||||
|
||||
@@ -22,7 +22,8 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"created_at": "2021-03-16 00:25:21-04:00",
|
||||
"carbs": None,
|
||||
"insulin": None,
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
@@ -41,7 +42,8 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"created_at": "2021-03-16 12:25:21-04:00",
|
||||
"carbs": None,
|
||||
"insulin": None,
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
@@ -57,7 +59,8 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"carbs": 45,
|
||||
"insulin": 7.5,
|
||||
"notes": "",
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
@@ -72,7 +75,8 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"carbs": 5,
|
||||
"insulin": 0.5,
|
||||
"notes": "",
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
@@ -92,7 +96,8 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"notes": "",
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"glucose": "123",
|
||||
"glucoseType": "Sensor"
|
||||
"glucoseType": "Sensor",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
@@ -111,28 +116,14 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"notes": "",
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"glucose": "150",
|
||||
"glucoseType": "Finger"
|
||||
"glucoseType": "Finger",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
def test_bolus_with_bg_invalid_type(self):
|
||||
self.assertRaises(InvalidBolusTypeException,
|
||||
NightscoutEntry.bolus,
|
||||
bolus=0.5,
|
||||
carbs=5,
|
||||
created_at="2021-03-16 12:25:21-04:00",
|
||||
bg="150")
|
||||
|
||||
self.assertRaises(InvalidBolusTypeException,
|
||||
NightscoutEntry.bolus,
|
||||
bolus=0.5,
|
||||
carbs=5,
|
||||
created_at="2021-03-16 12:25:21-04:00",
|
||||
bg="150",
|
||||
bg_type="")
|
||||
|
||||
self.assertRaises(InvalidBolusTypeException,
|
||||
NightscoutEntry.bolus,
|
||||
NightscoutEntry.bolus,
|
||||
bolus=0.5,
|
||||
carbs=5,
|
||||
created_at="2021-03-16 12:25:21-04:00",
|
||||
@@ -163,9 +154,10 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"date": 1635041834000,
|
||||
"dateString": "2021-10-23T22:17:14-0400",
|
||||
"device": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_sitechange(self):
|
||||
self.assertEqual(
|
||||
NightscoutEntry.sitechange(
|
||||
@@ -176,10 +168,11 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"reason": "reason",
|
||||
"notes": "reason",
|
||||
"created_at": "2021-12-05T00:16:35.058Z",
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_basalsuspension(self):
|
||||
self.assertEqual(
|
||||
NightscoutEntry.basalsuspension(
|
||||
@@ -190,11 +183,12 @@ class TestNightscoutEntry(unittest.TestCase):
|
||||
"reason": "reason",
|
||||
"notes": "reason",
|
||||
"created_at": "2021-12-05T00:16:35.058Z",
|
||||
"enteredBy": "Pump (tconnectsync)"
|
||||
"enteredBy": "Pump (tconnectsync)",
|
||||
"pump_event_id": ""
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
def test_profile_store(self):
|
||||
self.assertEqual(
|
||||
NightscoutEntry.profile_store(
|
||||
|
||||
@@ -16,7 +16,7 @@ def _stub_last_uploaded_entry(eventType, time_start=None, time_end=None):
|
||||
class TestNsWritePumpEvents(unittest.TestCase):
|
||||
|
||||
SITE_CHANGE_EVENT = {'time': '2024-02-04 16:27:50-05:00', 'event_type': 'Site/Cartridge Change'}
|
||||
SITE_CHANGE_NS = {'created_at': '2024-02-04 16:27:50-05:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Site Change', 'notes': 'Site/Cartridge Change','reason': 'Site/Cartridge Change'}
|
||||
SITE_CHANGE_NS = {'created_at': '2024-02-04 16:27:50-05:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Site Change', 'notes': 'Site/Cartridge Change','reason': 'Site/Cartridge Change', 'pump_event_id': ''}
|
||||
def test_write_single_sitechange_event(self):
|
||||
nightscout = NightscoutApi()
|
||||
nightscout.last_uploaded_entry = _stub_last_uploaded_entry
|
||||
@@ -31,7 +31,7 @@ class TestNsWritePumpEvents(unittest.TestCase):
|
||||
}, dict(nightscout.uploaded_entries))
|
||||
|
||||
EMPTY_CART_EVENT = {'time': '2024-05-14 09:01:59-04:00', 'event_type': 'Empty Cartridge/Pump Shutdown'}
|
||||
EMPTY_CART_NS = {'created_at': '2024-05-14 09:01:59-04:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Basal Suspension', 'notes': 'Empty Cartridge/Pump Shutdown', 'reason': 'Empty Cartridge/Pump Shutdown'}
|
||||
EMPTY_CART_NS = {'created_at': '2024-05-14 09:01:59-04:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Basal Suspension', 'notes': 'Empty Cartridge/Pump Shutdown', 'reason': 'Empty Cartridge/Pump Shutdown', 'pump_event_id': ''}
|
||||
def test_write_single_emptycart_event(self):
|
||||
nightscout = NightscoutApi()
|
||||
nightscout.last_uploaded_entry = _stub_last_uploaded_entry
|
||||
@@ -46,7 +46,7 @@ class TestNsWritePumpEvents(unittest.TestCase):
|
||||
}, dict(nightscout.uploaded_entries))
|
||||
|
||||
USER_SUSPENDED_EVENT = {'time': '2024-02-05 09:48:22-05:00', 'event_type': 'User Suspended'}
|
||||
USER_SUSPENDED_NS = {'created_at': '2024-02-05 09:48:22-05:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Basal Suspension', 'notes': 'User Suspended', 'reason': 'User Suspended'}
|
||||
USER_SUSPENDED_NS = {'created_at': '2024-02-05 09:48:22-05:00', 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Basal Suspension', 'notes': 'User Suspended', 'reason': 'User Suspended', 'pump_event_id': ''}
|
||||
def test_write_single_usersuspended_event(self):
|
||||
nightscout = NightscoutApi()
|
||||
nightscout.last_uploaded_entry = _stub_last_uploaded_entry
|
||||
@@ -59,11 +59,11 @@ class TestNsWritePumpEvents(unittest.TestCase):
|
||||
self.USER_SUSPENDED_NS
|
||||
]
|
||||
}, dict(nightscout.uploaded_entries))
|
||||
|
||||
|
||||
EXERCISE_EVENT = {'time': '2024-03-10 08:53:20-04:00', 'duration_mins': 269.3833333333333, 'event_type': 'Exercise'}
|
||||
EXERCISE_NS = {'created_at': '2024-03-10 08:53:20-04:00', 'duration': 269.3833333333333, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Exercise', 'notes': 'Exercise', 'reason': 'Exercise'}
|
||||
EXERCISE_NS = {'created_at': '2024-03-10 08:53:20-04:00', 'duration': 269.3833333333333, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Exercise', 'notes': 'Exercise', 'reason': 'Exercise', 'pump_event_id': ''}
|
||||
EXERCISE_EXTENDED_EVENT = {'time': '2024-03-10 08:53:20-04:00', 'duration_mins': 585.8833333333333, 'event_type': 'Exercise'}
|
||||
EXERCISE_EXTENDED_NS = {'created_at': '2024-03-10 08:53:20-04:00', 'duration': 585.8833333333333, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Exercise', 'notes': 'Exercise', 'reason': 'Exercise'}
|
||||
EXERCISE_EXTENDED_NS = {'created_at': '2024-03-10 08:53:20-04:00', 'duration': 585.8833333333333, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Exercise', 'notes': 'Exercise', 'reason': 'Exercise', 'pump_event_id': ''}
|
||||
def test_write_exercise_events(self):
|
||||
nightscout = NightscoutApi()
|
||||
nightscout.last_uploaded_entry = _stub_last_uploaded_entry
|
||||
@@ -101,11 +101,11 @@ class TestNsWritePumpEvents(unittest.TestCase):
|
||||
self.EXERCISE_EXTENDED_NS
|
||||
]
|
||||
}, dict(nightscout.uploaded_entries))
|
||||
|
||||
|
||||
SLEEP_EVENT = {'time': '2024-02-07 00:00:19-05:00', 'duration_mins': 13.916666666666666, 'event_type': 'Sleep'}
|
||||
SLEEP_NS = {'created_at': '2024-02-07 00:00:19-05:00', 'duration': 13.916666666666666, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Sleep', 'notes': 'Sleep', 'reason': 'Sleep'}
|
||||
SLEEP_NS = {'created_at': '2024-02-07 00:00:19-05:00', 'duration': 13.916666666666666, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Sleep', 'notes': 'Sleep', 'reason': 'Sleep', 'pump_event_id': ''}
|
||||
SLEEP_EXTENDED_EVENT = {'time': '2024-02-07 00:00:19-05:00', 'duration_mins': 74.0, 'event_type': 'Sleep'}
|
||||
SLEEP_EXTENDED_NS = {'created_at': '2024-02-07 00:00:19-05:00', 'duration': 74.0, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Sleep', 'notes': 'Sleep', 'reason': 'Sleep'}
|
||||
SLEEP_EXTENDED_NS = {'created_at': '2024-02-07 00:00:19-05:00', 'duration': 74.0, 'enteredBy': 'Pump (tconnectsync)', 'eventType': 'Sleep', 'notes': 'Sleep', 'reason': 'Sleep', 'pump_event_id': ''}
|
||||
def test_write_sleep_events(self):
|
||||
nightscout = NightscoutApi()
|
||||
nightscout.last_uploaded_entry = _stub_last_uploaded_entry
|
||||
@@ -143,7 +143,7 @@ class TestNsWritePumpEvents(unittest.TestCase):
|
||||
self.SLEEP_EXTENDED_NS
|
||||
]
|
||||
}, dict(nightscout.uploaded_entries))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+15
-15
@@ -26,7 +26,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
|
||||
def stub_therapy_timeline(self, time_start, time_end):
|
||||
return copy.deepcopy(TestBasalSync.base)
|
||||
|
||||
|
||||
def stub_ciq_therapy_events(self, time_start, time_end):
|
||||
return {
|
||||
"event": []
|
||||
@@ -39,7 +39,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
"basalData": [],
|
||||
"bolusData": []
|
||||
}
|
||||
|
||||
|
||||
def stub_ws2_basalsuspension(self, time_start, time_end):
|
||||
return {"BasalSuspension": []}
|
||||
|
||||
@@ -394,7 +394,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
self.assertDictEqual(nightscout.put_entries, {})
|
||||
self.assertListEqual(nightscout.deleted_entries, [])
|
||||
self.assertEqual(count, 0)
|
||||
|
||||
|
||||
"""Existing IOB in Nightscout. Uploads new iob reading and deletes old IOB."""
|
||||
def test_updates_ciq_iob_data(self):
|
||||
tconnect = TConnectApi()
|
||||
@@ -442,7 +442,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
"activity/sentinel_existing_iob_id"
|
||||
])
|
||||
self.assertEqual(count, 1)
|
||||
|
||||
|
||||
"""No pump activity events in Nightscout. New CIQ activity events."""
|
||||
def test_new_ciq_activity_events(self):
|
||||
tconnect = TConnectApi()
|
||||
@@ -460,7 +460,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
"events": [{
|
||||
"duration": 1200,
|
||||
"eventType": 2, # Exercise
|
||||
"continuation": None,
|
||||
"continuation": None,
|
||||
"timeZoneId": "America/Los_Angeles",
|
||||
"x": 1619901912 # 2021-05-01 13:45:12-04:00
|
||||
}, {
|
||||
@@ -510,7 +510,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
"events": [{
|
||||
"duration": 1200,
|
||||
"eventType": 2, # Exercise
|
||||
"continuation": None,
|
||||
"continuation": None,
|
||||
"timeZoneId": "America/Los_Angeles",
|
||||
"x": 1619901912 # 2021-05-01 13:45:12-04:00
|
||||
}, {
|
||||
@@ -539,7 +539,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
self.assertListEqual(nightscout.deleted_entries, [])
|
||||
self.assertEqual(count, 0)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Existing Sleep event in Nightscout with shorter duration than current, as well as a past Exercise event.
|
||||
Ensures that the old sleep event is deleted and a new one is created with the correct duration."""
|
||||
@@ -559,7 +559,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
"events": [{
|
||||
"duration": 1200,
|
||||
"eventType": 2, # Exercise
|
||||
"continuation": None,
|
||||
"continuation": None,
|
||||
"timeZoneId": "America/Los_Angeles",
|
||||
"x": 1619901912 # 2021-05-01 13:45:12-04:00
|
||||
}, {
|
||||
@@ -623,7 +623,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
tconnect.controliq.therapy_timeline = self.stub_therapy_timeline
|
||||
tconnect.ws2.therapy_timeline_csv = self.stub_therapy_timeline_csv
|
||||
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
self.assertEqual(time_start, start)
|
||||
self.assertEqual(time_end, end)
|
||||
|
||||
@@ -673,7 +673,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
tconnect.controliq.therapy_timeline = self.stub_therapy_timeline
|
||||
tconnect.ws2.therapy_timeline_csv = self.stub_therapy_timeline_csv
|
||||
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
self.assertEqual(time_start, start)
|
||||
self.assertEqual(time_end, end)
|
||||
|
||||
@@ -737,7 +737,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
tconnect.controliq.therapy_timeline = self.stub_therapy_timeline
|
||||
tconnect.ws2.therapy_timeline_csv = self.stub_therapy_timeline_csv
|
||||
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
def fake_basalsuspension(time_start, time_end):
|
||||
self.assertEqual(time_start, start)
|
||||
self.assertEqual(time_end, end)
|
||||
|
||||
@@ -781,7 +781,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
|
||||
pump_guid = '00000000-0000-0000-0000-000000000001'
|
||||
serial_number = '12345'
|
||||
|
||||
|
||||
def fake_my_devices():
|
||||
return {
|
||||
serial_number: Device(
|
||||
@@ -830,7 +830,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
|
||||
pump_guid = '00000000-0000-0000-0000-000000000001'
|
||||
serial_number = '12345'
|
||||
|
||||
|
||||
def fake_my_devices():
|
||||
return {
|
||||
serial_number: Device(
|
||||
@@ -878,7 +878,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
|
||||
pump_guid = '00000000-0000-0000-0000-000000000001'
|
||||
serial_number = '12345'
|
||||
|
||||
|
||||
def fake_my_devices():
|
||||
return {
|
||||
serial_number: Device(
|
||||
@@ -932,7 +932,7 @@ class TestProcessTimeRange(unittest.TestCase):
|
||||
|
||||
pump_guid = '00000000-0000-0000-0000-000000000001'
|
||||
serial_number = '12345'
|
||||
|
||||
|
||||
def fake_my_devices():
|
||||
return {
|
||||
serial_number: Device(
|
||||
|
||||
Reference in New Issue
Block a user