Files
tconnectsync/tests/eventparser/events/test_lidaapcmchange.py
T
James Woglom ee7384cc31 Sync events.json to upstream schema; preserve camelCase attribute names
Copy the exact eventSchema.json to events.json (camelCase keys) and fix
build_events.py's fieldNameFormat to preserve camelCase instead of collapsing
it via .title() (which turned schema keys like commandedRate into commandedrate).
Regenerate events.py so attributes are clean camelCase (commandedRate,
currentGlucoseDisplayValue, egvTimeStamp, bolusId, ...); acronyms follow the
schema's own casing (bg, iob, rssi). Update the battery transform and all
attribute references in the process handlers and tests to match.
2026-07-01 06:50:30 +00:00

148 lines
6.4 KiB
Python

#!/usr/bin/env python3
import json
import unittest
from tconnectsync.eventparser.generic import Event
from tconnectsync.eventparser import events as eventtypes
from tconnectsync.eventparser.raw_event import RawEvent
class TestLidAaPcmChange(unittest.TestCase):
"""230 LID_AA_PCM_CHANGE: currentPcm/previousPcm resolve to a PCM enum,
and the boolean-ish fields resolve to False/True enum members. All
fixtures are real captured events copied verbatim."""
maxDiff = None
def setUp(self):
# currentPcm:0 (NoControl) from previousPcm:3 (ClosedLoop), suspended.
self.fixtureSuspendedNoControl = {
"deviceAssignmentId": "4ff6bebc-d4d6-4423-b123-eecfcf5a4238",
"eventCode": 230,
"sequenceGroup": 0,
"sequenceNumber": 394337,
"pumpDateTime": "2026-04-30T10:01:49",
"eventProperties": {
"currentPcm": 0, "previousPcm": 3, "pumpSuspended": 1,
"calculationAvailable": 1, "cgmAvailable": 1,
"closedLoopPreferred": 1, "sufficientClosedLoopParams": 1,
},
"estimatedDateTime": "2026-04-30T10:01:49Z",
}
# currentPcm:3 (ClosedLoop) from previousPcm:0 (NoControl), not suspended.
self.fixtureResumedClosedLoop = {
"deviceAssignmentId": "4ff6bebc-d4d6-4423-b123-eecfcf5a4238",
"eventCode": 230,
"sequenceGroup": 0,
"sequenceNumber": 394430,
"pumpDateTime": "2026-04-30T10:16:31",
"eventProperties": {
"currentPcm": 3, "previousPcm": 0, "pumpSuspended": 0,
"calculationAvailable": 1, "cgmAvailable": 1,
"closedLoopPreferred": 1, "sufficientClosedLoopParams": 1,
},
"estimatedDateTime": "2026-04-30T10:16:31Z",
}
# currentPcm:2 (Pining) with cgmAvailable:0 -> FalseVal boolean-ish field.
self.fixturePiningNoCgm = {
"deviceAssignmentId": "4ff6bebc-d4d6-4423-b123-eecfcf5a4238",
"eventCode": 230,
"sequenceGroup": 0,
"sequenceNumber": 409128,
"pumpDateTime": "2026-05-04T18:58:22",
"eventProperties": {
"currentPcm": 2, "previousPcm": 3, "pumpSuspended": 0,
"calculationAvailable": 1, "cgmAvailable": 0,
"closedLoopPreferred": 1, "sufficientClosedLoopParams": 1,
},
"estimatedDateTime": "2026-05-04T18:58:22Z",
}
def test_dispatches_to_correct_class(self):
ev = Event(self.fixtureSuspendedNoControl)
self.assertIsInstance(ev, eventtypes.LidAaPcmChange)
self.assertNotIsInstance(ev, RawEvent)
def test_envelope_fields(self):
ev = Event(self.fixtureSuspendedNoControl)
self.assertEqual(ev.eventId, 230)
self.assertEqual(ev.seqNum, 394337)
def test_timestamp_preserves_wall_clock(self):
ev = Event(self.fixtureSuspendedNoControl)
self.assertEqual(ev.eventTimestamp.format('YYYY-MM-DDTHH:mm:ss'),
"2026-04-30T10:01:49")
def test_pcm_enums_no_control_from_closed_loop(self):
# currentPcm:0 -> NoControl, previousPcm:3 -> ClosedLoop
ev = Event(self.fixtureSuspendedNoControl)
self.assertEqual(ev.currentPcmRaw, 0)
self.assertEqual(ev.currentPcm,
eventtypes.LidAaPcmChange.CurrentpcmEnum.NoControl)
self.assertEqual(ev.previousPcmRaw, 3)
self.assertEqual(ev.previousPcm,
eventtypes.LidAaPcmChange.PreviouspcmEnum.ClosedLoop)
def test_pcm_enums_closed_loop_from_no_control(self):
# currentPcm:3 -> ClosedLoop, previousPcm:0 -> NoControl
ev = Event(self.fixtureResumedClosedLoop)
self.assertEqual(ev.currentPcm,
eventtypes.LidAaPcmChange.CurrentpcmEnum.ClosedLoop)
self.assertEqual(ev.previousPcm,
eventtypes.LidAaPcmChange.PreviouspcmEnum.NoControl)
def test_pcm_enum_pining(self):
# currentPcm:2 -> Pining
ev = Event(self.fixturePiningNoCgm)
self.assertEqual(ev.currentPcmRaw, 2)
self.assertEqual(ev.currentPcm,
eventtypes.LidAaPcmChange.CurrentpcmEnum.Pining)
def test_boolean_fields_when_suspended(self):
ev = Event(self.fixtureSuspendedNoControl)
self.assertEqual(ev.pumpSuspendedRaw, 1)
self.assertEqual(ev.pumpSuspended,
eventtypes.LidAaPcmChange.PumpsuspendedEnum.TrueVal)
self.assertEqual(ev.calculationAvailable,
eventtypes.LidAaPcmChange.CalculationavailableEnum.TrueVal)
self.assertEqual(ev.cgmAvailable,
eventtypes.LidAaPcmChange.CgmavailableEnum.TrueVal)
self.assertEqual(ev.closedLoopPreferred,
eventtypes.LidAaPcmChange.ClosedlooppreferredEnum.TrueVal)
self.assertEqual(ev.sufficientClosedLoopParams,
eventtypes.LidAaPcmChange.SufficientclosedloopparamsEnum.TrueVal)
def test_pump_suspended_false(self):
# pumpSuspended:0 -> FalseVal (0 must not be treated as missing)
ev = Event(self.fixtureResumedClosedLoop)
self.assertEqual(ev.pumpSuspendedRaw, 0)
self.assertEqual(ev.pumpSuspended,
eventtypes.LidAaPcmChange.PumpsuspendedEnum.FalseVal)
def test_cgm_available_false(self):
# cgmAvailable:0 -> FalseVal while other boolean-ish fields stay TrueVal
ev = Event(self.fixturePiningNoCgm)
self.assertEqual(ev.cgmAvailableRaw, 0)
self.assertEqual(ev.cgmAvailable,
eventtypes.LidAaPcmChange.CgmavailableEnum.FalseVal)
self.assertEqual(ev.calculationAvailable,
eventtypes.LidAaPcmChange.CalculationavailableEnum.TrueVal)
self.assertEqual(ev.closedLoopPreferred,
eventtypes.LidAaPcmChange.ClosedlooppreferredEnum.TrueVal)
def test_todict_is_json_serializable(self):
for fixture in (self.fixtureSuspendedNoControl,
self.fixtureResumedClosedLoop,
self.fixturePiningNoCgm):
ev = Event(fixture)
d = ev.todict()
json.dumps(d) # must not raise
self.assertEqual(d["id"], 230)
self.assertEqual(d["name"], "LID_AA_PCM_CHANGE")
if __name__ == "__main__":
unittest.main()