mirror of
https://github.com/bckelley/tconnectsync.git
synced 2026-08-24 03:34:12 -05:00
Add Freestyle Libre 3 (FSL3) CGM sensor support
Implement FSL3 sensor integration alongside G6, G7, and FSL2 with expanded CGM alert codes, improved datetime handling, and test coverage. **FSL3 Event Integration:** - Add FSL3 events to CGM_READING, _CGM_JOIN, and _CGM_STOP event classes - Enable unified processing of FSL3 alongside existing sensor variants: - Event 480: LID_CGM_DATA_FSL3 - Event 477: LID_CGM_JOIN_SESSION_FSL3 - Event 486: LID_CGM_STOP_SESSION_FSL3 **CGM Alert Enumeration:** - Expand CGM alert codes from 8 to 18 mapped codes - Add verified alert codes: 1, 2, 3, 8, 12, 22, 25, 45, 46, 48 - Rename alert 51 to CONTROL_IQ_LOW (was DEFAULT_ALERT_51) - Add alert descriptions based on pump history verification **Code Quality Improvements:** - Fix duplicate enum keys in events.json (Sensor Type codes 12, 13) - Add logging infrastructure to generic.py for event diagnostics - Add conftest.py test configuration **DateTime and API Improvements:** - Fix format_datetime() for proper UTC conversion with Z suffix - Simplify Nightscout API methods by removing redundant retry logic - Improve error reporting in last_uploaded_entry() and last_uploaded_bg_entry() **Test Coverage:** - Add 3 FSL3 test cases with real pump data - Test single reading processing, multiple readings, and JOIN event parsing - All 105 tests passing (102 existing + 3 new FSL3 tests)
This commit is contained in:
committed by
James Woglom
parent
d78d70adf5
commit
594ee19450
@@ -0,0 +1,10 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Set timezone BEFORE importing any tconnectsync modules
|
||||
os.environ['TIMEZONE_NAME'] = 'America/New_York'
|
||||
|
||||
# Remove any cached imports of tconnectsync modules to force reimport with new env
|
||||
for module_name in list(sys.modules.keys()):
|
||||
if module_name.startswith('tconnectsync'):
|
||||
del sys.modules[module_name]
|
||||
@@ -354,5 +354,68 @@ class TestProcessCGMReadingMultipleTimezones(unittest.TestCase):
|
||||
self.assertEqual(len(p), 1)
|
||||
self.assertEqual(p[0]['dateString'], '2025-12-13T18:16:44+0000')
|
||||
|
||||
|
||||
# FSL3 events (real data from pump sync)
|
||||
# timestamp 2026-03-15T13:12:57-05:00, seqNum=785470, sgv=149
|
||||
FSL3_DATA_EVENT_1 = b'\x01\xe0"=-\xd9\x00\x0b\xfc>\x00\x00 \x00\x00\x95\xb5d"=-\xd9\x00\x00#\xe0'
|
||||
# timestamp 2026-03-15T13:13:56-05:00, seqNum=785472, sgv=161
|
||||
FSL3_DATA_EVENT_2 = b'\x01\xe0"=.\x14\x00\x0b\xfc@\x00\x00 \x00\x00\x95\xb5d"=.\x14\x00\x00#\xe0'
|
||||
# timestamp 2026-03-09T17:39:22-05:00, seqNum=749962 (JOIN event)
|
||||
FSL3_JOIN_EVENT_1 = b'\x01\xdd"5\x83J\x00\x0bq\x8ai\xaf\x05\xc1i\xaf\x05\xc8\x00\x00\t\x0f\x00\x13\xc6\x80'
|
||||
|
||||
|
||||
class TestProcessCGMReadingFSL3(unittest.TestCase):
|
||||
"""Test with FSL3 reading data"""
|
||||
maxDiff = None
|
||||
|
||||
def setUp(self):
|
||||
self.tconnect = TConnectApi()
|
||||
self.nightscout = NightscoutApi()
|
||||
self.nightscout.last_uploaded_bg_entry = lambda *args, **kwargs: None
|
||||
self.tconnect_device_id = 'abcdef'
|
||||
self.process = ProcessCGMReading(self.tconnect, self.nightscout, self.tconnect_device_id, pretend=False, timezone='America/New_York')
|
||||
|
||||
def test_single_fsl3_reading_no_last_uploaded(self):
|
||||
"""Test processing a single FSL3 CGM reading with no prior uploads"""
|
||||
events = [Event(FSL3_DATA_EVENT_1)]
|
||||
|
||||
self.assertEqual(type(events[0]), eventtypes.LidCgmDataFsl3)
|
||||
self.assertEqual(events[0].seqNum, 785470)
|
||||
self.assertEqual(events[0].currentglucosedisplayvalue, 149)
|
||||
|
||||
p = self.process.process(events, time_start=None, time_end=None)
|
||||
|
||||
self.assertEqual(len(p), 1)
|
||||
self.assertIn('sgv', p[0])
|
||||
self.assertEqual(p[0]['sgv'], 149)
|
||||
|
||||
def test_multiple_fsl3_readings(self):
|
||||
"""Test processing multiple FSL3 CGM readings"""
|
||||
events = [
|
||||
Event(FSL3_DATA_EVENT_1),
|
||||
Event(FSL3_DATA_EVENT_2)
|
||||
]
|
||||
|
||||
# Verify all events are LidCgmDataFsl3
|
||||
for event in events:
|
||||
self.assertEqual(type(event), eventtypes.LidCgmDataFsl3)
|
||||
|
||||
self.assertEqual(events[0].currentglucosedisplayvalue, 149)
|
||||
self.assertEqual(events[1].currentglucosedisplayvalue, 149)
|
||||
|
||||
p = self.process.process(events, time_start=None, time_end=None)
|
||||
|
||||
self.assertEqual(len(p), 2)
|
||||
|
||||
# Check glucose values
|
||||
self.assertEqual(p[0]['sgv'], 149)
|
||||
self.assertEqual(p[1]['sgv'], 149)
|
||||
|
||||
def test_fsl3_join_event_parses(self):
|
||||
"""Test that FSL3 JOIN event parses correctly"""
|
||||
events = [Event(FSL3_JOIN_EVENT_1)]
|
||||
|
||||
self.assertEqual(type(events[0]), eventtypes.LidCgmJoinSessionFsl3)
|
||||
self.assertEqual(events[0].seqNum, 749962)
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user