From 9bae53e53a78a8a5056fe5a3fd78d8233ae6752c Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 10 Jun 2018 21:50:49 +0100 Subject: [PATCH] - update on initial checkin (code is now same as in RileyLinkAAPS on 10.June - most command working) - it will take some time until code is actually integrated into AAPS, but at least now all files are available --- app/build.gradle | 9 +- .../AppCompatPreferenceActivity.java | 109 --- .../com/gxwtech/roundtrip2/AutoStart.java | 21 - .../CommunicationService.java | 279 ------- .../CommunicationService/Objects/Bolus.java | 91 -- .../Objects/DateDeserializer.java | 20 - .../Objects/Integration.java | 216 ----- .../Objects/IntegrationSerializer.java | 35 - .../Objects/RealmManager.java | 23 - .../Objects/TempBasal.java | 179 ---- .../HistoryPageDetailActivity.txt | 83 -- .../HistoryPageDetailFragment.txt | 70 -- .../HistoryPageListActivity.txt | 230 ------ .../HistoryPageListContent.java | 94 --- .../com/gxwtech/roundtrip2/MainActivity.txt | 614 -------------- .../java/com/gxwtech/roundtrip2/MainApp.txt | 48 -- .../java/com/gxwtech/roundtrip2/RT2Const.java | 135 --- .../com/gxwtech/roundtrip2/RileyLinkScan.txt | 343 -------- .../RileyLink/FrequencyScanResults.java | 21 - .../RileyLink/FrequencyTrial.java | 11 - .../RileyLink/PumpManager.java | 599 -------------- .../RileyLink/PumpManagerStatus.java | 61 -- .../RileyLink/RawHistoryPage.java | 45 - .../BLECommOperations/BLECommOperation.java | 20 - .../BLECommOperationResult.java | 16 - .../CharacteristicReadOperation.java | 62 -- .../CharacteristicWriteOperation.java | 66 -- .../DescriptorWriteOperation.java | 56 -- .../RileyLinkBLE/GattAttributes.java | 52 -- .../RoundtripService/RileyLinkBLE/RFSpy.java | 203 ----- .../RileyLinkBLE/RFSpyReader.java | 117 --- .../RileyLinkBLE/RFSpyResponse.java | 75 -- .../RileyLinkBLE/RFTools.java | 295 ------- .../RileyLinkBLE/RadioPacket.java | 24 - .../RileyLinkBLE/RadioResponse.java | 67 -- .../RileyLinkBLE/RileyLinkBLE.java | 428 ---------- .../RoundtripService/RoundtripService.java | 638 -------------- .../RoundtripServiceIPCConnection.java | 165 ---- .../Tasks/DiscoverGattServicesTask.java | 15 - .../Tasks/FetchPumpHistoryTask.java | 40 - .../Tasks/InitializePumpManagerTask.java | 42 - .../RoundtripService/Tasks/PumpTask.java | 13 - .../Tasks/ReadBolusWizardCarbProfileTask.java | 24 - .../Tasks/ReadISFProfileTask.java | 37 - .../Tasks/ReadPumpClockTask.java | 29 - .../Tasks/RetrieveHistoryPageTask.java | 37 - .../RoundtripService/Tasks/ServiceTask.java | 50 -- .../Tasks/ServiceTaskExecutor.java | 42 - .../Tasks/UpdatePumpStatusTask.java | 58 -- .../Tasks/WakeAndTuneTask.java | 22 - .../ButtonPressCarelinkMessageBody.java | 23 - .../Messages/CarelinkLongMessageBody.java | 36 - .../Messages/CarelinkShortMessageBody.java | 38 - .../GetHistoryPageCarelinkMessageBody.java | 50 -- .../GetPumpModelCarelinkMessageBody.java | 31 - .../medtronic/Messages/MessageBody.java | 10 - .../medtronic/Messages/MessageType.java | 105 --- .../Messages/PumpAckMessageBody.java | 11 - .../Messages/UnknownMessageBody.java | 35 - .../medtronic/PacketType.java | 20 - .../medtronic/PumpData/BasalProfile.java | 175 ---- .../medtronic/PumpData/BasalProfileEntry.java | 28 - .../PumpData/BasalProfileTypeEnum.java | 8 - .../medtronic/PumpData/HistoryReport.java | 31 - .../medtronic/PumpData/HtmlByte.java | 11 - .../medtronic/PumpData/HtmlCodeTagEnd.java | 9 - .../medtronic/PumpData/HtmlCodeTagStart.java | 30 - .../medtronic/PumpData/HtmlElement.java | 9 - .../PumpData/HtmlElementGeneric.java | 15 - .../PumpData/HtmlHistoryPageStart.java | 15 - .../medtronic/PumpData/ISFTable.java | 102 --- .../medtronic/PumpData/Page.java | 409 --------- .../PumpData/PumpHistoryDatabaseEntry.java | 51 -- .../PumpData/PumpHistoryDatabaseHandler.java | 57 -- .../PumpData/PumpHistoryManager.java | 341 -------- .../medtronic/PumpData/PumpHistoryPage.java | 43 - .../medtronic/PumpData/PumpHistoryParser.java | 263 ------ .../medtronic/PumpData/PumpSettings.java | 168 ---- .../medtronic/PumpData/TempBasalPair.java | 45 - .../records/AlarmClockReminderPumpEvent.java | 13 - .../records/AlarmSensorPumpEvent.java | 19 - .../PumpData/records/BGReceivedPumpEvent.java | 47 -- .../PumpData/records/BasalProfileStart.java | 51 -- .../PumpData/records/BatteryPumpEvent.java | 10 - .../records/BolusNormalPumpEvent.java | 86 -- .../BolusWizardBolusEstimatePumpEvent.java | 118 --- .../PumpData/records/CalBgForPhPumpEvent.java | 39 - .../ChangeAlarmClockEnablePumpEvent.java | 13 - .../ChangeAlarmNotifyModePumpEvent.java | 10 - .../records/ChangeAudioBolusPumpEvent.java | 13 - .../ChangeBGReminderEnablePumpEvent.java | 13 - .../ChangeBasalProfilePatternPumpEvent.java | 21 - .../records/ChangeBasalProfilePumpEvent.java | 15 - .../ChangeBolusReminderEnablePumpEvent.java | 19 - .../ChangeBolusReminderTimePumpEvent.java | 19 - .../ChangeBolusScrollStepSizePumpEvent.java | 13 - .../ChangeBolusWizardSetupPumpEvent.java | 21 - .../ChangeCaptureEventEnablePumpEvent.java | 13 - .../records/ChangeCarbUnitsPumpEvent.java | 13 - .../ChangeChildBlockEnablePumpEvent.java | 13 - .../records/ChangeMaxBolusPumpEvent.java | 13 - .../records/ChangeOtherDeviceIDPumpEvent.java | 19 - .../ChangeReservoirWarningTimePumpEvent.java | 13 - ...SensorRateOfChangeAlertSetupPumpEvent.java | 19 - .../records/ChangeSensorSetup2PumpEvent.java | 19 - .../records/ChangeTempBasalTypePumpEvent.java | 44 - .../records/ChangeTimeFormatPumpEvent.java | 11 - .../PumpData/records/ChangeTimePumpEvent.java | 18 - .../records/ChangeVariableBolusPumpEvent.java | 13 - .../ChangeWatchdogEnablePumpEvent.java | 13 - ...hangeWatchdogMarriageProfilePumpEvent.java | 19 - .../PumpData/records/ClearAlarmPumpEvent.java | 10 - .../DeleteAlarmClockTimePumpEvent.java | 19 - .../DeleteBolusReminderTimePumpEvent.java | 19 - .../records/DeleteOtherDeviceIDPumpEvent.java | 19 - .../records/EnableDisableRemotePumpEvent.java | 17 - .../PumpData/records/InsulinMarkerEvent.java | 23 - .../JournalEntryExerciseMarkerPumpEvent.java | 18 - .../JournalEntryPumpLowBatteryPumpEvent.java | 10 - ...JournalEntryPumpLowReservoirPumpEvent.java | 10 - .../Model522ResultTotalsPumpEvent.java | 15 - .../PumpData/records/NewTimeSet.java | 15 - .../PumpData/records/PrimePumpEvent.java | 51 -- .../PumpData/records/PumpAlarmPumpEvent.java | 42 - .../medtronic/PumpData/records/Record.java | 92 --- .../PumpData/records/RecordTypeEnum.java | 126 --- .../records/ResultDailyTotalPumpEvent.java | 34 - .../PumpData/records/ResumePumpEvent.java | 10 - .../PumpData/records/RewindPumpEvent.java | 10 - .../PumpData/records/Sara6EPumpEvent.java | 36 - .../PumpData/records/SuspendPumpEvent.java | 10 - .../records/TempBasalDurationPumpEvent.java | 42 - .../records/TempBasalRatePumpEvent.java | 54 -- .../PumpData/records/TimeStampedRecord.java | 74 -- .../PumpData/records/UnabsorbedInsulin.java | 94 --- .../PumpData/records/Unknown7ByteEvent1.java | 13 - .../medtronic/PumpMessage.java | 71 -- .../RoundtripService/medtronic/PumpModel.java | 55 -- .../medtronic/PumpTimeStamp.java | 35 - .../medtronic/TempBasalEvent.java | 29 - .../medtronic/TimeFormat.java | 82 -- .../RoundtripServiceClientConnection.java | 133 --- .../roundtrip2/ServiceClientConnection.java | 142 ---- .../roundtrip2/ServiceData/BasalProfile.java | 47 -- .../ServiceData/BolusWizardCarbProfile.java | 27 - .../ServiceData/FetchPumpHistoryResult.java | 35 - .../roundtrip2/ServiceData/ISFProfile.java | 29 - .../ServiceData/PumpModelResult.java | 27 - .../ServiceData/PumpStatusResult.java | 137 ---- .../ServiceData/ReadPumpClockResult.java | 62 -- .../RetrieveHistoryPageResult.java | 22 - .../ServiceData/ServiceClientActions.java | 138 ---- .../ServiceData/ServiceMessage.java | 24 - .../ServiceData/ServiceMessageUpdate.java | 12 - .../roundtrip2/ServiceData/ServiceResult.java | 76 -- .../ServiceData/ServiceTransport.java | 126 --- .../ServiceData/TimeValueProfile.java | 126 --- .../ServiceMessageView.java | 35 - .../ServiceMessageViewDetailActivity.txt | 83 -- .../ServiceMessageViewDetailFragment.txt | 69 -- .../ServiceMessageViewItem.java | 25 - .../ServiceMessageViewListActivity.txt | 203 ----- .../gxwtech/roundtrip2/SettingsActivity.txt | 208 ----- .../gxwtech/roundtrip2/TreatmentHistory.txt | 320 -------- .../com/gxwtech/roundtrip2/util/ByteUtil.java | 146 ---- .../java/com/gxwtech/roundtrip2/util/CRC.java | 74 -- .../com/gxwtech/roundtrip2/util/Check.java | 98 --- .../com/gxwtech/roundtrip2/util/HexDump.java | 162 ---- .../gxwtech/roundtrip2/util/StringUtil.java | 37 - .../gxwtech/roundtrip2/util/ThreadUtil.java | 17 - .../com/gxwtech/roundtrip2/util/tools.java | 115 --- .../plugins/PumpCommon/data/PumpStatus.java | 30 + .../dialog/RileyLinkBLEScanActivity.java | 25 +- .../dialog/RileyLinkSettingsTab1.java | 19 +- .../RileyLinkCommunicationManager.java | 168 +++- .../hw/rileylink/RileyLinkConst.java | 14 + .../hw/rileylink/RileyLinkUtil.java | 174 +++- .../PumpCommon/hw/rileylink/ble/RFSpy.java | 189 +++-- .../hw/rileylink/ble/RFSpyReader.java | 25 +- .../PumpCommon/hw/rileylink/ble/RFTools.java | 17 +- .../hw/rileylink/ble/RileyLinkBLE.java | 59 +- .../hw/rileylink/ble/data/RadioPacket.java | 7 + .../hw/rileylink/ble/data/RadioResponse.java | 3 + .../hw/rileylink/ble/defs/CC111XRegister.java | 47 ++ .../hw/rileylink/ble/defs/RFSpyCommand.java | 26 + .../hw/rileylink/ble/defs/RLMessage.java | 10 + .../hw/rileylink/ble/defs/RLMessageType.java | 11 + .../hw/rileylink/ble/defs/RXFilterMode.java | 19 + .../ble/defs/RileyLinkTargetDevice.java | 11 + .../ble/defs/RileyLinkTargetFrequency.java | 38 + .../hw/rileylink/data/RLHistoryItem.java | 50 +- .../RileyLinkError.java} | 7 +- .../rileylink/defs/RileyLinkServiceState.java | 45 + .../defs/RileyLinkTargetDevice.java | 2 +- .../rileylink/service/RileyLinkService.java | 346 ++++---- .../service/RileyLinkServiceData.java | 7 +- .../service/RileyLinkServiceState.java | 30 - .../service/data}/ServiceCommand.java | 19 +- .../service/data/ServiceMessage.java | 40 + .../service/data}/ServiceNotification.java | 17 +- .../rileylink/service/data/ServiceResult.java | 96 +++ .../{tasks => data}/ServiceTransport.java | 45 +- .../service/data/ServiceTransportType.java | 15 + .../tasks/DiscoverGattServicesTask.java | 3 +- .../tasks/InitializePumpManagerTask.java | 60 ++ .../hw/rileylink/service/tasks/PumpTask.java | 17 + .../rileylink/service/tasks/ServiceTask.java | 9 +- .../service/tasks/ServiceTaskExecutor.java | 5 + .../service/tasks/WakeAndTuneTask.java | 28 + .../plugins/PumpCommon/utils/ByteUtil.java | 120 ++- .../plugins/PumpCommon/utils/CRC.java | 38 +- .../plugins/PumpCommon/utils/HexDump.java | 91 +- .../PumpCommon/utils}/LocationHelper.java | 36 +- .../plugins/PumpCommon/utils/StringUtil.java | 48 +- .../plugins/PumpCommon/utils/ThreadUtil.java | 2 + .../PumpMedtronic/MedtronicFragment.java | 9 + .../PumpMedtronic/MedtronicPumpPlugin.java | 57 +- .../comm/MedtronicCommunicationManager.java | 744 +++++++++++------ .../PumpMedtronic/comm/data/BasalProfile.java | 88 +- .../comm/data/BasalProfileEntry.java | 35 +- .../plugins/PumpMedtronic/comm/data/Page.java | 100 ++- .../PumpMedtronic/comm/data/PumpModel.java | 58 -- .../comm/data/RawHistoryPage.java | 32 +- .../comm/data/TempBasalPair.java | 85 +- .../comm/data/history/Record.java | 36 +- .../comm/data/history/RecordTypeEnum.java | 233 ++++-- .../comm/data/history/TimeStampedRecord.java | 14 +- .../history/record/BGReceivedPumpEvent.java | 11 +- .../history/record/BasalProfileStart.java | 11 +- .../history/record/BolusNormalPumpEvent.java | 16 +- .../BolusWizardBolusEstimatePumpEvent.java | 26 +- .../history/record/CalBgForPhPumpEvent.java | 10 +- .../record/ChangeTempBasalTypePumpEvent.java | 10 +- .../history/record/IgnoredHistoryEntry.java | 54 ++ .../comm/data/history/record/NewTimeSet.java | 6 +- .../data/history/record/PrimePumpEvent.java | 11 +- .../history/record/PumpAlarmPumpEvent.java | 11 +- .../record/ResultDailyTotalPumpEvent.java | 9 +- .../data/history/record/Sara6EPumpEvent.java | 8 +- .../record/TempBasalDurationPumpEvent.java | 11 +- .../record/TempBasalRatePumpEvent.java | 13 +- .../history/record/UnabsorbedInsulin.java | 19 +- .../history2/MedtronicHistoryDecoder.java | 190 +++++ .../data/history2/MedtronicHistoryEntry.java | 213 +++++ .../history2/MedtronicPumpHistoryDecoder.java | 775 ++++++++++++++++++ .../comm/data/history2/PumpHistoryEntry.java | 92 +++ .../data/history2/PumpHistoryEntryType.java | 411 ++++++++++ .../data/history2/RecordDecodeStatus.java | 49 ++ .../comm/message/CarelinkLongMessageBody.java | 7 +- .../message/CarelinkShortMessageBody.java | 9 + .../comm/message/MedtronicConverter.java | 360 ++++++++ .../comm/message/MessageBody.java | 21 + .../comm/message/MessageType.java | 55 +- .../comm/message/PacketType.java | 18 +- .../comm/message/PumpMessage.java | 160 +++- .../PumpMedtronic/data/dto/BolusDTO.java | 138 ++++ .../data/dto/BolusWizardDTO.java | 39 + .../PumpMedtronic/data/dto/PumpBolusType.java | 134 +++ .../data/dto/PumpSettingDTO.java | 23 + .../data/dto/PumpTimeStampedRecord.java | 31 + .../data/dto/TemporaryBasalRateDTO.java | 115 +++ .../PumpMedtronic/defs/BatteryType.java | 20 + .../defs/MedtronicCommandType.java | 436 ++++++++++ .../defs/MedtronicConverterType.java | 20 + .../defs/MedtronicDeviceType.java | 151 ++++ .../PumpMedtronic/defs/MinimedTargetType.java | 36 + .../defs/PumpConfigurationGroup.java | 58 ++ .../driver/MedtronicPumpStatus.java | 17 +- .../events/EventMedtronicNewStatus.java | 2 +- .../EventMedtronicRileyLinkStatusChange.java | 9 + .../medtronic/defs/MedtronicPumpType.java | 144 ---- .../service/RileyLinkMedtronicService.java | 253 +++--- .../service/data/MedtronicPumpResult.java | 96 +++ .../service/tasks/MedtronicPumpTask.java | 86 ++ .../PumpMedtronic/util/MedtronicConst.java | 6 +- .../PumpMedtronic/util/MedtronicUtil.java | 123 ++- app/src/main/res/values/strings.xml | 4 + 277 files changed, 6819 insertions(+), 14135 deletions(-) delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/AppCompatPreferenceActivity.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/AutoStart.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/CommunicationService.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Bolus.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/DateDeserializer.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Integration.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/IntegrationSerializer.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/RealmManager.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/TempBasal.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailFragment.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListContent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/MainActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/MainApp.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RT2Const.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RileyLinkScan.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyScanResults.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyTrial.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManager.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManagerStatus.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/RawHistoryPage.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperation.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperationResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicReadOperation.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicWriteOperation.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/DescriptorWriteOperation.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/GattAttributes.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpy.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpyReader.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpyResponse.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFTools.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioPacket.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioResponse.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RileyLinkBLE.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripService.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripServiceIPCConnection.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/DiscoverGattServicesTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/FetchPumpHistoryTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/InitializePumpManagerTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/PumpTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadBolusWizardCarbProfileTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadISFProfileTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadPumpClockTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/RetrieveHistoryPageTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTaskExecutor.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/UpdatePumpStatusTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/WakeAndTuneTask.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/ButtonPressCarelinkMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/CarelinkLongMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/CarelinkShortMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/GetHistoryPageCarelinkMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/GetPumpModelCarelinkMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageType.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/PumpAckMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/UnknownMessageBody.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PacketType.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfile.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfileEntry.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfileTypeEnum.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HistoryReport.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlByte.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagEnd.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagStart.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElement.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElementGeneric.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlHistoryPageStart.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/ISFTable.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/Page.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryDatabaseEntry.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryDatabaseHandler.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryManager.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryPage.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryParser.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpSettings.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/TempBasalPair.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmClockReminderPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmSensorPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BGReceivedPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BasalProfileStart.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BatteryPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusNormalPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusWizardBolusEstimatePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/CalBgForPhPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmClockEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmNotifyModePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAudioBolusPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBGReminderEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePatternPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderTimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusScrollStepSizePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusWizardSetupPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCaptureEventEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCarbUnitsPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeChildBlockEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeMaxBolusPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeOtherDeviceIDPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeReservoirWarningTimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorRateOfChangeAlertSetupPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorSetup2PumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTempBasalTypePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimeFormatPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeVariableBolusPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogEnablePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogMarriageProfilePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ClearAlarmPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteAlarmClockTimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteBolusReminderTimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteOtherDeviceIDPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/EnableDisableRemotePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/InsulinMarkerEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryExerciseMarkerPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowBatteryPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowReservoirPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Model522ResultTotalsPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/NewTimeSet.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PrimePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PumpAlarmPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Record.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RecordTypeEnum.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResultDailyTotalPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResumePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RewindPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Sara6EPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/SuspendPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalDurationPumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalRatePumpEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TimeStampedRecord.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/UnabsorbedInsulin.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Unknown7ByteEvent1.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpMessage.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpModel.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpTimeStamp.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TempBasalEvent.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TimeFormat.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/RoundtripServiceClientConnection.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceClientConnection.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BasalProfile.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BolusWizardCarbProfile.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/FetchPumpHistoryResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ISFProfile.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpModelResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpStatusResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ReadPumpClockResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/RetrieveHistoryPageResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceClientActions.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessage.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessageUpdate.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceResult.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceTransport.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceData/TimeValueProfile.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageView.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailFragment.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewItem.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewListActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/SettingsActivity.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/TreatmentHistory.txt delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/ByteUtil.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/CRC.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/Check.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/HexDump.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/StringUtil.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/ThreadUtil.java delete mode 100644 app/src/main/java/com/gxwtech/roundtrip2/util/tools.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/CC111XRegister.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessageType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RXFilterMode.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java rename app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/{service/RileyLinkErrorCode.java => defs/RileyLinkError.java} (68%) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java rename app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/{ => hw/rileylink}/defs/RileyLinkTargetDevice.java (62%) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceState.java rename app/src/main/java/{com/gxwtech/roundtrip2/ServiceData => info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data}/ServiceCommand.java (82%) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceMessage.java rename app/src/main/java/{com/gxwtech/roundtrip2/ServiceData => info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data}/ServiceNotification.java (77%) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceResult.java rename app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/{tasks => data}/ServiceTransport.java (83%) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransportType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/PumpTask.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java rename app/src/main/java/{com/gxwtech/roundtrip2/util => info/nightscout/androidaps/plugins/PumpCommon/utils}/LocationHelper.java (69%) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/PumpModel.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/IgnoredHistoryEntry.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryDecoder.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryEntry.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicPumpHistoryDecoder.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntry.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntryType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/RecordDecodeStatus.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusDTO.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusWizardDTO.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpBolusType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpSettingDTO.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpTimeStampedRecord.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/TemporaryBasalRateDTO.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/BatteryType.java create mode 100755 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicConverterType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicDeviceType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MinimedTargetType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/PumpConfigurationGroup.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicRileyLinkStatusChange.java delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/medtronic/defs/MedtronicPumpType.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/data/MedtronicPumpResult.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/tasks/MedtronicPumpTask.java diff --git a/app/build.gradle b/app/build.gradle index 567117a398..f53f766ed4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,7 +57,7 @@ def generateGitBuild = { -> return stringBuilder.toString() } -tasks.matching {it instanceof Test}.all { +tasks.matching { it instanceof Test }.all { testLogging.events = ["failed", "skipped", "started"] testLogging.exceptionFormat = "full" } @@ -97,7 +97,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - testCoverageEnabled (project.hasProperty('coverage') ? true : false) + testCoverageEnabled(project.hasProperty('coverage') ? true : false) } } productFlavors { @@ -164,7 +164,7 @@ android { unitTests.returnDefaultValues = true unitTests.includeAndroidResources = true } - } +} allprojects { repositories { @@ -207,6 +207,7 @@ dependencies { exclude group: "com.google.android", module: "android" } implementation "org.apache.commons:commons-lang3:3.6" + implementation "commons-collections:commons-collections:3.2.1" implementation "org.slf4j:slf4j-api:1.7.12" implementation "com.jjoe64:graphview:4.0.1" implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1" @@ -252,7 +253,7 @@ dependencies { } task unzip(type: Copy) { - def zipPath = configurations.libs.find {it.name.startsWith("danars") } + def zipPath = configurations.libs.find { it.name.startsWith("danars") } def zipFile = file(zipPath) def outputDir = file("${buildDir}/unpacked/dist") diff --git a/app/src/main/java/com/gxwtech/roundtrip2/AppCompatPreferenceActivity.java b/app/src/main/java/com/gxwtech/roundtrip2/AppCompatPreferenceActivity.java deleted file mode 100644 index a2b4bd050d..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/AppCompatPreferenceActivity.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.support.annotation.LayoutRes; -import android.support.annotation.Nullable; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatDelegate; -import android.support.v7.widget.Toolbar; -import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; - -/** - * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls - * to be used with AppCompat. - */ -public abstract class AppCompatPreferenceActivity extends PreferenceActivity { - - private AppCompatDelegate mDelegate; - - @Override - protected void onCreate(Bundle savedInstanceState) { - getDelegate().installViewFactory(); - getDelegate().onCreate(savedInstanceState); - super.onCreate(savedInstanceState); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - getDelegate().onPostCreate(savedInstanceState); - } - - public ActionBar getSupportActionBar() { - return getDelegate().getSupportActionBar(); - } - - public void setSupportActionBar(@Nullable Toolbar toolbar) { - getDelegate().setSupportActionBar(toolbar); - } - - @Override - public MenuInflater getMenuInflater() { - return getDelegate().getMenuInflater(); - } - - @Override - public void setContentView(@LayoutRes int layoutResID) { - getDelegate().setContentView(layoutResID); - } - - @Override - public void setContentView(View view) { - getDelegate().setContentView(view); - } - - @Override - public void setContentView(View view, ViewGroup.LayoutParams params) { - getDelegate().setContentView(view, params); - } - - @Override - public void addContentView(View view, ViewGroup.LayoutParams params) { - getDelegate().addContentView(view, params); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getDelegate().onPostResume(); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - super.onTitleChanged(title, color); - getDelegate().setTitle(title); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getDelegate().onConfigurationChanged(newConfig); - } - - @Override - protected void onStop() { - super.onStop(); - getDelegate().onStop(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - getDelegate().onDestroy(); - } - - public void invalidateOptionsMenu() { - getDelegate().invalidateOptionsMenu(); - } - - private AppCompatDelegate getDelegate() { - if (mDelegate == null) { - mDelegate = AppCompatDelegate.create(this, null); - } - return mDelegate; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/AutoStart.java b/app/src/main/java/com/gxwtech/roundtrip2/AutoStart.java deleted file mode 100644 index cc0df609be..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/AutoStart.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import com.gxwtech.roundtrip2.CommunicationService.CommunicationService; - -/** - * Created by Tim on 07/06/2016. - * Receives BOOT_COMPLETED Intent and starts service - */ -public class AutoStart extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - - context.startService(new Intent(context, CommunicationService.class)); - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/CommunicationService.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/CommunicationService.java deleted file mode 100644 index 79ceb678f5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/CommunicationService.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.res.Resources; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.util.Log; -import android.widget.Toast; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import com.gxwtech.roundtrip2.CommunicationService.Objects.Bolus; -import com.gxwtech.roundtrip2.CommunicationService.Objects.DateDeserializer; -import com.gxwtech.roundtrip2.CommunicationService.Objects.Integration; -import com.gxwtech.roundtrip2.CommunicationService.Objects.IntegrationSerializer; -import com.gxwtech.roundtrip2.CommunicationService.Objects.RealmManager; -import com.gxwtech.roundtrip2.CommunicationService.Objects.TempBasal; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.util.Check; - - -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.MainApp; - -/** - * Created by Tim on 07/06/2016. - * This service listens out for requests from HAPP and processes them - */ -public class CommunicationService extends android.app.Service { - - public CommunicationService(){} - final static String TAG = "CommunicationService"; - - class IncomingHandler extends Handler { - @Override - public void handleMessage(Message msg) { - String action = ""; - Long requested = 0L; - String safteyCheck = ""; - String pump = ""; - List remoteIntegrations; - List remoteTreatments; - Bundle data = new Bundle(); - RealmManager realmManager = new RealmManager(); - - Log.d(TAG, "START"); - try { - - /* - Expected Bundle data... - "ACTION" - What is this incoming request? Example: "NEW_TREATMENTS" - "DATE_REQUESTED" - When was this requested? So we can ignore old requests - "PUMP" - Name of the pump the APS expects this app to support - "INTEGRATION_OBJECTS" - Array of Integration Objects, details of the objects being synced. *OPTIONAL for NEW_TREATMENTS only* - "TREATMENT_OBJECTS" - Array of Objects themselves being synced, TempBasal or Bolus *OPTIONAL for NEW_TREATMENTS only* - */ - - data = msg.getData(); - action = data.getString(RT2Const.commService.ACTION); - requested = data.getLong(RT2Const.commService.DATE_REQUESTED, 0); - pump = data.getString(RT2Const.commService.PUMP); - Log.d("RECEIVED: ACTION", action); - Log.d("RECEIVED: DATE", requested.toString()); - Log.d("RECEIVED: PUMP", pump); - - } catch (Exception e) { - e.printStackTrace(); - // TODO: 16/01/2016 Issue getting treatment details from APS app msg for user - } - - - switch (action) { - case RT2Const.commService.INCOMING_TEST_MSG: - Resources appR = MainApp.instance().getResources(); - CharSequence txt = appR.getText(appR.getIdentifier("app_name", "string", MainApp.instance().getPackageName())); - Toast.makeText(MainApp.instance(), txt + ": Pump Driver App has connected successfully. ", Toast.LENGTH_LONG).show(); - Log.d(TAG, txt + ": APS app has connected successfully."); - - break; - case RT2Const.commService.INCOMING_NEW_TREATMENTS: - GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(Date.class, new DateDeserializer()); - Gson gson = gsonBuilder.create(); - - remoteIntegrations = gson.fromJson(data.getString(RT2Const.commService.INTEGRATION_OBJECTS), new TypeToken>() {}.getType()); - remoteTreatments = gson.fromJson(data.getString(RT2Const.commService.TREATMENT_OBJECTS), new TypeToken>() {}.getType()); - Log.d("RECEIVED: INTEGRATIONS", remoteIntegrations.toString()); - Log.d("RECEIVED: TREATMENTS", remoteTreatments.toString()); - - for (int i = 0; i < remoteIntegrations.size(); i++) { - - realmManager.getRealm().beginTransaction(); - - Integration integrationForAPS = remoteIntegrations.get(i); - integrationForAPS.setType ("aps_app"); - integrationForAPS.setState ("received"); - integrationForAPS.setToSync (true); - integrationForAPS.setDate_updated (new Date()); - integrationForAPS.setRemote_id(remoteIntegrations.get(i).getLocal_object_id()); - - Integration integrationForPump = new Integration(); - integrationForPump.setType ("pump"); - integrationForPump.setDate_updated (new Date()); - integrationForPump.setLocal_object(remoteIntegrations.get(i).getLocal_object()); - - String localObjectlID = "", localObjectState = "", localObjectDetails = "", rejectRequest = ""; - if (!Check.isPumpSupported(pump)) - rejectRequest += "Pump requested not supported. "; - if (Check.isRequestTooOld(requested)) rejectRequest += "Request too old. "; - - switch (remoteIntegrations.get(i).getLocal_object()) { - case "temp_basal": - TempBasal tempBasal = gson.fromJson(remoteTreatments.get(i), TempBasal.class); - realmManager.getRealm().copyToRealm(tempBasal); - localObjectlID = tempBasal.getId(); - - switch (remoteIntegrations.get(i).getAction()) { - case "new": - rejectRequest += Check.isNewTempBasalSafe(tempBasal); - if (rejectRequest.equals("")) // TODO: 12/08/2016 command to send TempBasal to pump - break; - case "cancel": - rejectRequest += Check.isCancelTempBasalSafe(tempBasal, integrationForAPS, realmManager.getRealm()); - if (rejectRequest.equals("")) // TODO: 12/08/2016 command to send TempBasal to pump - break; - } - break; - - case "bolus_delivery": - Bolus bolus = gson.fromJson(remoteTreatments.get(i), Bolus.class); - realmManager.getRealm().copyToRealm(bolus); - localObjectlID = bolus.getId(); - rejectRequest += Check.isBolusSafeToAction(bolus); - - if (rejectRequest.equals("")) //TODO: 12/08/2016 command to action Bolus - - break; - } - - if (rejectRequest.equals("")) { - //all ok - localObjectState = "received"; - localObjectDetails = "Request sent to pump"; - } else { - //reject - localObjectState = "error"; - localObjectDetails = rejectRequest; - } - - integrationForAPS.setLocal_object_id(localObjectlID); - integrationForAPS.setState(localObjectState); - integrationForAPS.setDetails(localObjectDetails); - realmManager.getRealm().copyToRealm(integrationForAPS); - integrationForPump.setLocal_object_id(localObjectlID); - integrationForPump.setState(localObjectState); - integrationForPump.setDetails(localObjectDetails); - realmManager.getRealm().copyToRealm(integrationForPump); - realmManager.getRealm().commitTransaction(); - } - break; - - default: - Log.e(TAG, "handleMessage: Unknown Action: " + action); - } - - connect_to_aps_app(); - realmManager.closeRealm(); - } - } - - - - final Messenger myMessenger = new Messenger(new IncomingHandler()); - - @Override - public IBinder onBind(Intent intent) { - return myMessenger.getBinder(); - } - - - public void updateAPSApp(){ - - RealmManager realmManager = new RealmManager(); - List integrations = Integration.getIntegrationsToSync("aps_app", null, realmManager.getRealm()); - - if (integrations.size() > 0) { - /* - Bundle data... - "ACTION" - What is this incoming request? Example: "TREATMENT_UPDATES" - "INTEGRATION_OBJECTS" - Array of Integration Objects, details of the objects being synced. *OPTIONAL for UPDATE_TREATMENTS only* - */ - - Log.d(TAG, "UPDATE APS App:" + integrations.size() + " treatments to update"); - Log.d(TAG, "INTEGRATIONS:" + integrations.toString()); - Message msg = Message.obtain(); - boolean updateOK = true; - try { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Class.forName("io.realm.IntegrationRealmProxy"), new IntegrationSerializer()) - .create(); - - Bundle bundle = new Bundle(); - bundle.putString(RT2Const.commService.ACTION, RT2Const.commService.OUTGOING_TREATMENT_UPDATES); - bundle.putString(RT2Const.commService.INTEGRATION_OBJECTS, gson.toJson(integrations)); - msg.setData(bundle); - - } catch (ClassNotFoundException e){ - updateOK = false; - Log.e(TAG, "Error creating gson object: " + e.getLocalizedMessage()); - } - - try { - myService.send(msg); - Log.d(TAG, integrations.size() + " updates sent"); - } catch (RemoteException e) { - updateOK = false; - Log.e(TAG, integrations.size() + " updates failed. " + e.getLocalizedMessage()); - } - - for (Integration integration : integrations){ - realmManager.getRealm().beginTransaction(); - if (updateOK) { - integration.setState("sent"); - } else { - integration.setState("error"); - integration.setDetails("Update to APS failed. Will not be resent."); - } - integration.setToSync(false); - realmManager.getRealm().commitTransaction(); - } - } - - try { - if (isBound) CommunicationService.this.unbindService(myConnection); - } catch (IllegalArgumentException e) { - //catch if service was killed in a unclean way - } - - realmManager.closeRealm(); - } - - //Connect to the APS App Treatments Service - private void connect_to_aps_app(){ - // TODO: 16/06/2016 should be able to pick the APS app from UI not hardcoded - Intent intent = new Intent("com.hypodiabetic.happ.services.TreatmentService"); - intent.setPackage("com.hypodiabetic.happ"); - CommunicationService.this.bindService(intent, myConnection, Context.BIND_AUTO_CREATE); - } - //Our Service that APS App will connect to - private Messenger myService = null; - private Boolean isBound = false; - private ServiceConnection myConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - myService = new Messenger(service); - isBound = true; - - updateAPSApp(); - } - - public void onServiceDisconnected(ComponentName className) { - myService = null; - isBound = false; - } - }; - - -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Bolus.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Bolus.java deleted file mode 100644 index d7e4829d2f..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Bolus.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import io.realm.Realm; -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.Sort; - - -/** - * Created by Tim on 05/08/2016. - */ -public class Bolus extends RealmObject { - - public Double getValue() { - return value; - } - public void setValue(Double value) { - this.value = value; - } - public void setTimestamp(Date timestamp) { - this.timestamp = timestamp; - } - public Date getTimestamp() { - return timestamp; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public String getId() { - return id; - } - - private String id = UUID.randomUUID().toString(); - private Date timestamp = new Date(); - private String type; - private Double value; - - public static Bolus getBolus(String uuid, Realm realm) { - RealmResults results = realm.where(Bolus.class) - .equalTo("id", uuid) - .findAllSorted("timestamp", Sort.DESCENDING); - - if (results.isEmpty()) { - return null; - } else { - return results.first(); - } - } - - public static List getBolusList(Realm realm){ - RealmResults results = realm.where(Bolus.class) - .findAllSorted("timestamp", Sort.DESCENDING); - if (results.isEmpty()) { - return null; - } else { - return results; - } - } - - public static List getBolusesBetween(Date dateFrom, Date dateTo, Realm realm) { - RealmResults results = realm.where(Bolus.class) - .greaterThanOrEqualTo("timestamp", dateFrom) - .lessThanOrEqualTo("timestamp", dateTo) - .findAllSorted("timestamp", Sort.DESCENDING); - return results; - } - - public static Double getBolusCountBetween(Date dateFrom, Date dateTo, Realm realm) { - Number result = realm.where(Bolus.class) - .greaterThanOrEqualTo("timestamp", dateFrom) - .lessThanOrEqualTo("timestamp", dateTo) - .sum("value"); - return result.doubleValue(); - } - - - public static class sortByDateTimeOld2YoungOLD implements Comparator { - @Override - public int compare(Bolus o1, Bolus o2) { - return o2.getTimestamp().compareTo(o1.getTimestamp()); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/DateDeserializer.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/DateDeserializer.java deleted file mode 100644 index 76c25a6e4c..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/DateDeserializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import java.lang.reflect.Type; - -import java.util.Date; - -/** - * Created by Tim on 16/08/2016. - * Used by GSON to Deserializer Dates - */ -public class DateDeserializer implements JsonDeserializer { - public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - Date date = null; - date = new Date(json.getAsJsonPrimitive().getAsLong()); - return date; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Integration.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Integration.java deleted file mode 100644 index a62a22f3be..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/Integration.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import io.realm.Realm; -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.Sort; - - -/** - * Created by Tim on 16/01/2016. - * This table holds Integration details of an object - * one object may have multiple Integrations - */ - -public class Integration extends RealmObject { - - public String getId() { - return id; - } - public String getType() { - return type; - } - public void setType(String type) { - this.type = type; - } - public String getState() { - return state; - } - public void setState(String state) { - this.state = state; - } - public String getAction() { - return action; - } - public void setAction(String action) { - this.action = action; - } - public Date getTimestamp() { - return timestamp; - } - public Date getDate_updated() { - return date_updated; - } - public void setDate_updated(Date date_updated) { - this.date_updated = date_updated; - } - public String getLocal_object() { - return local_object; - } - public void setLocal_object(String local_object) { - this.local_object = local_object; - } - public String getLocal_object_id() { - return local_object_id; - } - public void setLocal_object_id(String local_object_id) { - this.local_object_id = local_object_id; - } - public String getRemote_id() { - return remote_id; - } - public void setRemote_id(String remote_id) { - this.remote_id = remote_id; - } - public String getDetails() { - return details; - } - public void setDetails(String details) { - this.details = details; - } - public String getRemote_var1() { - return remote_var1; - } - public void setRemote_var1(String remote_var1) { - this.remote_var1 = remote_var1; - } - public String getAuth_code() { - return auth_code; - } - public void setAuth_code(String auth_code) { - this.auth_code = auth_code; - } - public Boolean getToSync() { - return toSync; - } - public void setToSync(Boolean toSync) { - this.toSync = toSync; - } - - - private String id; - private String type; //What Integration is this? - private String state; //Current state this Integration is in - private String action; //Requested action for this object - private Date timestamp; //Date created - private Date date_updated; //Last time the Integration for this object was updated - private String local_object; //What rt2 object is this? Bolus, TempBasal etc - private String local_object_id; //HAPP ID for this object - private String remote_id; //ID provided by the remote system - private String details; //The details of this Integration attempt - private String remote_var1; //Misc information about this Integration - private String auth_code; //auth_code if required - private Boolean toSync; //Do we need to sync this object? - - public Integration(){ - id = UUID.randomUUID().toString(); - timestamp = new Date(); - date_updated = new Date(); - remote_var1 = ""; - state = ""; - toSync = true; - } - - public Integration(String type, String local_object, String local_object_id){ - id = UUID.randomUUID().toString(); - timestamp = new Date(); - date_updated = new Date(); - remote_var1 = ""; - state = ""; - this.type = type; - this.local_object = local_object; - this.local_object_id = local_object_id; - toSync = true; - } - - public static Integration getIntegration(String type, String local_object, String rt2_id, Realm realm){ - RealmResults results = realm.where(Integration.class) - .equalTo("type", type) - .equalTo("local_object", local_object) - .equalTo("local_object_id", rt2_id) - .findAllSorted("date_updated", Sort.DESCENDING); - - if (results.isEmpty()) { //We dont have an Integration for this item - return null; - - } else { //Found an Integration, return it - return results.first(); - } - } - - public static List getIntegrationsFor(String local_object, String local_object_id, Realm realm) { - RealmResults results = realm.where(Integration.class) - .equalTo("local_object", local_object) - .equalTo("local_object_id", local_object_id) - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } - - public static List getIntegrationsHoursOld(String type, String local_object, int inLastHours, Realm realm) { - Date now = new Date(); - Date hoursAgo = new Date(now.getTime() - (inLastHours * 60 * 60 * 1000)); - - RealmResults results = realm.where(Integration.class) - .equalTo("local_object", local_object) - .equalTo("type", type) - .greaterThanOrEqualTo("date_updated", hoursAgo) - .lessThanOrEqualTo("date_updated", now) - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } - - public static List getIntegrationsToSync(String type, String local_object, Realm realm) { - if (local_object != null) { - RealmResults results = realm.where(Integration.class) - .equalTo("local_object", local_object) - .equalTo("type", type) - .equalTo("toSync", Boolean.TRUE) - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } else { - RealmResults results = realm.where(Integration.class) - .equalTo("type", type) - .equalTo("toSync", Boolean.TRUE) - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } - } - - public static Integration getIntegrationByID(String uuid, Realm realm) { - RealmResults results = realm.where(Integration.class) - .equalTo("id", uuid) - .findAllSorted("timestamp", Sort.DESCENDING); - if (results.isEmpty()) { - return null; - } else { - return results.first(); - } - } - - public static List getUpdatedInLastMins(Integer inLastMins, String type, Realm realm) { - Date now = new Date(); - Date minsAgo = new Date(now.getTime() - (inLastMins * 60 * 1000)); - - RealmResults results = realm.where(Integration.class) - .equalTo("type", type) - .greaterThanOrEqualTo("date_updated", minsAgo) - .lessThanOrEqualTo("date_updated", now) - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } - - public static List getIntegrationsWithErrors(String type, Realm realm) { - RealmResults results = realm.where(Integration.class) - .equalTo("type", type) - .equalTo("state", "error") - .findAllSorted("date_updated", Sort.DESCENDING); - return results; - } - - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/IntegrationSerializer.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/IntegrationSerializer.java deleted file mode 100644 index 380e6b3e10..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/IntegrationSerializer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -import java.lang.reflect.Type; - -/** - * Created by Tim on 12/08/2016. - * Required by Realm for converting to gson https://realm.io/docs/java/latest/#gson - */ -public class IntegrationSerializer implements JsonSerializer { - - @Override - public JsonElement serialize(Integration src, Type typeOfSrc, JsonSerializationContext context) { - final JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("id", src.getId()); - jsonObject.addProperty("type", src.getType()); - jsonObject.addProperty("state", src.getState()); - jsonObject.addProperty("action", src.getAction()); - jsonObject.addProperty("timestamp", src.getTimestamp().getTime()); - jsonObject.addProperty("date_updated", src.getDate_updated().getTime()); - jsonObject.addProperty("local_object", src.getLocal_object()); - jsonObject.addProperty("local_object_id", src.getLocal_object_id()); - jsonObject.addProperty("remote_id", src.getRemote_id()); - jsonObject.addProperty("details", src.getDetails()); - jsonObject.addProperty("remote_var1", src.getRemote_var1()); - jsonObject.addProperty("auth_code", src.getAuth_code()); - jsonObject.addProperty("toSync", src.getToSync()); - - return jsonObject; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/RealmManager.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/RealmManager.java deleted file mode 100644 index fff16ed4ac..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/RealmManager.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import io.realm.Realm; - -/** - * Created by Tim on 11/08/2016. - */ -public class RealmManager { - private Realm realm; - - public RealmManager(){ - realm = Realm.getDefaultInstance(); - } - - public void closeRealm(){ - realm.close(); - } - - public Realm getRealm(){ - if (realm.isClosed() || realm.isEmpty()) realm = Realm.getDefaultInstance(); - return realm; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/TempBasal.java b/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/TempBasal.java deleted file mode 100644 index ae021cf967..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/CommunicationService/Objects/TempBasal.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.gxwtech.roundtrip2.CommunicationService.Objects; - -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import io.realm.Realm; -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.Sort; -import io.realm.annotations.Ignore; - -/** - * Created by Tim on 03/09/2015. - */ -public class TempBasal extends RealmObject { - - - public Double getRate() { - return rate; - } - public void setRate(Double rate) { - this.rate = rate; - } - public Integer getDuration() { - return duration; - } - public void setDuration(Integer duration) { - this.duration = duration; - } - public Date getStart_time() { - return start_time; - } - public void setStart_time(Date start_time) { - this.start_time = start_time; - } - public String getBasal_adjustemnt() { - return basal_adjustemnt; - } - public void setBasal_adjustemnt(String basal_adjustemnt) { - this.basal_adjustemnt = basal_adjustemnt; - } - public String getAps_mode() { - return aps_mode; - } - public void setAps_mode(String aps_mode) { - this.aps_mode = aps_mode; - } - public String getId() { - return id; - } - public Date getTimestamp() { - return timestamp; - } - - private String id = UUID.randomUUID().toString(); - private Double rate = 0D; //Temp Basal Rate for (U/hr) mode - private Integer duration = 0; //Duration of Temp - private Date start_time; //When the Temp Basal started - private String basal_adjustemnt = ""; //High or Low temp - private String aps_mode; - - @Ignore - public Date timestamp = new Date(); - - public static TempBasal getTempBasalByID(String uuid, Realm realm) { - RealmResults results = realm.where(TempBasal.class) - .equalTo("id", uuid) - .findAllSorted("start_time", Sort.DESCENDING); - - if (results.isEmpty()) { - return null; - } else { - return results.first(); - } - } - - public static TempBasal last(Realm realm) { - RealmResults results = realm.where(TempBasal.class) - .findAllSorted("start_time", Sort.DESCENDING); - - if (results.isEmpty()) { - return new TempBasal(); //returns an empty TempBasal, other than null - } else { - return results.first(); - } - } - - public static TempBasal lastActive(Realm realm) { - RealmResults results = realm.where(TempBasal.class) - .findAllSorted("start_time", Sort.DESCENDING); - - if (results.isEmpty()) { - return null; - } else { - TempBasal tempBasal = results.first(); - Integration integration = Integration.getIntegration("pump","temp_Basal",tempBasal.getId(),realm); - - if (integration.getState().equals("set")){ - return tempBasal; - } else { - return null; - } - } - } - - public static TempBasal getCurrentActive(Date atThisDate, Realm realm) { - RealmResults results = realm.where(TempBasal.class) - .findAllSorted("start_time", Sort.DESCENDING); - - TempBasal last = null; - if (!results.isEmpty()) last = results.first(); - if (last != null && last.isactive(atThisDate)){ - return last; - } else { - return new TempBasal(); //returns an empty TempBasal, other than null or inactive basal - } - } - - public boolean isactive(Date atThisDate){ - if (atThisDate == null) atThisDate = new Date(); - - if (start_time == null){ return false;} - - Date fur = new Date(start_time.getTime() + duration * 60000); - if (fur.after(atThisDate)){ - return true; - } else { - return false; - } - } - - public String ageFormattted(){ - Integer minsOld = age(); - if (minsOld > 1){ - return minsOld + " mins ago"; - } else { - return minsOld + " min ago"; - } - } - - public int age(){ - Date timeNow = new Date(); - return (int)(timeNow.getTime() - timestamp.getTime()) /1000/60; //Age in Mins the Temp Basal was suggested - } - - public Date endDate(){ - Date endedAt = new Date(start_time.getTime() + (duration * 1000 * 60)); //The date this Temp Basal ended - return endedAt; - } - - public Long durationLeft(){ - if (start_time != null) { - Date timeNow = new Date(); - Long min_left = ((start_time.getTime() + duration * 60000) - timeNow.getTime()) / 60000; //Time left to run in Mins - return min_left; - } else { - return duration.longValue(); - } - } - - public static List getTempBasalsDated(Date dateFrom, Date dateTo, Realm realm) { - RealmResults results = realm.where(TempBasal.class) - .greaterThanOrEqualTo("start_time", dateFrom) - .lessThanOrEqualTo("start_time", dateTo) - .findAllSorted("start_time", Sort.DESCENDING); - return results; - } - - public boolean checkIsCancelRequest() { - if (rate.equals(0D) && duration.equals(0)){ - return true; - } else { - return false; - } - } - -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailActivity.txt deleted file mode 100644 index a6e06d0fe7..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailActivity.txt +++ /dev/null @@ -1,83 +0,0 @@ -package com.gxwtech.roundtrip2.HistoryActivity; - -import android.content.Intent; -import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.view.MenuItem; -import android.view.View; - -import com.gxwtech.roundtrip2.R; - -/** - * An activity representing a single HistoryPage detail screen. This - * activity is only used narrow width devices. On tablet-size devices, - * item details are presented side-by-side with a list of items - * in a {@link HistoryPageListActivity}. - */ -public class HistoryPageDetailActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_historypage_detail); - Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar); - setSupportActionBar(toolbar); - - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own detail action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - - // Show the Up button in the action bar. - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } - - // savedInstanceState is non-null when there is fragment state - // saved from previous configurations of this activity - // (e.g. when rotating the screen from portrait to landscape). - // In this case, the fragment will automatically be re-added - // to its container so we don't need to manually add it. - // For more information, see the Fragments API guide at: - // - // http://developer.android.com/guide/components/fragments.html - // - if (savedInstanceState == null) { - // Create the detail fragment and add it to the activity - // using a fragment transaction. - Bundle arguments = new Bundle(); - arguments.putString(HistoryPageDetailFragment.ARG_ITEM_ID, - getIntent().getStringExtra(HistoryPageDetailFragment.ARG_ITEM_ID)); - HistoryPageDetailFragment fragment = new HistoryPageDetailFragment(); - fragment.setArguments(arguments); - getSupportFragmentManager().beginTransaction() - .add(R.id.historypage_detail_container, fragment) - .commit(); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - // This ID represents the Home or Up button. In the case of this - // activity, the Up button is shown. For - // more details, see the Navigation pattern on Android Design: - // - // http://developer.android.com/design/patterns/navigation.html#up-vs-back - // - navigateUpTo(new Intent(this, HistoryPageListActivity.class)); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailFragment.txt b/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailFragment.txt deleted file mode 100644 index 20ffed149e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageDetailFragment.txt +++ /dev/null @@ -1,70 +0,0 @@ -package com.gxwtech.roundtrip2.HistoryActivity; - -import android.app.Activity; -import android.os.Bundle; -import android.support.design.widget.CollapsingToolbarLayout; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.gxwtech.roundtrip2.R; - - -/** - * A fragment representing a single HistoryPage detail screen. - * This fragment is either contained in a {@link HistoryPageListActivity} - * in two-pane mode (on tablets) or a {@link HistoryPageDetailActivity} - * on handsets. - */ -public class HistoryPageDetailFragment extends Fragment { - /** - * The fragment argument representing the item ID that this fragment - * represents. - */ - public static final String ARG_ITEM_ID = "item_id"; - - /** - * The dummy content this fragment is presenting. - */ - private HistoryPageListContent.RecordHolder mItem; - - /** - * Mandatory empty constructor for the fragment manager to instantiate the - * fragment (e.g. upon screen orientation changes). - */ - public HistoryPageDetailFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (getArguments().containsKey(ARG_ITEM_ID)) { - // Load the dummy content specified by the fragment - // arguments. In a real-world scenario, use a Loader - // to load content from a content provider. - mItem = HistoryPageListContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID)); - - Activity activity = this.getActivity(); - CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout); - if (appBarLayout != null) { - appBarLayout.setTitle("Details"/*mItem.content*/); - } - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.historypage_detail, container, false); - - // Show the dummy content as text in a TextView. - if (mItem != null) { - ((TextView) rootView.findViewById(R.id.historypage_detail)).setText(mItem.details); - } - - return rootView; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListActivity.txt deleted file mode 100644 index a0517d3a00..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListActivity.txt +++ /dev/null @@ -1,230 +0,0 @@ -package com.gxwtech.roundtrip2.HistoryActivity; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.ActionBar; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.gxwtech.roundtrip2.R; -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.ServiceData.RetrieveHistoryPageResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * An activity representing a list of HistoryPages. This activity - * has different presentations for handset and tablet-size devices. On - * handsets, the activity presents a list of items, which when touched, - * lead to a {@link HistoryPageDetailActivity} representing - * item details. On tablets, the activity presents the list of items and - * item details side-by-side using two vertical panes. - */ -public class HistoryPageListActivity extends AppCompatActivity { - private static final String TAG = "HistoryPageListActivity"; - - - /** - * Whether or not the activity is in two-pane mode, i.e. running on a tablet - * device. - */ - private boolean mTwoPane; - private BroadcastReceiver mBroadcastRecevier; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_historypage_list); - - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - toolbar.setTitle(R.string.title_pump_history); - - // Show the Up button in the action bar. - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } - - View recyclerView = findViewById(R.id.historypage_list); - assert recyclerView != null; - setupRecyclerView((RecyclerView) recyclerView); - - if (findViewById(R.id.historypage_detail_container) != null) { - // The detail container view will be present only in the - // large-screen layouts (res/values-w900dp). - // If this view is present, then the - // activity should be in two-pane mode. - mTwoPane = true; - } - - mBroadcastRecevier = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent receivedIntent) { - if (receivedIntent == null) { - Log.e(TAG,"onReceive: received null intent"); - } else { - String action = receivedIntent.getAction(); - if (action == null) { - Log.e(TAG, "onReceive: null action"); - } else { - if (RT2Const.local.INTENT_historyPageBundleIncoming.equals(action)) { - Bundle incomingBundle = receivedIntent.getExtras().getBundle(RT2Const.IPC.MSG_PUMP_history_key); - ServiceTransport transport = new ServiceTransport(incomingBundle); - ServiceResult result = transport.getServiceResult(); - if ("RetrieveHistoryPageResult".equals(result.getServiceResultType())) { - RetrieveHistoryPageResult pageResult = (RetrieveHistoryPageResult) result; - Bundle page = pageResult.getPageBundle(); - ArrayList recordBundleList = page.getParcelableArrayList("mRecordList"); - try { - for (Bundle record : recordBundleList) { - HistoryPageListContent.addItem(record); - } - } catch (java.lang.NullPointerException e) { - e.printStackTrace(); - } - } - } else { - Log.e(TAG,"Unrecognized intent action: "+action); - } - } - } - } - }; - IntentFilter filter = new IntentFilter(); - filter.addAction(RT2Const.local.INTENT_historyPageBundleIncoming); - LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mBroadcastRecevier,filter); - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_bluetooth_scan, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.miScan: - getHistory(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - public void getHistory(){ - // tell them we're ready for data - Intent intent = new Intent(RT2Const.local.INTENT_historyPageViewerReady); - LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent); - } - - private void setupRecyclerView(@NonNull RecyclerView recyclerView) { - recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(HistoryPageListContent.ITEMS)); - } - - public class SimpleItemRecyclerViewAdapter - extends RecyclerView.Adapter { - - private final List mValues; - - public SimpleItemRecyclerViewAdapter(List items) { - mValues = items; - } - - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.historypage_list_content, parent, false); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(final ViewHolder holder, int position) { - holder.mItem = mValues.get(position); - holder.mIdView.setText(mValues.get(position).dateAndName); - String keytext = ""; - Set keys = holder.mItem.content.keySet(); - int n = 0; - for (String key : keys) { - if (!key.equals("_type") && !key.equals("_stype") && !key.equals("timestamp") && !key.equals("_opcode")) { - try { - keytext += key + ":" + holder.mItem.content.get(key).toString(); - n++; - if (n < keys.size() - 1) { - keytext += "\n"; - } - } catch (NullPointerException e) { - e.printStackTrace(); - } - } - } - holder.mContentView.setText(keytext); - - holder.mView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mTwoPane) { - Bundle arguments = new Bundle(); - arguments.putString(HistoryPageDetailFragment.ARG_ITEM_ID, holder.mItem.id); - HistoryPageDetailFragment fragment = new HistoryPageDetailFragment(); - fragment.setArguments(arguments); - getSupportFragmentManager().beginTransaction() - .replace(R.id.historypage_detail_container, fragment) - .commit(); - } else { - Context context = v.getContext(); - Intent intent = new Intent(context, HistoryPageDetailActivity.class); - intent.putExtra(HistoryPageDetailFragment.ARG_ITEM_ID, holder.mItem.id); - - context.startActivity(intent); - } - } - }); - } - - @Override - public int getItemCount() { - return mValues.size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - public final View mView; - public final TextView mIdView; - public final TextView mContentView; - public HistoryPageListContent.RecordHolder mItem; - - public ViewHolder(View view) { - super(view); - mView = view; - mIdView = (TextView) view.findViewById(R.id.id); - mContentView = (TextView) view.findViewById(R.id.content); - } - - @Override - public String toString() { - return super.toString() + " '" + mContentView.getText() + "'"; - } - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListContent.java b/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListContent.java deleted file mode 100644 index a61bc86f21..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/HistoryActivity/HistoryPageListContent.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.gxwtech.roundtrip2.HistoryActivity; - -import android.os.Bundle; -import android.util.ArraySet; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Created by geoff on 6/12/16. - */ -public class HistoryPageListContent { - public static final List ITEMS = new ArrayList<>(); - - /** - * A map of items, by ID. - */ - public static final Map ITEM_MAP = new HashMap<>(); - - static void addItem(Bundle recordBundle) { - addItem(new RecordHolder(recordBundle)); - } - - private static void addItem(RecordHolder item) { - ITEMS.add(item); - ITEM_MAP.put(item.id, item); - } - - private static String makeDetails(int position) { - RecordHolder rh = ITEMS.get(position); - if (rh == null) { - return "(null)"; - } - - return makeDetails(rh.content); - } - - private static String makeDetails(Bundle historyEntry) { - Set ignoredSet = new HashSet<>(); - ignoredSet.add("_type"); - ignoredSet.add("_stype"); - ignoredSet.add("_opcode"); - ignoredSet.add("timestamp"); - StringBuilder builder = new StringBuilder(); - int n = 0; - for (String key : historyEntry.keySet()) { - if (!ignoredSet.contains(key)) { - builder.append(key); - n++; - if (n= 12) { - veryShortName = veryShortName.substring(0,12); - } - dateAndNameBuilder.append(veryShortName); - this.dateAndName = dateAndNameBuilder.toString(); - this.content = content; - details = makeDetails(content); - } - - @Override - public String toString() { - return content.getString("_stype", "(unk)"); - } - } - -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/MainActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/MainActivity.txt deleted file mode 100644 index 41efc5fddf..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/MainActivity.txt +++ /dev/null @@ -1,614 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.res.Resources; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.os.SystemClock; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.design.widget.Snackbar; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.preference.PreferenceManager; -import android.content.SharedPreferences; - -import com.gxwtech.roundtrip2.HistoryActivity.HistoryPageListActivity; -import android.view.LayoutInflater; -import android.view.ViewGroup; -import android.widget.ListView; - - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.ServiceData.BasalProfile; -import com.gxwtech.roundtrip2.ServiceData.BolusWizardCarbProfile; -import com.gxwtech.roundtrip2.ServiceData.ISFProfile; -import com.gxwtech.roundtrip2.ServiceData.PumpModelResult; -import com.gxwtech.roundtrip2.ServiceData.ReadPumpClockResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceClientActions; -import com.gxwtech.roundtrip2.ServiceData.ServiceCommand; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; -import com.gxwtech.roundtrip2.ServiceMessageViewActivity.ServiceMessageViewListActivity; -import com.gxwtech.roundtrip2.util.tools; - -import java.util.ArrayList; - -public class MainActivity extends AppCompatActivity { - - private static final String TAG = "MainActivity"; - private static final int REQUEST_ENABLE_BT = 2177; // just something unique. - private RoundtripServiceClientConnection roundtripServiceClientConnection; - private BroadcastReceiver mBroadcastReceiver; - - BroadcastReceiver apsAppConnected; - Bundle storeForHistoryViewer; - - //UI items - private DrawerLayout mDrawerLayout; - private LinearLayout mDrawerLinear; - private Toolbar toolbar; - - public static Context mContext; // TODO: 09/07/2016 @TIM this should not be needed - - @Override - protected void onCreate(Bundle savedInstanceState) { - Log.w(TAG,"onCreate"); - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - setupMenuAndToolbar(); - - mContext = this; // TODO: 09/07/2016 @TIM this should not be needed - - //Sets default Preferences - PreferenceManager.setDefaultValues(this, R.xml.pref_pump, false); - PreferenceManager.setDefaultValues(this, R.xml.pref_rileylink, false); - - setBroadcastReceiver(); - - - - - /* start the RoundtripService */ - /* using startService() will keep the service running until it is explicitly stopped - * with stopService() or by RoundtripService calling stopSelf(). - * Note that calling startService repeatedly has no ill effects on RoundtripService - */ - // explicitly call startService to keep it running even when the GUI goes away. - Intent bindIntent = new Intent(this,RoundtripService.class); - startService(bindIntent); - - linearProgressBar = (ProgressBar)findViewById(R.id.progressBarCommandActivity); - spinnyProgressBar = (ProgressBar)findViewById(R.id.progressBarSpinny); - } - - - @Override - protected void onResume(){ - super.onResume(); - - setBroadcastReceiver(); - } - - @Override - public void onPause() { - super.onPause(); - if (apsAppConnected != null){ - LocalBroadcastManager.getInstance(MainApp.instance()).unregisterReceiver(apsAppConnected); - } - if (mBroadcastReceiver != null){ - LocalBroadcastManager.getInstance(MainApp.instance()).unregisterReceiver(mBroadcastReceiver); - } - } - - public void setBroadcastReceiver() { - //Register this receiver for UI Updates - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent receivedIntent) { - - if (receivedIntent == null) { - Log.e(TAG, "onReceive: received null intent"); - } else { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()); - ServiceTransport transport; - - switch (receivedIntent.getAction()) { - case RT2Const.local.INTENT_serviceConnected: - case RT2Const.local.INTENT_NEW_rileylinkAddressKey: - showIdle(); - /** - * Client MUST send a "UseThisRileylink" message because it asserts that - * the user has given explicit permission to use bluetooth. - * - * We can change the format so that it is a simple "bluetooth OK" message, - * rather than an explicit address of a Rileylink, and the Service can - * use the last known good value. But the kick-off of bluetooth ops must - * come from an Activity. - */ - String RileylinkBLEAddress = prefs.getString(RT2Const.serviceLocal.rileylinkAddressKey, ""); - if (RileylinkBLEAddress.equals("")){ - // TODO: 11/07/2016 @TIM UI message for user - Log.e(TAG, "No Rileylink BLE Address saved in app"); - } else { - showBusy("Configuring Service", 50); - MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress); - } - break; - case RT2Const.local.INTENT_NEW_pumpIDKey: - MainApp.getServiceClientConnection().sendPUMP_useThisDevice(prefs.getString(RT2Const.serviceLocal.pumpIDKey, "")); - break; - case RT2Const.local.INTENT_historyPageViewerReady: - Intent sendHistoryIntent = new Intent(RT2Const.local.INTENT_historyPageBundleIncoming); - sendHistoryIntent.putExtra(RT2Const.IPC.MSG_PUMP_history_key, storeForHistoryViewer); - LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(sendHistoryIntent); - break; - case RT2Const.IPC.MSG_ServiceResult: - Log.i(TAG, "Received ServiceResult"); - - Bundle bundle = receivedIntent.getBundleExtra(RT2Const.IPC.bundleKey); - transport = new ServiceTransport(bundle); - if (transport.commandDidCompleteOK()) { - String originalCommandName = transport.getOriginalCommandName(); - switch (originalCommandName) { - case "ReadPumpModel": - PumpModelResult modelResult = new PumpModelResult(); - modelResult.initFromServiceResult(transport.getServiceResult()); - String pumpModelString = modelResult.getPumpModel(); - // GGW Tue Jul 12 02:29:54 UTC 2016: ok, now what do we do with the pump model? - showIdle(); - break; - case "ReadPumpClock": - ReadPumpClockResult clockResult = new ReadPumpClockResult(); - clockResult.initFromServiceResult(transport.getServiceResult()); - TextView pumpTimeTextView = (TextView) findViewById(R.id.textViewPumpClockTime); - pumpTimeTextView.setText(clockResult.getTimeString()); - showIdle(); - break; - case "FetchPumpHistory": - storeForHistoryViewer = receivedIntent.getExtras().getBundle(RT2Const.IPC.bundleKey); - startActivity(new Intent(context, HistoryPageListActivity.class)); - // wait for history viewer to announce "ready" - showIdle(); - break; - case "RetrieveHistoryPage": - storeForHistoryViewer = receivedIntent.getExtras().getBundle(RT2Const.IPC.bundleKey); - startActivity(new Intent(context, HistoryPageListActivity.class)); - // wait for history viewer to announce "ready" - showIdle(); - break; - case "ISFProfile": - ISFProfile isfProfile = new ISFProfile(); - isfProfile.initFromServiceResult(transport.getServiceResult()); - // TODO: do something with isfProfile - showIdle(); - break; - case "BasalProfile": - BasalProfile basalProfile = new BasalProfile(); - basalProfile.initFromServiceResult(transport.getServiceResult()); - // TODO: do something with basal profile - showIdle(); - break; - case "BolusWizardCarbProfile": - BolusWizardCarbProfile carbProfile = new BolusWizardCarbProfile(); - carbProfile.initFromServiceResult(transport.getServiceResult()); - // TODO: do something with carb profile - showIdle(); - break; - case "UpdatePumpStatus": - // rebroadcast for HAPP - - break; - default: - Log.e(TAG, "Dunno what to do with this command completion: " + transport.getOriginalCommandName()); - } - } else { - Log.e(TAG,"Command failed? " + transport.getOriginalCommandName()); - } - break; - case RT2Const.IPC.MSG_ServiceNotification: - transport = new ServiceTransport(receivedIntent.getBundleExtra(RT2Const.IPC.bundleKey)); - ServiceNotification notification = transport.getServiceNotification(); - String note = notification.getNotificationType(); - switch (note) { - case RT2Const.IPC.MSG_BLE_RileyLinkReady: - setRileylinkStatusMessage("OK"); - break; - case RT2Const.IPC.MSG_PUMP_pumpFound: - setPumpStatusMessage("OK"); - break; - case RT2Const.IPC.MSG_PUMP_pumpLost: - setPumpStatusMessage("Lost"); - break; - case RT2Const.IPC.MSG_note_WakingPump: - showBusy("Waking Pump", 99); - break; - case RT2Const.IPC.MSG_note_FindingRileyLink: - showBusy("Finding RileyLink", 99); - break; - case RT2Const.IPC.MSG_note_Idle: - showIdle(); - break; - default: - Log.e(TAG, "Unrecognized Notification: '" + note + "'"); - } - break; - default: - Log.e(TAG, "Unrecognized intent action: " + receivedIntent.getAction()); - } - } - } - }; - - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(RT2Const.local.INTENT_serviceConnected); - intentFilter.addAction(RT2Const.IPC.MSG_ServiceResult); - intentFilter.addAction(RT2Const.IPC.MSG_ServiceNotification); - intentFilter.addAction(RT2Const.local.INTENT_historyPageViewerReady); - - - linearProgressBar = (ProgressBar)findViewById(R.id.progressBarCommandActivity); - spinnyProgressBar = (ProgressBar)findViewById(R.id.progressBarSpinny); - LocalBroadcastManager.getInstance(MainApp.instance()).registerReceiver(mBroadcastReceiver, intentFilter); - } - - - - - - - /** - * - * GUI element functions - * - */ - - - private int mProgress = 0; - private int mSpinnyProgress = 0; - private ProgressBar linearProgressBar; - private ProgressBar spinnyProgressBar; - private static final int spinnyFPS = 10; - private Thread spinnyThread; - void showBusy(String activityString, int progress) { - mProgress = progress; - TextView tv = (TextView)findViewById(R.id.textViewActivity); - tv.setText(activityString); - linearProgressBar.setProgress(progress); - if (progress > 0) { - spinnyProgressBar.setVisibility(View.VISIBLE); - if (spinnyThread == null) { - spinnyThread = new Thread(new Runnable() { - @Override - public void run() { - while ((mProgress > 0) && (mProgress < 100)) { - mSpinnyProgress += 100 / spinnyFPS; - spinnyProgressBar.setProgress(mSpinnyProgress); - SystemClock.sleep(1000 / spinnyFPS); - } - spinnyThread = null; - } - }); - spinnyThread.start(); - } - } else { - spinnyProgressBar.setVisibility(View.INVISIBLE); - } - } - - void showIdle() { - showBusy("Idle",0); - } - - void setRileylinkStatusMessage(String statusMessage) { - TextView field = (TextView)findViewById(R.id.textViewFieldRileyLink); - field.setText(statusMessage); - } - - void setPumpStatusMessage(String statusMessage) { - TextView field = (TextView)findViewById(R.id.textViewFieldPump); - field.setText(statusMessage); - } - - public void onTunePumpButtonClicked(View view) { - MainApp.getServiceClientConnection().doTunePump(); - } - - public void onFetchHistoryButtonClicked(View view) { - /* does not work. Crashes sig 11 */ - showBusy("Fetch history page 0",50); - MainApp.getServiceClientConnection().doFetchPumpHistory(); - } - - public void onFetchSavedHistoryButtonClicked(View view) { - showBusy("Fetching history (not saved)",50); - MainApp.getServiceClientConnection().doFetchSavedHistory(); - } - - public void onReadPumpClockButtonClicked(View view) { - showBusy("Reading Pump Clock",50); - MainApp.getServiceClientConnection().readPumpClock(); - } - - public void onGetISFProfileButtonClicked(View view) { - //ServiceCommand getISFProfileCommand = ServiceClientActions.makeReadISFProfileCommand(); - //roundtripServiceClientConnection.sendServiceCommand(getISFProfileCommand); - MainApp.getServiceClientConnection().readISFProfile(); - } - - public void onViewEventLogButtonClicked(View view) { - startActivity(new Intent(getApplicationContext(),ServiceMessageViewListActivity.class)); - } - - public void onUpdateAllStatusButtonClicked(View view) { - MainApp.getServiceClientConnection().updateAllStatus(); - } - - public void onGetCarbProfileButtonClicked(View view) { - showBusy("Getting Carb Profile",1); - roundtripServiceClientConnection.sendServiceCommand(ServiceClientActions.makeReadBolusWizardCarbProfileCommand()); - } - - /* UI Setup */ - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_main, menu); - return true; - } - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_MENU: - if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){ - mDrawerLayout.closeDrawers(); - } else { - mDrawerLayout.openDrawer(GravityCompat.START); - } - return true; - } - return super.onKeyUp(keyCode, event); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle item selection - switch (item.getItemId()) { - case android.R.id.home: - mDrawerLayout.openDrawer(mDrawerLinear); - return true; - - default: - return true; - } - } - - public void setupMenuAndToolbar() { - //Setup menu - mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout); - mDrawerLinear = (LinearLayout) findViewById(R.id.left_drawer); - toolbar = (Toolbar) findViewById(R.id.mainActivityToolbar); - Drawable logsIcon = getDrawable(R.drawable.file_chart); - Drawable historyIcon = getDrawable(R.drawable.history); - Drawable settingsIcon = getDrawable(R.drawable.settings); - Drawable catIcon = getDrawable(R.drawable.cat); - Drawable apsIcon = getDrawable(R.drawable.refresh); - - logsIcon.setColorFilter(getResources().getColor(R.color.primary_dark), PorterDuff.Mode.SRC_ATOP); - historyIcon.setColorFilter(getResources().getColor(R.color.primary_dark), PorterDuff.Mode.SRC_ATOP); - settingsIcon.setColorFilter(getResources().getColor(R.color.primary_dark), PorterDuff.Mode.SRC_ATOP); - catIcon.setColorFilter(getResources().getColor(R.color.primary_dark), PorterDuff.Mode.SRC_ATOP); - apsIcon.setColorFilter(getResources().getColor(R.color.primary_dark), PorterDuff.Mode.SRC_ATOP); - - ListView mDrawerList = (ListView)findViewById(R.id.navList); - ArrayList menuItems = new ArrayList<>(); - menuItems.add(new NavItem("APS Integration", apsIcon)); - menuItems.add(new NavItem("Pump History", historyIcon)); - menuItems.add(new NavItem("Treatment Logs", logsIcon)); - menuItems.add(new NavItem("Settings", settingsIcon)); - menuItems.add(new NavItem("View LogCat", catIcon)); - DrawerListAdapter adapterMenu = new DrawerListAdapter(this, menuItems); - mDrawerList.setAdapter(adapterMenu); - mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - switch (position) { - case 0: - //Check APS App Connectivity - sendAPSAppMessage(view); - break; - case 1: - //Pump History - startActivity(new Intent(getApplicationContext(), HistoryPageListActivity.class)); - break; - case 2: - //Treatment Logs - startActivity(new Intent(getApplicationContext(), TreatmentHistory.class)); - break; - case 3: - //Settings - startActivity(new Intent(getApplicationContext(), SettingsActivity.class)); - break; - case 4: - //View LogCat - tools.showLogging(); - break; - } - mDrawerLayout.closeDrawers(); - } - }); - - ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.string.drawer_open, R.string.drawer_close) { - /** Called when a drawer has settled in a completely open state. */ - public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - - //Insulin Integration App, try and connect - //checkInsulinAppIntegration(false); - } - /** Called when a drawer has settled in a completely closed state. */ - public void onDrawerClosed(View view) { - super.onDrawerClosed(view); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - } - }; - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - mDrawerToggle.syncState(); - mDrawerToggle.setDrawerIndicatorEnabled(true); - mDrawerLayout.addDrawerListener(mDrawerToggle); - } - - - /* Functions for APS App Service */ - - //Our Service that APS App will connect to - private Messenger myService = null; - private ServiceConnection myConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - myService = new Messenger(service); - - //Broadcast there has been a connection - Intent intent = new Intent("APS_CONNECTED"); - LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - } - - public void onServiceDisconnected(ComponentName className) { - myService = null; - //FYI, only called if Service crashed or was killed, not on unbind - } - }; - - public void sendAPSAppMessage(final View view) - { - //listen out for a successful connection - apsAppConnected = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - - Resources appR = view.getContext().getResources(); - CharSequence txt = appR.getText(appR.getIdentifier("app_name", "string", view.getContext().getPackageName())); - - Message msg = Message.obtain(); - Bundle bundle = new Bundle(); - bundle.putString(RT2Const.commService.ACTION,RT2Const.commService.OUTGOING_TEST_MSG); - bundle.putString(RT2Const.commService.REMOTE_APP_NAME, txt.toString()); - msg.setData(bundle); - - try { - myService.send(msg); - } catch (RemoteException e) { - e.printStackTrace(); - //cannot Bind to service - Snackbar snackbar = Snackbar - .make(view, "error sending msg: " + e.getMessage(), Snackbar.LENGTH_INDEFINITE); - snackbar.show(); - } - - if (apsAppConnected != null) LocalBroadcastManager.getInstance(MainApp.instance()).unregisterReceiver(apsAppConnected); //Stop listening for new connections - MainApp.instance().unbindService(myConnection); - } - }; - LocalBroadcastManager.getInstance(MainApp.instance()).registerReceiver(apsAppConnected, new IntentFilter("APS_CONNECTED")); - - connect_to_aps_app(MainApp.instance()); - } - - //Connect to the APS App Treatments Service - private void connect_to_aps_app(Context c){ - // TODO: 16/06/2016 add user selected aps app - Intent intent = new Intent("com.hypodiabetic.happ.services.TreatmentService"); - intent.setPackage("com.hypodiabetic.happ"); - c.bindService(intent, myConnection, Context.BIND_AUTO_CREATE); - } - - - -} - -class NavItem { - String mTitle; - Drawable mIcon; - - public NavItem(String title, Drawable icon) { - mTitle = title; - mIcon = icon; - } -} - -class DrawerListAdapter extends BaseAdapter { - - Context mContext; - ArrayList mNavItems; - - public DrawerListAdapter(Context context, ArrayList navItems) { - mContext = context; - mNavItems = navItems; - } - - @Override - public int getCount() { - return mNavItems.size(); - } - - @Override - public Object getItem(int position) { - return mNavItems.get(position); - } - - @Override - public long getItemId(int position) { - return 0; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view; - - if (convertView == null) { - LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(R.layout.menu_item, null); - } - else { - view = convertView; - } - - TextView titleView = (TextView) view.findViewById(R.id.menuText); - ImageView iconView = (ImageView) view.findViewById(R.id.menuIcon); - - titleView.setText( mNavItems.get(position).mTitle); - iconView.setBackground(mNavItems.get(position).mIcon); - return view; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/MainApp.txt b/app/src/main/java/com/gxwtech/roundtrip2/MainApp.txt deleted file mode 100644 index ad553c2056..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/MainApp.txt +++ /dev/null @@ -1,48 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.app.Application; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Tim on 15/06/2016. - */ -public class MainApp extends Application { - - private static MainApp sInstance; - private static ServiceClientConnection serviceClientConnection; - - @Override - public void onCreate() { - super.onCreate(); - - sInstance = this; - serviceClientConnection = new ServiceClientConnection(); - - //initialize Realm - RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(instance()) - .name("rt2.realm") - .schemaVersion(0) - .deleteRealmIfMigrationNeeded() // TODO: 03/08/2016 @TIM remove - .build(); - Realm.setDefaultConfiguration(realmConfiguration); - } - - - - - public static MainApp instance() { - return sInstance; - } - - public static ServiceClientConnection getServiceClientConnection(){ - if (serviceClientConnection == null) { - serviceClientConnection = new ServiceClientConnection(); - } - return serviceClientConnection; - } - - // TODO: 09/07/2016 @TIM uncomment ServiceClientConnection once class is added - -} \ No newline at end of file diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RT2Const.java b/app/src/main/java/com/gxwtech/roundtrip2/RT2Const.java deleted file mode 100644 index 1b5e68ff76..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RT2Const.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.gxwtech.roundtrip2; - -/** - * Created by geoff on 6/5/16. - */ -public class RT2Const { - public static final String RT2Prefix = "com.gxwtech.roundtrip2."; - public class IPC { - public static final String Prefix = RT2Prefix + "IPC."; - - // This message is used to bind the "replyTo" field - public static final int MSG_clientRegistered = 63; // arbitrary - public static final int MSG_unregisterClient = 64; - public static final int MSG_registerClient = 65; - - // used in IPC to mark a message as a generic IPC message - public static final int MSG_IPC = 66; - // used as the key to find the message in the bundle. - public static final String messageKey = Prefix + "messageKey"; - // used as a key for the bundle, when the bundle is packed into an Intent - public static final String bundleKey = Prefix + "bundleKey"; - // a field to hold the instant (milliseconds since 1970) the message - // was sent or received by the CLIENT - public static final String instantKey = Prefix + "instantKey"; - // key for the "command" string in a bundle - public static final String commandKey = Prefix + "commandKey"; - // key for the command-response bundle in a result bundle - public static final String serviceResultKey = Prefix + "commandResponse"; - - // used by gui to pass the address of the Rileylink to the Service - // has an 'address' field with the string address. - public static final String MSG_BLE_useThisDevice = Prefix + "MSG_BLE_useThisDevice"; - public static final String MSG_BLE_useThisDevice_addressKey = Prefix + "MSG_BLE_useThisDevice_addressKey"; - - // used by gui to tell service that BLE access is denied by user. - public static final String MSG_BLE_accessDenied = Prefix + "MSG_BLE_accessDenied"; - public static final String MSG_BLE_accessGranted = Prefix + "MSG_BLE_accessGranted"; - // used by service to ask user for Bluetooth permission - public static final String MSG_BLE_requestAccess = Prefix + "MSG_BLE_requestAccess"; - public static final String MSG_BLE_RileyLinkReady = Prefix + "MSG_BLE_RileyLinkReady"; - - // used to pass the pump ID from GUI to service - // has a 'pumpID' field containing a six digit String - public static final String MSG_PUMP_useThisAddress = Prefix + "MSG_PUMP_useThisAddress"; - public static final String MSG_PUMP_useThisAddress_pumpIDKey = Prefix + "MSG_PUMP_useThisAddress_pumpIDKey"; - - // These are used to pass information about the pump from the service to the GUI. - // has a 'model' field - //public static final String MSG_PUMP_reportedPumpModel = Prefix + "MSG_PUMP_reportedPumpModel"; - public static final String MSG_PUMP_pumpFound = Prefix + "MSG_PUMP_pumpFound"; - public static final String MSG_PUMP_pumpLost = Prefix + "MSG_PUMP_pumpLost"; - - public static final String MSG_PUMP_tunePump = Prefix + "MSG_PUMP_tunePump"; - public static final String MSG_PUMP_quickTune = Prefix + "MSG_PUMP_quickTune"; - public static final String MSG_PUMP_fetchHistory = Prefix + "MSG_PUMP_fetchHistory"; - - public static final String MSG_PUMP_history = Prefix + "MSG_PUMP_history"; - public static final String MSG_PUMP_history_key = Prefix + "MSG_PUMP_history_key"; - public static final String MSG_PUMP_fetchSavedHistory = Prefix + "MSG_PUMP_fetchSavedHistory"; - - // interface for ServiceCommand/ServiceResult - public static final String MSG_ServiceCommand = Prefix + "MSG_ServiceCommand"; - public static final String MSG_ServiceResult = Prefix + "MSG_ServiceResult"; - public static final String MSG_ServiceNotification = Prefix + "MSG_ServiceNotification"; - - // These are notifications to GUIs to let them know what's happening - public static final String MSG_note_Idle = Prefix + "MSG_note_Idle"; - public static final String MSG_note_FindingRileyLink = Prefix + "MSG_note_FindingRileyLink"; - public static final String MSG_note_WakingPump = Prefix + "MSG_note_WakingPump"; - public static final String MSG_note_TaskProgress = Prefix + "MSG_note_TaskProgress"; - - } - public class local { - // These are local to the GUI activities - public static final String Prefix = RT2Prefix + "local."; - public static final String INTENT_serviceConnected = Prefix + "INTENT_serviceConnected"; - public static final String INTENT_NEW_rileylinkAddressKey = Prefix + "INTENT_NEW_rileylinkAddressKey"; - public static final String INTENT_NEW_pumpIDKey = Prefix + "INTENT_NEW_pumpIDKey"; - - - public static final String INTENT_historyPageViewerReady = Prefix + "I'm ready, hit me up"; - public static final String INTENT_historyPageBundleIncoming = Prefix + "Here's the kitchen sink"; - } - - public class serviceLocal { - public static final String Prefix = RT2Prefix + "serviceLocal."; - // for local broadcasts annoucing connectivity events - public static final String INTENT_seekRileylink = Prefix + "INTENT_seekRileylink"; - public static final String bluetooth_connected = Prefix + "bluetooth_connected"; - public static final String bluetooth_disconnected = Prefix + "bluetooth_disconnected"; - public static final String BLE_services_discovered = Prefix + "BLE_services_discovered"; - - public static final String ipcBound = Prefix + "ipcBound"; - - // primary shared preferences file identifier - public static final String sharedPreferencesKey = Prefix + "sharedPreferencesKey"; - - // These are used to identify shared preference items - public static final String pumpIDKey = Prefix + "PumpIDKey"; - public static final String rileylinkAddressKey = Prefix + "rileylinkAddressKey"; - public static final String prefsLastGoodPumpFrequency = Prefix + "prefsLastGoodPumpFrequency"; - - // The the key to identify the hashCode() of the msg.replyTo, when the bundle is moved to an intent. - public static final String IPCReplyTo_hashCodeKey = Prefix + "IPCReplyTo_hashCodeKey"; - - // This is sent from the PumpManager to RoundtripService at the completion of a pump command session. - public static final String INTENT_sessionCompleted = Prefix + "INTENT_sessionCompleted"; - - } - - public class commService { - //Data - public static final String ACTION = "ACTION"; - public static final String DATE_REQUESTED = "DATE_REQUESTED"; - public static final String INTEGRATION_OBJECTS = "INTEGRATION_OBJECTS"; - public static final String TREATMENT_OBJECTS = "TREATMENT_OBJECTS"; - public static final String PUMP = "PUMP"; - public static final String REMOTE_APP_NAME = "REMOTE_APP_NAME"; - - //Incoming actions - public static final String INCOMING_NEW_TREATMENTS = "NEW_TREATMENTS"; - public static final String INCOMING_TEST_MSG = "TEST_MSG"; - - //Outgoing actions - public static final String OUTGOING_TREATMENT_UPDATES = "TREATMENT_UPDATES"; - public static final String OUTGOING_TEST_MSG = "TEST_MSG"; - - } - - public class safety { - public static final int INCOMING_REQUEST_MAX_AGE = 10; //mins - public static final int TREATMENT_MAX_AGE = 8; //mins - - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RileyLinkScan.txt b/app/src/main/java/com/gxwtech/roundtrip2/RileyLinkScan.txt deleted file mode 100644 index 49b37f5489..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RileyLinkScan.txt +++ /dev/null @@ -1,343 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.Manifest; -import android.app.AlertDialog; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothManager; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.ScanFilter; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Toast; -import android.util.Log; - -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; - -import com.gxwtech.roundtrip2.util.LocationHelper; - -import java.util.ArrayList; -import java.util.List; - -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.view.LayoutInflater; - -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.TextView; - - -public class RileyLinkScan extends AppCompatActivity { - private final static String TAG = "RileyLinkScan"; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothLeScanner mLEScanner; - private LeDeviceListAdapter mLeDeviceListAdapter; - public boolean mScanning; - private Handler mHandler; - public Snackbar snackbar; - public ScanSettings settings; - public List filters; - public ListView listBTScan; - public Toolbar toolbarBTScan; - public Context mContext = this; - - private static final int PERMISSION_REQUEST_COARSE_LOCATION = 30241; // arbitrary. - private static final int REQUEST_ENABLE_BT = 30242; // arbitrary - // Stops scanning after 10 seconds. - private static final long SCAN_PERIOD = 10000; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_riley_link_scan); - - // Initializes Bluetooth adapter. - final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); - mBluetoothAdapter = bluetoothManager.getAdapter(); - mHandler = new Handler(); - - mLeDeviceListAdapter = new LeDeviceListAdapter(); - listBTScan = (ListView) findViewById(R.id.listBTScan); - listBTScan.setAdapter(mLeDeviceListAdapter); - listBTScan.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - TextView textview = (TextView) view.findViewById(R.id.device_address); - String bleAddress = textview.getText().toString(); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - prefs.edit().putString(RT2Const.serviceLocal.rileylinkAddressKey, bleAddress).apply(); - - //Notify that we have a new rileylinkAddressKey - LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(new Intent(RT2Const.local.INTENT_NEW_rileylinkAddressKey)); - - Log.d(TAG, "New rileylinkAddressKey: " + bleAddress); - - //Notify that we have a new pumpIDKey - LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(new Intent(RT2Const.local.INTENT_NEW_pumpIDKey)); - finish(); - } - }); - - toolbarBTScan = (Toolbar) findViewById(R.id.toolbarBTScan); - toolbarBTScan.setTitle(R.string.title_activity_riley_link_scan); - setSupportActionBar(toolbarBTScan); - - snackbar = Snackbar.make(findViewById(R.id.RileyLinkScan), "Scanning...",Snackbar.LENGTH_INDEFINITE); - snackbar.setAction("STOP", new View.OnClickListener() { - @Override - public void onClick(View view) { - scanLeDevice(false); - } - }); - - startScanBLE(); - } - - @Override - protected void onPause() { - super.onPause(); - scanLeDevice(false); - mLeDeviceListAdapter.clear(); - mLeDeviceListAdapter.notifyDataSetChanged(); - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_bluetooth_scan, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.miScan: - startScanBLE(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - public void startScanBLE(){ - // https://developer.android.com/training/permissions/requesting.html - // http://developer.radiusnetworks.com/2015/09/29/is-your-beacon-app-ready-for-android-6.html - if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { - Toast.makeText(this, "R.string.ble_not_supported", Toast.LENGTH_SHORT).show(); - } else { - // Use this check to determine whether BLE is supported on the device. Then - // you can selectively disable BLE-related features. - if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) - != PackageManager.PERMISSION_GRANTED) { - //your code that requires permission - ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION }, - PERMISSION_REQUEST_COARSE_LOCATION); - } - - // Ensures Bluetooth is available on the device and it is enabled. If not, - // displays a dialog requesting user permission to enable Bluetooth. - if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { - Toast.makeText(this, "R.string.ble_not_enabled", Toast.LENGTH_SHORT).show(); - } else { - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - // Will request that GPS be enabled for devices running Marshmallow or newer. - LocationHelper.requestLocationForBluetooth(this); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); - startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); - } - - mLEScanner = mBluetoothAdapter.getBluetoothLeScanner(); - settings = new ScanSettings.Builder() - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .build(); - filters = new ArrayList(); - - scanLeDevice(true); - } - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_ENABLE_BT) { - if (resultCode == RESULT_OK) { - // User allowed Bluetooth to turn on - } else if (resultCode == RESULT_CANCELED) { - // Error, or user said "NO" - finish(); - } - } - } - - private void scanLeDevice(final boolean enable) { - if (enable) { - // Stops scanning after a pre-defined scan period. - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - mScanning = false; - mLEScanner.stopScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Stop"); - //Toast.makeText(mContext, "Scanning finished", Toast.LENGTH_SHORT).show(); - snackbar.dismiss(); - } - }, SCAN_PERIOD); - - mScanning = true; - mLEScanner.startScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Start"); - //Toast.makeText(this, "Scanning", Toast.LENGTH_SHORT).show(); - snackbar.show(); - } else { - mScanning = false; - mLEScanner.stopScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Stop"); - //Toast.makeText(this, "Scanning finished", Toast.LENGTH_SHORT).show(); - snackbar.dismiss(); - - } - } - private ScanCallback mScanCallback = new ScanCallback() { - @Override - public void onScanResult(int callbackType, ScanResult result) { - final BluetoothDevice device = result.getDevice(); - runOnUiThread(new Runnable() { - @Override - public void run() { - if (device.getName() != null && device.getName().length() > 0) { - mLeDeviceListAdapter.addDevice(device); - mLeDeviceListAdapter.notifyDataSetChanged(); - Log.d(TAG, "Found BLE" + device.getName()); - } - } - }); - } - - @Override - public void onBatchScanResults(final List results) { - runOnUiThread(new Runnable() { - @Override - public void run() { - for (ScanResult result: results) { - BluetoothDevice device = result.getDevice(); - if (device.getName() != null && device.getName().length() > 0) { - mLeDeviceListAdapter.addDevice(device); - Log.d(TAG, "Found BLE" + result.toString()); - } else { - Log.e(TAG, "Found BLE, but name appears to be missing. Ignoring. " + device.getAddress()); - } - } - mLeDeviceListAdapter.notifyDataSetChanged(); - } - }); - } - - @Override - public void onScanFailed(int errorCode) { - Log.e("Scan Failed", "Error Code: " + errorCode); - Toast.makeText(mContext, "Scan Failed " + errorCode, Toast.LENGTH_LONG).show(); - } - }; - - - - private class LeDeviceListAdapter extends BaseAdapter { - private ArrayList mLeDevices; - private LayoutInflater mInflator; - - public LeDeviceListAdapter() { - super(); - mLeDevices = new ArrayList<>(); - mInflator = RileyLinkScan.this.getLayoutInflater(); - } - - public void addDevice(BluetoothDevice device) { - if(!mLeDevices.contains(device)) { - mLeDevices.add(device); - notifyDataSetChanged(); - } - } - - public BluetoothDevice getDevice(int position) { - return mLeDevices.get(position); - } - - public void clear() { - mLeDevices.clear(); - notifyDataSetChanged(); - } - - @Override - public int getCount() { - return mLeDevices.size(); - } - - @Override - public Object getItem(int i) { - return mLeDevices.get(i); - } - - @Override - public long getItemId(int i) { - return i; - } - - @Override - public View getView(int i, View view, ViewGroup viewGroup) { - ViewHolder viewHolder; - // General ListView optimization code. - if (view == null) { - view = mInflator.inflate(R.layout.listitem_device, null); - viewHolder = new ViewHolder(); - viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address); - viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name); - view.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) view.getTag(); - } - - BluetoothDevice device = mLeDevices.get(i); - String deviceName = device.getName(); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - if(prefs.getString(RT2Const.serviceLocal.rileylinkAddressKey, "").compareTo(device.getAddress()) == 0) { - viewHolder.deviceName.setTextColor(getColor(R.color.secondary_text_light)); - viewHolder.deviceAddress.setTextColor(getColor(R.color.secondary_text_light)); - deviceName += " (" + getResources().getString(R.string.selected_device) + ")"; - } - viewHolder.deviceName.setText(deviceName); - viewHolder.deviceAddress.setText(device.getAddress()); - - return view; - } - } - - - static class ViewHolder { - TextView deviceName; - TextView deviceAddress; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyScanResults.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyScanResults.java deleted file mode 100644 index 4dcb91bab8..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyScanResults.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLink; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -/** - * Created by geoff on 5/30/16. - */ -public class FrequencyScanResults { - public ArrayList trials = new ArrayList<>(); - public double bestFrequencyMHz = 0.0; - public void sort() { - Collections.sort(trials, new Comparator() { - @Override - public int compare(FrequencyTrial trial1, FrequencyTrial trial2) { - return trial1.averageRSSI.compareTo(trial2.averageRSSI); - } - }); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyTrial.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyTrial.java deleted file mode 100644 index aa2a2eb418..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/FrequencyTrial.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLink; - -/** - * Created by geoff on 5/30/16. - */ -public class FrequencyTrial { - public int tries = 0; - public int successes = 0; - public Double averageRSSI = 0.0; - public double frequencyMHz = 0.0; -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManager.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManager.java deleted file mode 100644 index d96413b3a1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManager.java +++ /dev/null @@ -1,599 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLink; - -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RFSpy; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RFSpyResponse; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RadioPacket; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RadioResponse; -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.ButtonPressCarelinkMessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.CarelinkShortMessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.GetHistoryPageCarelinkMessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.GetPumpModelCarelinkMessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.MessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.MessageType; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages.PumpAckMessageBody; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PacketType; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.ISFTable; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.Page; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records.Record; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpMessage; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.ServiceData.ReadPumpClockResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.StringUtil; - -import org.joda.time.Duration; -import org.joda.time.IllegalFieldValueException; -import org.joda.time.Instant; -import org.joda.time.LocalDateTime; - -import java.util.ArrayList; - - -/** - * Created by geoff on 5/30/16. - */ -public class PumpManager { - private static final String TAG = "PumpManager"; - public double[] scanFrequencies = {916.45, 916.50, 916.55, 916.60, 916.65, 916.70, 916.75, 916.80}; - public static final int startSession_signal = 6656; // arbitrary. - //private long pumpAwakeUntil = 0; - private int pumpAwakeForMinutes = 6; - private final RFSpy rfspy; - private byte[] pumpID; - public boolean DEBUG_PUMPMANAGER = true; - private final Context context; - private SharedPreferences prefs; - private Instant lastGoodPumpCommunicationTime = new Instant(0); - - public PumpManager(Context context, RFSpy rfspy, byte[] pumpID) { - this.context = context; - this.rfspy = rfspy; - this.pumpID = pumpID; - prefs = context.getSharedPreferences(RT2Const.serviceLocal.sharedPreferencesKey, Context.MODE_PRIVATE); - } - - private PumpMessage runCommandWithArgs(PumpMessage msg) { - PumpMessage rval; - PumpMessage shortMessage = makePumpMessage(msg.messageType, new CarelinkShortMessageBody(new byte[]{0})); - // look for ack from short message - PumpMessage shortResponse = sendAndListen(shortMessage); - if (shortResponse.messageType.mtype == MessageType.PumpAck) { - rval = sendAndListen(msg); - return rval; - } else { - Log.e(TAG, "runCommandWithArgs: Pump did not ack Attention packet"); - } - return new PumpMessage(); - } - - protected PumpMessage sendAndListen(PumpMessage msg) { - return sendAndListen(msg, 2000); - } - - // All pump communications go through this function. - protected PumpMessage sendAndListen(PumpMessage msg, int timeout_ms) { - boolean showPumpMessages = true; - if (showPumpMessages) { - Log.i(TAG, "Sent:" + ByteUtil.shortHexString(msg.getTxData())); - } - RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), timeout_ms); - PumpMessage rval = new PumpMessage(resp.getRadioResponse().getPayload()); - if (rval.isValid()) { - // Mark this as the last time we heard from the pump. - rememberLastGoodPumpCommunicationTime(); - } - if (showPumpMessages) { - Log.i(TAG, "Received:" + ByteUtil.shortHexString(resp.getRadioResponse().getPayload())); - } - return rval; - } - - public Page getPumpHistoryPage(int pageNumber) { - RawHistoryPage rval = new RawHistoryPage(); - wakeup(pumpAwakeForMinutes); - PumpMessage getHistoryMsg = makePumpMessage(new MessageType(MessageType.CMD_M_READ_HISTORY), new GetHistoryPageCarelinkMessageBody(pageNumber)); - //Log.i(TAG,"getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData())); - // Ask the pump to transfer history (we get first frame?) - PumpMessage firstResponse = runCommandWithArgs(getHistoryMsg); - //Log.i(TAG,"getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); - - PumpMessage ackMsg = makePumpMessage(MessageType.PumpAck, new PumpAckMessageBody()); - GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse.getMessageBody().getTxData()); - int expectedFrameNum = 1; - boolean done = false; - //while (expectedFrameNum == currentResponse.getFrameNumber()) { - int failures = 0; - while (!done) { - // examine current response for problems. - byte[] frameData = currentResponse.getFrameData(); - if ((frameData != null) && (frameData.length > 0) && currentResponse.getFrameNumber() == expectedFrameNum) { - // success! got a frame. - if (frameData.length != 64) { - Log.w(TAG, "Expected frame of length 64, got frame of length " + frameData.length); - // but append it anyway? - } - // handle successful frame data - rval.appendData(currentResponse.getFrameData()); - RoundtripService.getInstance().announceProgress(((100 / 16) * currentResponse.getFrameNumber() + 1)); - Log.i(TAG, "getPumpHistoryPage: Got frame " + currentResponse.getFrameNumber()); - // Do we need to ask for the next frame? - if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722 - expectedFrameNum++; - } else { - done = true; // successful completion - } - } else { - if (frameData == null) { - Log.e(TAG, "null frame data, retrying"); - } else if (currentResponse.getFrameNumber() != expectedFrameNum) { - Log.w(TAG, String.format("Expected frame number %d, received %d (retrying)", expectedFrameNum, currentResponse.getFrameNumber())); - } else if (frameData.length == 0) { - Log.w(TAG, "Frame has zero length, retrying"); - } - failures++; - if (failures == 6) { - Log.e(TAG, String.format("6 failures in attempting to download frame %d of page %d, giving up.", expectedFrameNum, pageNumber)); - done = true; // failure completion. - } - } - if (!done) { - // ask for next frame - PumpMessage nextMsg = sendAndListen(ackMsg); - currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData()); - } - } - if (rval.getLength() != 1024) { - Log.w(TAG, "getPumpHistoryPage: short page. Expected length of 1024, found length of " + rval.getLength()); - } - if (rval.isChecksumOK() == false) { - Log.e(TAG, "getPumpHistoryPage: checksum is wrong"); - } - - rval.dumpToDebug(); - - Page page = new Page(); - //page.parseFrom(rval.getData(),PumpModel.MM522); - page.parseFrom(rval.getData(), PumpModel.MM522); - - return page; - } - - public ArrayList getAllHistoryPages() { - ArrayList pages = new ArrayList<>(); - - for (int pageNum = 0; pageNum < 16; pageNum++) { - pages.add(getPumpHistoryPage(pageNum)); - } - - return pages; - } - - public ArrayList getHistoryEventsSinceDate(Instant when) { - ArrayList pages = new ArrayList<>(); - for (int pageNum = 0; pageNum < 16; pageNum++) { - pages.add(getPumpHistoryPage(pageNum)); - for (Page page : pages) { - for (Record r : page.mRecordList) { - LocalDateTime timestamp = r.getTimestamp().getLocalDateTime(); - Log.i(TAG, "Found record: (" + r.getClass().getSimpleName() + ") " + timestamp.toString()); - } - } - } - return pages; - } - - private LocalDateTime parsePumpRTCBytes(byte[] bytes) { - if (bytes == null) return null; - if (bytes.length < 7) return null; - int hours = ByteUtil.asUINT8(bytes[0]); - int minutes = ByteUtil.asUINT8(bytes[1]); - int seconds = ByteUtil.asUINT8(bytes[2]); - int year = (ByteUtil.asUINT8(bytes[4]) & 0x3f) + 1984; - int month = ByteUtil.asUINT8(bytes[5]); - int day = ByteUtil.asUINT8(bytes[6]); - try { - LocalDateTime pumpTime = new LocalDateTime(year, month, day, hours, minutes, seconds); - return pumpTime; - } catch (IllegalFieldValueException e) { - Log.e(TAG, String.format("parsePumpRTCBytes: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", year, month, day, hours, minutes, seconds)); - return null; - } - } - - public ReadPumpClockResult getPumpRTC() { - ReadPumpClockResult rval = new ReadPumpClockResult(); - wakeup(pumpAwakeForMinutes); - PumpMessage getRTCMsg = makePumpMessage(new MessageType(MessageType.CMD_M_READ_RTC), new CarelinkShortMessageBody(new byte[]{0})); - Log.i(TAG, "getPumpRTC: " + ByteUtil.shortHexString(getRTCMsg.getTxData())); - PumpMessage response = sendAndListen(getRTCMsg); - if (response.isValid()) { - byte[] receivedData = response.getContents(); - if (receivedData != null) { - if (receivedData.length >= 9) { - LocalDateTime pumpTime = parsePumpRTCBytes(ByteUtil.substring(receivedData, 2, 7)); - if (pumpTime != null) { - rval.setTime(pumpTime); - rval.setResultOK(); - } else { - rval.setResultError(ServiceResult.ERROR_MALFORMED_PUMP_RESPONSE); - } - } else { - rval.setResultError(ServiceResult.ERROR_MALFORMED_PUMP_RESPONSE); - } - } else { - rval.setResultError(ServiceResult.ERROR_MALFORMED_PUMP_RESPONSE); - } - } else { - rval.setResultError(ServiceResult.ERROR_INVALID_PUMP_RESPONSE); - } - return rval; - } - - public PumpModel getPumpModel() { - wakeup(pumpAwakeForMinutes); - PumpMessage msg = makePumpMessage(new MessageType(MessageType.GetPumpModel), new GetPumpModelCarelinkMessageBody()); - Log.i(TAG, "getPumpModel: " + ByteUtil.shortHexString(msg.getTxData())); - PumpMessage response = sendAndListen(msg); - Log.i(TAG, "getPumpModel response: " + ByteUtil.shortHexString(response.getContents())); - byte[] contents = response.getContents(); - PumpModel rval = PumpModel.UNSET; - if (contents != null) { - if (contents.length >= 7) { - rval = PumpModel.fromString(StringUtil.fromBytes(ByteUtil.substring(contents, 3, 3))); - } else { - Log.w(TAG, "getPumpModel: Cannot return pump model number: data is too short."); - } - } else { - Log.w(TAG, "getPumpModel: Cannot return pump model number: null response"); - } - - return rval; - } - - - public ISFTable getPumpISFProfile() { - wakeup(pumpAwakeForMinutes); - PumpMessage getISFProfileMessage = makePumpMessage(new MessageType(MessageType.GetISFProfile), new CarelinkShortMessageBody()); - PumpMessage resp = sendAndListen(getISFProfileMessage); - ISFTable table = new ISFTable(); - table.parseFrom(resp.getContents()); - return table; - } - - public PumpMessage getBolusWizardCarbProfile() { - wakeup(pumpAwakeForMinutes); - PumpMessage getCarbProfileMessage = makePumpMessage(new MessageType(MessageType.CMD_M_READ_CARB_RATIOS), new CarelinkShortMessageBody()); - PumpMessage resp = sendAndListen(getCarbProfileMessage); - return resp; - } - - public void tryoutPacket(byte[] pkt) { - sendAndListen(makePumpMessage(pkt)); - } - - public void hunt() { - tryoutPacket(new byte[]{MessageType.CMD_M_READ_PUMP_STATUS, 0}); - tryoutPacket(new byte[]{MessageType.CMD_M_READ_FIRMWARE_VER, 0}); - tryoutPacket(new byte[]{MessageType.CMD_M_READ_INSULIN_REMAINING, 0}); - - } - - // See ButtonPressCarelinkMessageBody - public void pressButton(int which) { - wakeup(pumpAwakeForMinutes); - PumpMessage pressButtonMessage = makePumpMessage(new MessageType(MessageType.CMD_M_KEYPAD_PUSH), new ButtonPressCarelinkMessageBody(which)); - PumpMessage resp = sendAndListen(pressButtonMessage); - if (resp.messageType.mtype != MessageType.PumpAck) { - Log.e(TAG, "Pump did not ack button press."); - } - } - - public void wakeup(int duration_minutes) { - // If it has been longer than n minutes, do wakeup. Otherwise assume pump is still awake. - // **** FIXME: this wakeup doesn't seem to work well... must revisit - pumpAwakeForMinutes = duration_minutes; - Instant lastGood = getLastGoodPumpCommunicationTime(); -// Instant lastGoodPlus = lastGood.plus(new Duration(receiverDeviceAwakeForMinutes * 60 * 1000)); - Instant lastGoodPlus = lastGood.plus(new Duration(1 * 60 * 1000)); - Instant now = Instant.now(); - if (now.compareTo(lastGoodPlus) > 0) { - Log.i(TAG, "Waking pump..."); - PumpMessage msg = makePumpMessage(new MessageType(MessageType.PowerOn), new CarelinkShortMessageBody(new byte[]{(byte) duration_minutes})); - RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), (byte) 0, (byte) 200, (byte) 0, (byte) 0, 15000, (byte) 0); - Log.i(TAG, "wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw())); - } else { - Log.v(TAG, "Last pump communication was recent, not waking pump."); - } - } - - public void setRadioFrequencyForPump(double freqMHz) { - rfspy.setBaseFrequency(freqMHz); - } - - public double tuneForPump() { - return scanForPump(scanFrequencies); - } - - private int tune_tryFrequency(double freqMHz) { - rfspy.setBaseFrequency(freqMHz); - PumpMessage msg = makePumpMessage(new MessageType(MessageType.GetPumpModel), new GetPumpModelCarelinkMessageBody()); - RadioPacket pkt = new RadioPacket(msg.getTxData()); - RFSpyResponse resp = rfspy.transmitThenReceive(pkt, (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); - if (resp.wasTimeout()) { - Log.w(TAG, String.format("tune_tryFrequency: no pump response at frequency %.2f", freqMHz)); - } else if (resp.looksLikeRadioPacket()) { - RadioResponse radioResponse = new RadioResponse(resp.getRaw()); - if (radioResponse.isValid()) { - Log.w(TAG, String.format("tune_tryFrequency: saw response level %d at frequency %.2f", radioResponse.rssi, freqMHz)); - return radioResponse.rssi; - } else { - Log.w(TAG, "tune_tryFrequency: invalid radio response:" + ByteUtil.shortHexString(radioResponse.getPayload())); - } - } - return 0; - } - - public double quickTuneForPump(double startFrequencyMHz) { - double betterFrequency = startFrequencyMHz; - double stepsize = 0.05; - for (int tries = 0; tries < 4; tries++) { - double evenBetterFrequency = quickTunePumpStep(betterFrequency, stepsize); - if (evenBetterFrequency == 0.0) { - // could not see the pump at all. - // Try again at larger step size - stepsize += 0.05; - } else { - if ((int) (evenBetterFrequency * 100) == (int) (betterFrequency * 100)) { - // value did not change, so we're done. - break; - } - betterFrequency = evenBetterFrequency; // and go again. - } - } - if (betterFrequency == 0.0) { - // we've failed... caller should try a full scan for pump - Log.e(TAG, "quickTuneForPump: failed to find pump"); - } else { - rfspy.setBaseFrequency(betterFrequency); - if (betterFrequency != startFrequencyMHz) { - Log.i(TAG, String.format("quickTuneForPump: new frequency is %.2fMHz", betterFrequency)); - } else { - Log.i(TAG, String.format("quickTuneForPump: pump frequency is the same: %.2fMHz", startFrequencyMHz)); - } - } - return betterFrequency; - } - - private double quickTunePumpStep(double startFrequencyMHz, double stepSizeMHz) { - Log.i(TAG, "Doing quick radio tune for pump ID " + pumpID); - wakeup(pumpAwakeForMinutes); - int startRssi = tune_tryFrequency(startFrequencyMHz); - double lowerFrequency = startFrequencyMHz - stepSizeMHz; - int lowerRssi = tune_tryFrequency(lowerFrequency); - double higherFrequency = startFrequencyMHz + stepSizeMHz; - int higherRssi = tune_tryFrequency(higherFrequency); - if ((higherRssi == 0.0) && (lowerRssi == 0.0) && (startRssi == 0.0)) { - // we can't see the pump at all... - return 0.0; - } - if (higherRssi > startRssi) { - // need to move higher - return higherFrequency; - } else if (lowerRssi > startRssi) { - // need to move lower. - return lowerFrequency; - } - return startFrequencyMHz; - } - - private double scanForPump(double[] frequencies) { - Log.i(TAG, "Scanning for pump ID " + pumpID); - wakeup(pumpAwakeForMinutes); - FrequencyScanResults results = new FrequencyScanResults(); - - for (int i = 0; i < frequencies.length; i++) { - int tries = 3; - FrequencyTrial trial = new FrequencyTrial(); - trial.frequencyMHz = frequencies[i]; - rfspy.setBaseFrequency(frequencies[i]); - int sumRSSI = 0; - for (int j = 0; j < tries; j++) { - PumpMessage msg = makePumpMessage(new MessageType(MessageType.GetPumpModel), new GetPumpModelCarelinkMessageBody()); - RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); - if (resp.wasTimeout()) { - Log.e(TAG, String.format("scanForPump: Failed to find pump at frequency %.2f", frequencies[i])); - } else if (resp.looksLikeRadioPacket()) { - RadioResponse radioResponse = new RadioResponse(resp.getRaw()); - if (radioResponse.isValid()) { - sumRSSI += radioResponse.rssi; - trial.successes++; - } else { - Log.w(TAG, "Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw())); - } - } else { - Log.e(TAG, "scanForPump: raw response is " + ByteUtil.shortHexString(resp.getRaw())); - } - trial.tries++; - } - sumRSSI += -99.0 * (trial.tries - trial.successes); - trial.averageRSSI = (double) (sumRSSI) / (double) (trial.tries); - results.trials.add(trial); - } - results.sort(); // sorts in ascending order - Log.d(TAG, "Sorted scan results:"); - for (int k = 0; k < results.trials.size(); k++) { - FrequencyTrial one = results.trials.get(k); - Log.d(TAG, String.format("Scan Result[%d]: Freq=%.2f, avg RSSI = %f", k, one.frequencyMHz, one.averageRSSI)); - } - FrequencyTrial bestTrial = results.trials.get(results.trials.size() - 1); - results.bestFrequencyMHz = bestTrial.frequencyMHz; - if (bestTrial.successes > 0) { - rfspy.setBaseFrequency(results.bestFrequencyMHz); - return results.bestFrequencyMHz; - } else { - Log.e(TAG, "No pump response during scan."); - return 0.0; - } - } - - private PumpMessage makePumpMessage(MessageType messageType, MessageBody messageBody) { - PumpMessage msg = new PumpMessage(); - msg.init(new PacketType(PacketType.Carelink), pumpID, messageType, messageBody); - return msg; - } - - private PumpMessage makePumpMessage(byte msgType, MessageBody body) { - return makePumpMessage(new MessageType(msgType), body); - } - - private PumpMessage makePumpMessage(byte[] typeAndBody) { - PumpMessage msg = new PumpMessage(); - msg.init(ByteUtil.concat(ByteUtil.concat(new byte[]{(byte) 0xa7}, pumpID), typeAndBody)); - return msg; - } - - private void rememberLastGoodPumpCommunicationTime() { - lastGoodPumpCommunicationTime = Instant.now(); - SharedPreferences.Editor ed = prefs.edit(); - ed.putLong("lastGoodReceiverCommunicationTime", lastGoodPumpCommunicationTime.getMillis()); - ed.commit(); - } - - private Instant getLastGoodPumpCommunicationTime() { - // If we have a value of zero, we need to load from prefs. - if (lastGoodPumpCommunicationTime.getMillis() == new Instant(0).getMillis()) { - lastGoodPumpCommunicationTime = new Instant(prefs.getLong("lastGoodReceiverCommunicationTime", 0)); - // Might still be zero, but that's fine. - } - double minutesAgo = (Instant.now().getMillis() - lastGoodPumpCommunicationTime.getMillis()) / (1000.0 * 60.0); - Log.v(TAG, "Last good pump communication was " + minutesAgo + " minutes ago."); - return lastGoodPumpCommunicationTime; - } - - public PumpMessage getRemainingBattery() { - PumpMessage getBatteryMsg = makePumpMessage(new MessageType(MessageType.GetBattery), new CarelinkShortMessageBody()); - PumpMessage resp = sendAndListen(getBatteryMsg); - return resp; - } - - public PumpMessage getRemainingInsulin() { - PumpMessage msg = makePumpMessage(new MessageType(MessageType.CMD_M_READ_INSULIN_REMAINING), new CarelinkShortMessageBody()); - PumpMessage resp = sendAndListen(msg); - return resp; - } - - public PumpMessage getCurrentBasalRate() { - PumpMessage msg = makePumpMessage(new MessageType(MessageType.ReadTempBasal), new CarelinkShortMessageBody()); - PumpMessage resp = sendAndListen(msg); - return resp; - } - - PumpManagerStatus pumpManagerStatus = new PumpManagerStatus(); - - public PumpManagerStatus getPumpManagerStatus() { - return pumpManagerStatus; - } - - public void updatePumpManagerStatus() { - PumpMessage resp = getRemainingBattery(); - if (resp.isValid()) { - byte[] remainingBatteryBytes = resp.getContents(); - if (remainingBatteryBytes != null) { - if (remainingBatteryBytes.length == 5) { - /** - * 0x72 0x03, 0x00, 0x00, 0x82 - * meaning what ???? - */ - pumpManagerStatus.remainBattery = ByteUtil.asUINT8(remainingBatteryBytes[5]); - } - } - } - resp = getRemainingInsulin(); - byte[] insulinRemainingBytes = resp.getContents(); - if (insulinRemainingBytes != null) { - if (insulinRemainingBytes.length == 4) { - /* 0x73 0x02 0x05 0xd2 - * the 0xd2 (210) represents 21 units remaining. - */ - double insulinUnitsRemaining = ByteUtil.asUINT8(insulinRemainingBytes[3]) / 10.0; - pumpManagerStatus.remainUnits = insulinUnitsRemaining; - } - } - /* current basal */ - resp = getCurrentBasalRate(); - byte[] basalRateBytes = resp.getContents(); - if (basalRateBytes != null) { - if (basalRateBytes.length == 2) { - /** - * 0x98 0x06 - * 0x98 is "basal rate" - * 0x06 is what? Not currently running a temp basal, current basal is "standard" at 0 - */ - double basalRate = ByteUtil.asUINT8(basalRateBytes[1]); - pumpManagerStatus.currentBasal = basalRate; - } - } - // get last bolus amount - // get last bolus time - // get tempBasalInProgress - // get tempBasalRatio - // get tempBasalRemainMin - // get tempBasalStart - // get pump time - ReadPumpClockResult clockResult = getPumpRTC(); - if (clockResult.resultIsOK()) { - pumpManagerStatus.time = clockResult.getTime().toDate(); - } - // get last sync time - - } - - public void testPageDecode() { - byte[] raw = new byte[]{(byte) 0x6D, (byte) 0x62, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x63, (byte) 0x10, (byte) 0x6D, (byte) 0x63, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x5A, (byte) 0xA5, (byte) 0x49, (byte) 0x04, (byte) 0x10, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x6D, (byte) 0xA5, (byte) 0x49, (byte) 0x04, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x10, (byte) 0x6D, (byte) 0x64, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x0C, (byte) 0x00, - (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x01, (byte) 0x75, (byte) 0x94, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x64, (byte) 0x01, (byte) 0x44, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x17, (byte) 0x00, (byte) 0x4E, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x18, (byte) 0x00, (byte) 0x40, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, - (byte) 0x19, (byte) 0x00, (byte) 0x40, (byte) 0x81, (byte) 0x15, (byte) 0x05, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x65, (byte) 0x10, (byte) 0x6D, (byte) 0x65, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1A, (byte) 0x00, (byte) 0x47, (byte) 0x82, (byte) 0x09, (byte) 0x06, - (byte) 0x10, (byte) 0x1A, (byte) 0x01, (byte) 0x5C, (byte) 0x82, (byte) 0x09, (byte) 0x06, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x66, (byte) 0x10, (byte) 0x6D, (byte) 0x66, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x67, (byte) 0x10, (byte) 0x6D, (byte) 0x67, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x68, (byte) 0x10, (byte) 0x6D, (byte) 0x68, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x69, (byte) 0x10, (byte) 0x6D, (byte) 0x69, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6A, (byte) 0x10, (byte) 0x6D, (byte) 0x6A, (byte) 0x10, (byte) 0x05, (byte) 0x0C, - (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6B, (byte) 0x10, (byte) 0x6D, (byte) 0x6B, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6C, - (byte) 0x10, (byte) 0x6D, (byte) 0x6C, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6D, (byte) 0x10, (byte) 0x6D, (byte) 0x6D, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6E, (byte) 0x10, (byte) 0x6D, (byte) 0x6E, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6F, (byte) 0x10, (byte) 0x6D, (byte) 0x6F, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, - (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x19, (byte) 0x00, (byte) 0x40, (byte) 0x81, (byte) 0x03, (byte) 0x10, (byte) 0x10, (byte) 0x1A, (byte) 0x00, (byte) 0x68, (byte) 0x96, (byte) 0x0A, (byte) 0x10, (byte) 0x10, (byte) 0x1A, (byte) 0x01, (byte) 0x40, (byte) 0x97, (byte) 0x0A, (byte) 0x10, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x70, (byte) 0x10, (byte) 0x6D, (byte) 0x70, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x71, (byte) 0x10, (byte) 0x6D, (byte) 0x71, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x72, (byte) 0x10, (byte) 0x6D, (byte) 0x72, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x73, (byte) 0x10, (byte) 0x6D, (byte) 0x73, (byte) 0x10, (byte) 0x05, (byte) 0x0C, - (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x74, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2C, (byte) 0x79, - }; - Page page = new Page(); - page.parseFrom(raw, PumpModel.MM522); - page.parseByDates(raw, PumpModel.MM522); - page.parsePicky(raw, PumpModel.MM522); - Log.i(TAG, "testPageDecode: done"); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManagerStatus.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManagerStatus.java deleted file mode 100644 index d3896e10c4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/PumpManagerStatus.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLink; - -import java.util.Date; - -/** - * Created by geoff on 7/16/16. - * - * This class is intended to provide compatibility with HAPP, and was - * modeled after the PumpStatus class from happdanardriver - * - * happdanardriver/app/src/main/java/info/nightscout/danar/db/PumpStatus.java - */ -public class PumpManagerStatus { - public long getTimeIndex() { - return (long) Math.ceil(time.getTime() / 60000d ); - } - - public void setTimeIndex(long timeIndex) { - this.timeIndex = timeIndex; - } - - public long timeIndex; - - public Date time; - - public double remainUnits = 0; - - public int remainBattery = 0; - - public double currentBasal = 0; - - public int tempBasalInProgress = 0; - - public int tempBasalRatio = 0; - - public int tempBasalRemainMin = 0 ; - - public Date last_bolus_time ; - - public double last_bolus_amount = 0; - - public Date tempBasalStart; - - @Override - public String toString() { - return "PumpStatus{" + - "timeIndex=" + timeIndex + - ", time=" + time + - ", remainUnits=" + remainUnits + - ", remainBattery=" + remainBattery + - ", currentBasal=" + currentBasal + - ", tempBasalInProgress=" + tempBasalInProgress + - ", tempBasalRatio=" + tempBasalRatio + - ", tempBasalRemainMin=" + tempBasalRemainMin + - ", last_bolus_time=" + last_bolus_time + - ", last_bolus_amount=" + last_bolus_amount + - ", tempBasalStart=" + tempBasalStart + - '}'; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/RawHistoryPage.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/RawHistoryPage.java deleted file mode 100644 index 2fb01053ab..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLink/RawHistoryPage.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLink; - -import android.util.Log; - -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.CRC; - -/** - * Created by geoff on 6/4/16. - */ -public class RawHistoryPage { - private static final String TAG = "RawHistoryPage"; - byte[] data = new byte[0]; - public RawHistoryPage() { - } - public void appendData(byte[] newdata) { - data = ByteUtil.concat(data,newdata); - } - public byte[] getData() { - return data; - } - public int getLength() { - return data.length; - } - public boolean isChecksumOK() { - if (getLength() != 1024) { - return false; - } - byte[] computedCRC = CRC.calculate16CCITT(ByteUtil.substring(data,0,1022)); - return ((computedCRC[0] == data[1022]) && (computedCRC[1] == data[1023])); - } - - public void dumpToDebug() { - int linesize = 80; - int offset = 0; - while (offset < data.length) { - int bytesToLog = linesize; - if (offset + linesize > data.length) { - bytesToLog = data.length - offset; - } - Log.d(TAG,ByteUtil.shortHexString(ByteUtil.substring(data,offset,bytesToLog))); - offset += linesize; - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperation.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperation.java deleted file mode 100644 index 4c77fe2278..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RileyLinkBLE; - -import java.util.UUID; - -/** - * Created by geoff on 5/26/16. - */ -public abstract class BLECommOperation { - public boolean timedOut = false; - public boolean interrupted = false; - - // This is to be run on the main thread - public abstract void execute(RileyLinkBLE comm); - public void gattOperationCompletionCallback(UUID uuid, byte[] value) {} - public int getGattOperationTimeout_ms() { return 22000;} - - public byte[] getValue() { return null; } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperationResult.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperationResult.java deleted file mode 100644 index 4570480310..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/BLECommOperationResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations; - -/** - * Created by geoff on 5/26/16. - */ -public class BLECommOperationResult { - public byte[] value; - public int resultCode; - - public static final int RESULT_NONE = 0; - public static final int RESULT_SUCCESS = 1; - public static final int RESULT_TIMEOUT = 2; - public static final int RESULT_BUSY = 3; - public static final int RESULT_INTERRUPTED = 4; - public static final int RESULT_NOT_CONFIGURED = 5; -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicReadOperation.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicReadOperation.java deleted file mode 100644 index e6d647b28d..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicReadOperation.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.os.SystemClock; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.GattAttributes; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RileyLinkBLE; - -import java.util.UUID; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * Created by geoff on 5/26/16. - */ -public class CharacteristicReadOperation extends BLECommOperation { - private static final String TAG = "CharacteristicReadOp"; - private BluetoothGatt gatt; - private BluetoothGattCharacteristic characteristic; - private byte[] value; - private Semaphore operationComplete = new Semaphore(0,true); - public CharacteristicReadOperation(BluetoothGatt gatt, BluetoothGattCharacteristic chara) { - this.gatt = gatt; - this.characteristic = chara; - } - @Override - public void execute(RileyLinkBLE comm) { - gatt.readCharacteristic(characteristic); - // wait here for callback to notify us that value was read. - try { - boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); - if (didAcquire) { - SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier understanding of the sequence of events. - // success - } else { - Log.e(TAG,"Timeout waiting for gatt write operation to complete"); - timedOut = true; - } - } catch (InterruptedException e) { - Log.e(TAG,"Interrupted while waiting for gatt write operation to complete"); - interrupted = true; - } - value = characteristic.getValue(); - } - - @Override - public void gattOperationCompletionCallback(UUID uuid, byte[] value) { - super.gattOperationCompletionCallback(uuid, value); - if (!characteristic.getUuid().equals(uuid)) { - Log.e(TAG,String.format("Completion callback: UUID does not match! out of sequence? Found: %s, should be %s", - GattAttributes.lookup(characteristic.getUuid()),GattAttributes.lookup(uuid))); - } - operationComplete.release(); - } - - @Override - public byte[] getValue() { - return value; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicWriteOperation.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicWriteOperation.java deleted file mode 100644 index a08264edf6..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/CharacteristicWriteOperation.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.os.SystemClock; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.GattAttributes; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RileyLinkBLE; - -import java.util.UUID; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * Created by geoff on 5/26/16. - */ -public class CharacteristicWriteOperation extends BLECommOperation { - private static final String TAG = "CharacteristicWriteOp"; - private BluetoothGatt gatt; - private BluetoothGattCharacteristic characteristic; - private byte[] value; - private Semaphore operationComplete = new Semaphore(0,true); - - public CharacteristicWriteOperation(BluetoothGatt gatt, BluetoothGattCharacteristic chara, byte[] value) { - this.gatt = gatt; - this.characteristic = chara; - this.value = value; - } - @Override - public void execute(RileyLinkBLE comm) { - - characteristic.setValue(value); - gatt.writeCharacteristic(characteristic); - // wait here for callback to notify us that value was written. - try { - boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); - if (didAcquire) { - SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier understanding of the sequence of events. - // success - } else { - Log.e(TAG,"Timeout waiting for gatt write operation to complete"); - timedOut = true; - } - } catch (InterruptedException e) { - Log.e(TAG,"Interrupted while waiting for gatt write operation to complete"); - interrupted = true; - } - - } - - // This will be run on the IBinder thread - @Override - public void gattOperationCompletionCallback(UUID uuid, byte[] value) { - if (!characteristic.getUuid().equals(uuid)) { - Log.e(TAG,String.format("Completion callback: UUID does not match! out of sequence? Found: %s, should be %s", - GattAttributes.lookup(characteristic.getUuid()),GattAttributes.lookup(uuid))); - } - operationComplete.release(); - } - - @Override - public byte[] getValue() { - return value; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/DescriptorWriteOperation.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/DescriptorWriteOperation.java deleted file mode 100644 index a3519228bc..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/BLECommOperations/DescriptorWriteOperation.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattDescriptor; -import android.os.SystemClock; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RileyLinkBLE; - -import java.util.UUID; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * Created by geoff on 5/26/16. - */ -public class DescriptorWriteOperation extends BLECommOperation { - - private static final String TAG = "DescrWriteOp"; - private BluetoothGatt gatt; - private BluetoothGattDescriptor descr; - private byte[] value; - private Semaphore operationComplete = new Semaphore(0,true); - - public DescriptorWriteOperation(BluetoothGatt gatt, BluetoothGattDescriptor descr, byte[] value) { - this.gatt = gatt; - this.descr = descr; - this.value = value; - } - - @Override - public void gattOperationCompletionCallback(UUID uuid, byte[] value) { - super.gattOperationCompletionCallback(uuid, value); - operationComplete.release(); - } - - @Override - public void execute(RileyLinkBLE comm) { - descr.setValue(value); - gatt.writeDescriptor(descr); - // wait here for callback to notify us that value was read. - try { - boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); - if (didAcquire) { - SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier understanding of the sequence of events. - // success - } else { - Log.e(TAG,"Timeout waiting for descriptor write operation to complete"); - timedOut = true; - } - } catch (InterruptedException e) { - Log.e(TAG,"Interrupted while waiting for descriptor write operation to complete"); - interrupted = true; - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/GattAttributes.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/GattAttributes.java deleted file mode 100644 index a64d19f620..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/GattAttributes.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import java.util.HashMap; -import java.util.UUID; - -/** - * Created by geoff on 5/21/16. - */ -public class GattAttributes { - // NOTE: these uuid strings must be lower case! - private static HashMap attributes = new HashMap(); - public static String PREFIX = "0000"; - public static String SUFFIX = "-0000-1000-8000-00805f9b34fb"; - public static String SERVICE_GAP = PREFIX + "1800" + SUFFIX; - public static String CHARA_GAP_NAME = PREFIX + "2a00" + SUFFIX; - public static String CHARA_GAP_NUM = PREFIX + "2a01" + SUFFIX; - - public static String SERVICE_BATTERY = PREFIX + "180f" + SUFFIX; - public static String CHARA_BATTERY_UNK = PREFIX + "2a19" + SUFFIX; - - public static String SERVICE_RADIO = "0235733b-99c5-4197-b856-69219c2a3845"; - public static String CHARA_RADIO_DATA = "c842e849-5028-42e2-867c-016adada9155"; - public static String CHARA_RADIO_RESPONSE_COUNT = "6e6c7910-b89e-43a5-a0fe-50c5e2b81f4a"; - public static String CHARA_RADIO_TIMER_TICK = "6e6c7910-b89e-43a5-78af-50c5e2b86f7e"; - public static String CHARA_RADIO_CUSTOM_NAME = "d93b2af0-1e28-11e4-8c21-0800200c9a66"; - public static String CHARA_RADIO_VERSION = "30d99dc9-7c91-4295-a051-0a104d238cf2"; - - // table of names for uuids - static { - attributes.put(SERVICE_GAP, "Device Information Service"); - attributes.put(SERVICE_BATTERY,"Battery Service"); - attributes.put(CHARA_RADIO_CUSTOM_NAME,"customName"); - attributes.put(CHARA_RADIO_DATA,"data"); - attributes.put(CHARA_RADIO_RESPONSE_COUNT,"responseCount"); - attributes.put(CHARA_RADIO_TIMER_TICK,"timerTick"); - attributes.put(CHARA_RADIO_VERSION,"radioVersion"); - } - - public static String lookup(UUID uuid) { - return lookup(uuid.toString()); - } - - public static String lookup(String uuid) { - return lookup(uuid, uuid); - } - - public static String lookup(String uuid, String defaultName) { - String name = attributes.get(uuid); - return name == null ? defaultName : name; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpy.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpy.java deleted file mode 100644 index aec53007d0..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpy.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import android.content.Context; -import android.os.SystemClock; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.BLECommOperation; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.BLECommOperationResult; -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.StringUtil; -import com.gxwtech.roundtrip2.util.ThreadUtil; - -import java.util.UUID; - -/** - * Created by geoff on 5/26/16. - */ -public class RFSpy { - public static final byte RFSPY_GET_STATE = 1; - public static final byte RFSPY_GET_VERSION = 2; - public static final byte RFSPY_GET_PACKET = 3; // aka Listen, receive - public static final byte RFSPY_SEND = 4; - public static final byte RFSPY_SEND_AND_LISTEN = 5; - public static final byte RFSPY_UPDATE_REGISTER = 6; - public static final byte RFSPY_RESET = 7; - - public static final long RILEYLINK_FREQ_XTAL = 24000000; - - public static final byte CC111X_REG_FREQ2 = 0x09; - public static final byte CC111X_REG_FREQ1 = 0x0A; - public static final byte CC111X_REG_FREQ0 = 0x0B; - public static final byte CC111X_MDMCFG4 = 0x0C; - public static final byte CC111X_MDMCFG3 = 0x0D; - public static final byte CC111X_MDMCFG2 = 0x0E; - public static final byte CC111X_MDMCFG1 = 0x0F; - public static final byte CC111X_MDMCFG0 = 0x10; - public static final byte CC111X_AGCCTRL2 = 0x17; - public static final byte CC111X_AGCCTRL1 = 0x18; - public static final byte CC111X_AGCCTRL0 = 0x19; - public static final byte CC111X_FREND1 = 0x1A; - public static final byte CC111X_FREND0 = 0x1B; - - public static final int EXPECTED_MAX_BLUETOOTH_LATENCY_MS = 1500; - - private static final String TAG = "RFSpy"; - private RileyLinkBLE rileyLinkBle; - private RFSpyReader reader; - private Context context; - UUID radioServiceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); - UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); - UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION); - UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT); - - private static final byte[] pumpID = {0x51, (byte)0x81, 0x63}; - - public RFSpy(Context context, RileyLinkBLE rileyLinkBle) { - this.context = context; - this.rileyLinkBle = rileyLinkBle; - reader = new RFSpyReader(context, rileyLinkBle); - } - - // Call this after the RL services are discovered. - // Starts an async task to read when data is available - public void startReader() { - rileyLinkBle.registerRadioResponseCountNotification(new Runnable() { - @Override - public void run() { - newDataIsAvailable(); - } - }); - reader.start(); - } - - // Call this from the "response count" notification handler. - public void newDataIsAvailable() { - // pass the message to the reader (which should be internal to RFSpy) - reader.newDataIsAvailable(); - } - - // This gets the version from the BLE113, not from the CC1110. - // I.e., this gets the version from the BLE interface, not from the radio. - public String getVersion() { - BLECommOperationResult result = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID,radioVersionUUID); - if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - return StringUtil.fromBytes(result.value); - } else { - Log.e(TAG,"getVersion failed with code: "+result.resultCode); - return "(null)"; - } - } - - // The caller has to know how long the RFSpy will be busy with what was sent to it. - private RFSpyResponse writeToData(byte[] bytes, int responseTimeout_ms) { - SystemClock.sleep(100); - // FIXME drain read queue? - byte[] junkInBuffer = reader.poll(0); - - while (junkInBuffer != null) { - Log.w(TAG, ThreadUtil.sig()+"writeToData: draining read queue, found this: " + ByteUtil.shortHexString(junkInBuffer)); - junkInBuffer = reader.poll(0); - } - - // prepend length, and send it. - byte[] prepended = ByteUtil.concat(new byte[] {(byte)(bytes.length)},bytes); - BLECommOperationResult writeCheck = rileyLinkBle.writeCharacteristic_blocking(radioServiceUUID,radioDataUUID,prepended); - if (writeCheck.resultCode != BLECommOperationResult.RESULT_SUCCESS) { - Log.e(TAG,"BLE Write operation failed, code=" + writeCheck.resultCode); - return new RFSpyResponse(); // will be a null (invalid) response - } - SystemClock.sleep(100); - //Log.i(TAG,ThreadUtil.sig()+String.format(" writeToData:(timeout %d) %s",(responseTimeout_ms),ByteUtil.shortHexString(prepended))); - byte[] rawResponse = reader.poll(responseTimeout_ms); - RFSpyResponse resp = new RFSpyResponse(rawResponse); - if (rawResponse == null) { - Log.e(TAG,"writeToData: No response from RileyLink"); - } else { - if (resp.wasInterrupted()) { - Log.e(TAG, "writeToData: RileyLink was interrupted"); - } else if (resp.wasTimeout()) { - Log.e(TAG, "writeToData: RileyLink reports timeout"); - } else if (resp.isOK()) { - Log.w(TAG, "writeToData: RileyLink reports OK"); - } else { - if (resp.looksLikeRadioPacket()) { - RadioResponse radioResp = resp.getRadioResponse(); - byte[] responsePayload = radioResp.getPayload(); - Log.i(TAG,"writeToData: decoded radio response is "+ByteUtil.shortHexString(responsePayload)); - } - //Log.i(TAG, "writeToData: raw response is " + ByteUtil.shortHexString(rawResponse)); - } - } - return resp; - } - - public RFSpyResponse getRadioVersion() { - RFSpyResponse resp = writeToData(new byte[] {RFSPY_GET_VERSION},1000); - if (resp == null) { - Log.e(TAG,"getRadioVersion returned null"); - } - /* - Log.d(TAG,"checking response count"); - BLECommOperationResult checkRC = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID,responseCountUUID); - if (checkRC.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - Log.d(TAG,"Response count is: " + ByteUtil.shortHexString(checkRC.value)); - } else { - Log.e(TAG,"Error getting response count, code is " + checkRC.resultCode); - } - */ - return resp; - } - - public RFSpyResponse transmit(RadioPacket radioPacket, byte sendChannel, byte repeatCount, byte delay_ms) { - // append checksum, encode data, send it. - byte[] fullPacket = ByteUtil.concat(new byte[] {RFSPY_SEND,sendChannel,repeatCount, delay_ms},radioPacket.getEncoded()); - RFSpyResponse response = writeToData(fullPacket,repeatCount * delay_ms); - return response; - } - - public RFSpyResponse receive(byte listenChannel, int timeout_ms, byte retryCount) { - int receiveDelay = timeout_ms * (retryCount+1); - byte[] listen = {RFSPY_GET_PACKET,listenChannel, - (byte)((timeout_ms >> 24)&0x0FF), - (byte)((timeout_ms >> 16)&0x0FF), - (byte)((timeout_ms >> 8)&0x0FF), - (byte)(timeout_ms & 0x0FF), - retryCount}; - return writeToData(listen,receiveDelay); - } - - public RFSpyResponse transmitThenReceive(RadioPacket pkt, int timeout_ms) { - return transmitThenReceive(pkt,(byte)0,(byte)0,(byte)0,(byte)0,timeout_ms,(byte)0); - } - - public RFSpyResponse transmitThenReceive(RadioPacket pkt, byte sendChannel, byte repeatCount, byte delay_ms, byte listenChannel, int timeout_ms, byte retryCount) { - - int sendDelay = repeatCount * delay_ms; - int receiveDelay = timeout_ms * (retryCount + 1); - byte[] sendAndListen = {RFSPY_SEND_AND_LISTEN,sendChannel,repeatCount,delay_ms,listenChannel, - (byte)((timeout_ms >> 24)&0x0FF), - (byte)((timeout_ms >> 16)&0x0FF), - (byte)((timeout_ms >> 8)&0x0FF), - (byte)(timeout_ms & 0x0FF), - retryCount}; - byte[] fullPacket = ByteUtil.concat(sendAndListen,pkt.getEncoded()); - return writeToData(fullPacket, sendDelay + receiveDelay + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); - } - - public RFSpyResponse updateRegister(byte addr, byte val) { - byte[] updateRegisterPkt = new byte[] {RFSPY_UPDATE_REGISTER,addr,val}; - RFSpyResponse resp = writeToData(updateRegisterPkt,EXPECTED_MAX_BLUETOOTH_LATENCY_MS); - return resp; - } - - public void setBaseFrequency(double freqMHz) { - int value = (int)(freqMHz * 1000000/((double)(RILEYLINK_FREQ_XTAL)/Math.pow(2.0,16.0))); - updateRegister(CC111X_REG_FREQ0, (byte)(value & 0xff)); - updateRegister(CC111X_REG_FREQ1, (byte)((value >> 8) & 0xff)); - updateRegister(CC111X_REG_FREQ2, (byte)((value >> 16) & 0xff)); - Log.w(TAG,String.format("Set frequency to %.2f",freqMHz)); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpyReader.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpyReader.java deleted file mode 100644 index 938aab42cc..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFSpyReader.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import android.content.Context; -import android.os.AsyncTask; -import android.os.SystemClock; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.BLECommOperationResult; -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.ThreadUtil; - -import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -/** - * Created by geoff on 5/26/16. - */ -public class RFSpyReader { - private static final String TAG = "RFSpyReader"; - private Context context; - private RileyLinkBLE rileyLinkBle; - private Semaphore waitForRadioData = new Semaphore(0,true); - AsyncTask readerTask; - private LinkedBlockingQueue mDataQueue = new LinkedBlockingQueue<>(); - private int acquireCount = 0; - private int releaseCount = 0; - - public RFSpyReader(Context context, RileyLinkBLE rileyLinkBle) { - this.context = context; - this.rileyLinkBle = rileyLinkBle; - } - - public void init(Context context, RileyLinkBLE rileyLinkBLE) { - this.context = context; - this.rileyLinkBle = rileyLinkBLE; - } - - public void setRileyLinkBle(RileyLinkBLE rileyLinkBle) { - if (readerTask != null) { - readerTask.cancel(true); - } - this.rileyLinkBle = rileyLinkBle; - } - - // This timeout must be coordinated with the length of the RFSpy radio operation or Bad Things Happen. - public byte[] poll(int timeout_ms) { - Log.v(TAG, ThreadUtil.sig()+"Entering poll at t=="+SystemClock.uptimeMillis()+", timeout is "+timeout_ms+" mDataQueue size is "+mDataQueue.size()); - if (mDataQueue.isEmpty()) - try { - // block until timeout or data available. - // returns null if timeout. - byte[] dataFromQueue = mDataQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); - if (dataFromQueue != null) { - Log.d(TAG, "Got data [" + ByteUtil.shortHexString(dataFromQueue) + "] at t==" + SystemClock.uptimeMillis()); - } else { - Log.d(TAG, "Got data [null] at t==" + SystemClock.uptimeMillis()); - } - return dataFromQueue; - } catch (InterruptedException e) { - Log.e(TAG,"poll: Interrupted waiting for data"); - } - return null; - } - - // Call this from the "response count" notification handler. - public void newDataIsAvailable() { - releaseCount++; - Log.v(TAG,ThreadUtil.sig()+"waitForRadioData released(count="+releaseCount+") at t="+SystemClock.uptimeMillis()); - waitForRadioData.release(); - } - - public void start() { - readerTask = new AsyncTask() { - @Override - protected Void doInBackground(Void... voids) { - UUID serviceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); - UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); - BLECommOperationResult result; - while (true) { - try { - acquireCount++; - waitForRadioData.acquire(); - Log.v(TAG,ThreadUtil.sig()+"waitForRadioData acquired (count="+acquireCount+") at t="+SystemClock.uptimeMillis()); - SystemClock.sleep(100); - SystemClock.sleep(1); - result = rileyLinkBle.readCharacteristic_blocking(serviceUUID, radioDataUUID); - SystemClock.sleep(100); - - if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - // only data up to the first null is valid - for (int i=0; i 2) { - return true; - } - return false; - } - - public byte[] getRaw() { - return raw; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFTools.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFTools.java deleted file mode 100644 index 8b62ee29b2..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RFTools.java +++ /dev/null @@ -1,295 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import android.util.Log; - -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.CRC; - -import java.util.ArrayList; - -/** - * Created by geoff on 7/31/15. - */ -public class RFTools { - private static final String TAG = "RFTools"; - /* - CodeSymbols is an ordered list of translations - 6bits -> 4 bits, in order from 0x0 to 0xF - The 6 bit codes are what is used on the RF side of the RileyLink - to communicate with a Medtronic pump. - - */ - public static byte[] CodeSymbols = { - 0x15, - 0x31, - 0x32, - 0x23, - 0x34, - 0x25, - 0x26, - 0x16, - 0x1a, - 0x19, - 0x2a, - 0x0b, - 0x2c, - 0x0d, - 0x0e, - 0x1c - }; - - public static byte[] appendChecksum(final byte[] input) { - if (input == null) { - return null; - } - if (input.length == 0) { - return null; - } - byte[] rval = new byte[input.length+1]; - System.arraycopy(input, 0, rval, 0, input.length); - byte mycrc = CRC.crc8(input); - Log.d(TAG,String.format("Adding checksum 0x%02X to %d byte array from 0x%02X to 0x%02X",mycrc,input.length,input[0],input[input.length-1])); - rval[input.length] = mycrc; - return rval; - } - - public static ArrayList fromBytes(byte[] data) { - ArrayList rval = new ArrayList<>(); - for (int i=0; i data) { - byte[] rval = new byte[data.size()]; - for (int i = 0; i < data.size(); i++) { - rval[i] = data.get(i); - } - return rval; - } - -/* - + (NSData*)encode4b6b:(NSData*)data { - NSMutableData *outData = [NSMutableData data]; - NSMutableData *dataPlusCrc = [data mutableCopy]; - unsigned char crc = [MinimedPacket crcForData:data]; - [dataPlusCrc appendBytes:&crc length:1]; - char codes[16] = {21,49,50,35,52,37,38,22,26,25,42,11,44,13,14,28}; - const unsigned char *inBytes = [dataPlusCrc bytes]; - unsigned int acc = 0x0; - int bitcount = 0; - for (int i=0; i < dataPlusCrc.length; i++) { - acc <<= 6; - acc |= codes[inBytes[i] >> 4]; - bitcount += 6; - - acc <<= 6; - acc |= codes[inBytes[i] & 0x0f]; - bitcount += 6; - - while (bitcount >= 8) { - unsigned char outByte = acc >> (bitcount-8) & 0xff; - [outData appendBytes:&outByte length:1]; - bitcount -= 8; - acc &= (0xffff >> (16-bitcount)); - } - } - if (bitcount > 0) { - acc <<= (8-bitcount); - unsigned char outByte = acc & 0xff; - [outData appendBytes:&outByte length:1]; - } - return outData; - } -*/ - - public static final byte[] codes = new byte[] {21,49,50,35,52,37,38,22,26,25,42,11,44,13,14,28 }; - - /* O(n) lookup. Run on an O(n) translation of a byte-stream, gives O(n**2) performance. Sigh. */ - public static int codeIndex(byte b) { - for (int i=0; i< codes.length; i++) { - if (b == codes[i]) { - return i; - } - } - return -1; - } - - public static byte[] encode4b6b(byte[] data) { - if ((data.length % 2)!=0) { - // Log.e(TAG,"Warning: data is odd number of bytes"); - } - // use arraylists because byte[] is annoying. - ArrayList inData = fromBytes(data); - ArrayList outData = new ArrayList<>(); - - int acc = 0; - int bitcount = 0; - int i; - for (i=0; i> 4) & 0x0f]; - bitcount += 6; - - acc <<= 6; - acc |= codes[inData.get(i) & 0x0f]; - bitcount += 6; - - while (bitcount >= 8) { - byte outByte = (byte)(acc >> (bitcount-8) & 0xff); - outData.add(outByte); - bitcount -= 8; - acc &= (0xffff >> (16 - bitcount)); - } - } - if (bitcount > 0) { - acc <<= 6; - acc |= 0x14; // marks uneven packet boundary. - bitcount += 6; - if (bitcount >= 8) { - byte outByte = (byte)((acc >> (bitcount - 8)) & 0xff); - outData.add(outByte); - bitcount -=8; - // acc &= (0xffff >> (16 - bitcount)); - } - while(bitcount >=8) { - outData.add((byte)0); - bitcount -= 8; - } - } - - - // convert back to byte[] - byte[] rval = toBytes(outData); - - return rval; - - } - - public static void test() { - /* - {0xa7} -> {0xa9, 0x60} - {0xa7, 0x12} -> {0xa9, 0x6c, 0x72} - {0xa7, 0x12, 0xa7} -> {0xa9, 0x6c, 0x72, 0xa9, 0x60} - */ - /* test compare */ - byte[] s1 = {0,1,2}; - byte[] s2 = {2,1,0,3}; - byte[] s3 = {0,1,2,3}; - if (ByteUtil.compare(s1,s1)!=0) { - Log.e(TAG,"test: compare failed."); - } - if (ByteUtil.compare(s1,s2)>=0) { - Log.e(TAG,"test: compare failed."); - } - if (ByteUtil.compare(s2,s1)<=0) { - Log.e(TAG,"test: compare failed."); - } - if (ByteUtil.compare(s1,s3)>=0) { - Log.e(TAG,"test: compare failed."); - } - //testCompose(new byte[] {(byte)0xa7, (byte)0xa7}); - byte[] bs = encode4b6b(new byte[]{(byte) 0xa7}); - byte[] out = new byte[] {(byte)(0xa9),0x65}; - if (ByteUtil.compare(bs,out)!=0) { - Log.e(TAG,"encode Data failed: expected "+ByteUtil.shortHexString(out)+" but got "+ByteUtil.shortHexString(bs)); - } - bs = encode4b6b(new byte[]{(byte) 0xa7, 0x12}); - out = new byte[] {(byte)(0xa9),0x6c,0x72}; - if (ByteUtil.compare(bs,out)!=0) { - Log.e(TAG,"encode Data failed: expected "+ByteUtil.shortHexString(out)+" but got "+ByteUtil.shortHexString(bs)); - } - bs = encode4b6b(new byte[]{(byte) 0xa7, 0x12, (byte) 0xa7}); - out = new byte[] {(byte)(0xa9),0x6c,0x72,(byte)0xa9,0x65}; - if (ByteUtil.compare(bs,out)!=0) { - Log.e(TAG,"encode Data failed: expected "+ByteUtil.shortHexString(out)+" but got "+ByteUtil.shortHexString(bs)); - } - return; - } - - public static byte[] decode4b6b(byte[] raw) throws NumberFormatException { - /* - if ((raw.length % 2) != 0) { - Log.e(TAG,"Warning: data is odd number of bytes"); - } - */ - byte[] rval = new byte[]{}; - int availableBits = 0; - int codingErrors = 0; - int x = 0; - //Log.w(TAG,"decode4b6b: untested code"); - //Log.w(TAG,String.format("Decoding %d bytes: %s",raw.length,ByteUtil.shortHexString(raw))); - for (int i=0; i= 12) { - // take top six - int highcode = (x >> (availableBits - 6)) & 0x3F; - int highIndex = codeIndex((byte) (highcode)); - // take bottom six - int lowcode = (x >> (availableBits - 12)) & 0x3F; - int lowIndex = codeIndex((byte) (lowcode)); - // special case at end of transmission on uneven boundaries: - if ((highIndex >= 0) && (lowIndex >= 0)) { - byte decoded = (byte) ((highIndex << 4) + lowIndex); - rval = ByteUtil.concat(rval, decoded); - /* - Log.d(TAG,String.format("i=%d,x=0x%08X,0x%02X->0x%02X, 0x%02X->0x%02X, result: 0x%02X, %d bits remaining, errors %d, bytes remaining: %s", - i,x,highcode,highIndex, lowcode, lowIndex,decoded,availableBits,codingErrors,ByteUtil.shortHexString(ByteUtil.substring(raw,i+1,raw.length-i-1)))); - */ - } else { - //Log.d(TAG,String.format("i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining",i,x,highcode,lowcode,availableBits)); - codingErrors++; - } - - availableBits -= 12; - x = x & (0x0000ffff >> (16 - availableBits)); - } else { - //Log.d(TAG,String.format("i=%d, skip: x=0x%08X, available bits %d",i,x,availableBits)); - } - } - if (availableBits !=0) { - if ((availableBits == 4) && (x == 0x05)) { - // normal end - } else { - Log.e(TAG, "decode4b6b: failed clean decode -- extra bits available (not marker)(" + availableBits + ")"); - codingErrors++; - } - } else { - // also normal end. - } - if (codingErrors>0) { - Log.e(TAG, "decode4b6b: "+codingErrors+" coding errors encountered."); - throw new NumberFormatException(); - } - return rval; - } - - public static String toHexString(byte[] array) { - return toHexString(array, 0, array.length); - } - - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - public static String toHexString(byte[] array, int offset, int length) { - char[] buf = new char[length * 2]; - - int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { - byte b = array[i]; - buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; - buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; - } - - return new String(buf); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioPacket.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioPacket.java deleted file mode 100644 index b6916e73e9..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioPacket.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.CRC; - -/** - * Created by geoff on 5/22/16. - */ - -public class RadioPacket { - protected byte[] pkt; - public RadioPacket(byte[] pkt) { - this.pkt = pkt; - } - public byte[] getRaw() { - return pkt; - } - public byte[] getEncoded() { - byte[] withCRC = ByteUtil.concat(pkt, CRC.crc8(pkt)); - byte[] encoded = RFTools.encode4b6b(withCRC); - byte[] withNullTerm = ByteUtil.concat(encoded,(byte)0); - return withNullTerm; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioResponse.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioResponse.java deleted file mode 100644 index 8d27ab9210..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RadioResponse.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import android.util.Log; - -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.CRC; - -/** - * Created by geoff on 5/30/16. - */ -public class RadioResponse { - private static final String TAG = "RadioResponse"; - public boolean decodedOK = false; - public int rssi; - public int responseNumber; - public byte[] decodedPayload = new byte[0]; - public byte receivedCRC; - - public RadioResponse() { - } - - public RadioResponse(byte[] rxData) { - init(rxData); - } - - public boolean isValid() { - if (!decodedOK) { - return false; - } - if (decodedPayload != null) { - if (receivedCRC == CRC.crc8(decodedPayload)) { - return true; - } - } - return false; - } - - public void init(byte[] rxData) { - if (rxData == null) { - return; - } - if (rxData.length < 3) { - // This does not look like something valid heard from a RileyLink device - return; - } - rssi = rxData[0]; - responseNumber = rxData[1]; - byte[] encodedPayload = ByteUtil.substring(rxData, 2, rxData.length - 2); - try { - byte[] decodeThis = RFTools.decode4b6b(encodedPayload); - decodedOK = true; - decodedPayload = ByteUtil.substring(decodeThis, 0, decodeThis.length - 1); - byte calculatedCRC = CRC.crc8(decodedPayload); - receivedCRC = decodeThis[decodeThis.length - 1]; - if (receivedCRC != calculatedCRC) { - Log.e(TAG, String.format("RadioResponse: CRC mismatch, calculated 0x%02x, received 0x%02x", calculatedCRC, receivedCRC)); - } - } catch (NumberFormatException e) { - decodedOK = false; - Log.e(TAG, "Failed to decode radio data: " + ByteUtil.shortHexString(encodedPayload)); - } - } - - public byte[] getPayload() { - return decodedPayload; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RileyLinkBLE.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RileyLinkBLE.java deleted file mode 100644 index 55562fc6a1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RileyLinkBLE/RileyLinkBLE.java +++ /dev/null @@ -1,428 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothManager; -import android.bluetooth.BluetoothProfile; -import android.content.Context; -import android.content.Intent; -import android.os.SystemClock; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.widget.Toast; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.BLECommOperation; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.BLECommOperationResult; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.CharacteristicReadOperation; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.CharacteristicWriteOperation; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.BLECommOperations.DescriptorWriteOperation; -import com.gxwtech.roundtrip2.util.HexDump; -import com.gxwtech.roundtrip2.util.ThreadUtil; - -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Semaphore; - -/** - * Created by geoff on 5/26/16. - */ -public class RileyLinkBLE { - private static final String TAG = "RileyLinkBLE"; - public boolean gattDebugEnabled = true; - - private BluetoothAdapter bluetoothAdapter; - private BluetoothGattCallback bluetoothGattCallback; - - private final Context context; - private BluetoothManager bluetoothManager; - - private BluetoothDevice rileyLinkDevice; - private BluetoothGatt bluetoothConnectionGatt = null; - - private BLECommOperation mCurrentOperation; - private Semaphore gattOperationSema = new Semaphore(1,true); - - private Runnable radioResponseCountNotified; - - private boolean mIsConnected = false; - - public RileyLinkBLE(final Context context) { - this.context = context; - this.bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); - this.bluetoothAdapter = bluetoothManager.getAdapter(); - - bluetoothGattCallback = new BluetoothGattCallback() { - - @Override - public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { - super.onCharacteristicChanged(gatt, characteristic); - if (gattDebugEnabled) { - Log.v(TAG, ThreadUtil.sig() + "onCharacteristicChanged " + GattAttributes.lookup(characteristic.getUuid()) + " " + HexDump.toHexString(characteristic.getValue())); - if (characteristic.getUuid().equals(UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT))) { - Log.d(TAG, "Response Count is " + HexDump.toHexString(characteristic.getValue())); - } - } - if (radioResponseCountNotified != null) { - radioResponseCountNotified.run(); - } - } - - @Override - public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status) { - super.onCharacteristicRead(gatt, characteristic, status); - - - final String statusMessage = getGattStatusMessage(status); - if (gattDebugEnabled) { - Log.v(TAG, ThreadUtil.sig() + "onCharacteristicRead (" + GattAttributes.lookup(characteristic.getUuid()) + ") " - + statusMessage + ":" + HexDump.toHexString(characteristic.getValue())); - } - mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(),characteristic.getValue()); - } - - @Override - public void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status) { - super.onCharacteristicWrite(gatt, characteristic, status); - - final String uuidString = GattAttributes.lookup(characteristic.getUuid()); - if (gattDebugEnabled) { - Log.v(TAG, ThreadUtil.sig() + "onCharacteristicWrite " + getGattStatusMessage(status) + " " + uuidString + " " + HexDump.toHexString(characteristic.getValue())); - } - mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(),characteristic.getValue()); - } - - @Override - public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) { - super.onConnectionStateChange(gatt, status, newState); - - // https://github.com/NordicSemiconductor/puck-central-android/blob/master/PuckCentral/app/src/main/java/no/nordicsemi/puckcentral/bluetooth/gatt/GattManager.java#L117 - if (status == 133) { - Log.e(TAG, "Got the status 133 bug, closing gatt"); - disconnect(); - return; - } - - if (gattDebugEnabled) { - final String stateMessage; - if (newState == BluetoothProfile.STATE_CONNECTED) { - stateMessage = "CONNECTED"; - } else if (newState == BluetoothProfile.STATE_CONNECTING) { - stateMessage = "CONNECTING"; - } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { - stateMessage = "DISCONNECTED"; - } else if (newState == BluetoothProfile.STATE_DISCONNECTING) { - stateMessage = "DISCONNECTING"; - } else { - stateMessage = "UNKNOWN (" + newState + ")"; - } - - Log.w(TAG, "onConnectionStateChange " + getGattStatusMessage(status) + " " + stateMessage); - } - - if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(RT2Const.serviceLocal.bluetooth_connected)); - } else { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(RT2Const.serviceLocal.bluetooth_disconnected)); - disconnect(); - Log.w(TAG, "Cannot establish Bluetooth connection."); - } - } - - - @Override - public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - super.onDescriptorWrite(gatt, descriptor, status); - if (gattDebugEnabled) { - Log.w(TAG, "onDescriptorWrite " - + GattAttributes.lookup(descriptor.getUuid()) + " " - + getGattStatusMessage(status) - + " written: " + HexDump.toHexString(descriptor.getValue())); - } - mCurrentOperation.gattOperationCompletionCallback(descriptor.getUuid(),descriptor.getValue()); - } - - @Override - public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - super.onDescriptorRead(gatt, descriptor, status); - mCurrentOperation.gattOperationCompletionCallback(descriptor.getUuid(),descriptor.getValue()); - if (gattDebugEnabled) { - Log.w(TAG, "onDescriptorRead " + getGattStatusMessage(status) + " status " + descriptor); - } - } - - @Override - public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { - super.onMtuChanged(gatt, mtu, status); - if (gattDebugEnabled) { - Log.w(TAG, "onMtuChanged " + mtu + " status " + status); - } - } - - @Override - public void onReadRemoteRssi(final BluetoothGatt gatt, int rssi, int status) { - super.onReadRemoteRssi(gatt, rssi, status); - if (gattDebugEnabled) { - Log.w(TAG, "onReadRemoteRssi " + getGattStatusMessage(status) + ": " + rssi); - } - } - - @Override - public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { - super.onReliableWriteCompleted(gatt, status); - if (gattDebugEnabled) { - Log.w(TAG, "onReliableWriteCompleted status " + status); - } - } - - @Override - public void onServicesDiscovered(final BluetoothGatt gatt, int status) { - super.onServicesDiscovered(gatt, status); - - if (status == BluetoothGatt.GATT_SUCCESS) { - final List services = gatt.getServices(); - // TODO: in here, we need to determine if this Bluetooth device is a RileyLink with appropriate software (subg_rfspy) and set mIsConnected if the GATT is ok. - for (BluetoothGattService service : services) { - final List characteristics = service.getCharacteristics(); - - final UUID uuidService = service.getUuid(); - final String uuidServiceString = uuidService.toString(); - if (gattDebugEnabled) { - String debugString = "Found service: " + GattAttributes.lookup(uuidServiceString, "Unknown device") + " (" + uuidServiceString + ")"; - - for (BluetoothGattCharacteristic character : characteristics) { - final String uuidCharacteristicString = character.getUuid().toString(); - debugString += " - " + GattAttributes.lookup(uuidCharacteristicString); - } - Log.w(TAG, debugString); - } - } - if (gattDebugEnabled) { - Log.w(TAG, "onServicesDiscovered " + getGattStatusMessage(status)); - } - mIsConnected = true; - Intent intent = new Intent(RT2Const.serviceLocal.BLE_services_discovered); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); - } else { - Log.e(TAG, "onServicesDiscovered " + getGattStatusMessage(status)); - } - } - }; - } - - public void registerRadioResponseCountNotification(Runnable notifier) { - radioResponseCountNotified = notifier; - } - - public boolean isConnected() { - return mIsConnected; - } - - public void discoverServices() { - if (bluetoothConnectionGatt.discoverServices()) { - Log.w(TAG, "Starting to discover GATT Services."); - - } else { - Log.e(TAG, "Cannot discover GATT Services."); - } - } - - public boolean enableNotifications() { - BLECommOperationResult result = setNotification_blocking( - UUID.fromString(GattAttributes.SERVICE_RADIO), - UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT)); - if (result.resultCode != BLECommOperationResult.RESULT_SUCCESS) { - Log.e(TAG, "Error setting response count notification"); - return false; - } - return true; - } - - public void findRileyLink(String RileyLinkAddress) { - Log.d(TAG,"Rileylink address: " + RileyLinkAddress); - // Must verify that this is a valid MAC, or crash. - - rileyLinkDevice = bluetoothAdapter.getRemoteDevice(RileyLinkAddress); - // if this succeeds, we get a connection state change callback? - connectGatt(); - } - - // This function must be run on UI thread. - public void connectGatt() { - bluetoothConnectionGatt = rileyLinkDevice.connectGatt(context, true, bluetoothGattCallback); - if (bluetoothConnectionGatt == null) { - Log.e(TAG,"Failed to connect to Bluetooth Low Energy device at "+bluetoothAdapter.getAddress()); - Toast.makeText(context, "No Rileylink at " + bluetoothAdapter.getAddress(), Toast.LENGTH_SHORT).show(); - } else { - if (gattDebugEnabled) { - Log.d(TAG, "Gatt Connected?"); - } - } - } - - public void disconnect() { - mIsConnected = false; - Log.w(TAG, "Closing GATT connection"); - // Close old conenction - if (bluetoothConnectionGatt != null) { - // Not sure if to disconnect or to close first.. - bluetoothConnectionGatt.disconnect(); - bluetoothConnectionGatt.close(); - bluetoothConnectionGatt = null; - } - } - - public BLECommOperationResult setNotification_blocking(UUID serviceUUID, UUID charaUUID) { - BLECommOperationResult rval = new BLECommOperationResult(); - if (bluetoothConnectionGatt != null) { - - try { - gattOperationSema.acquire(); - SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow - } catch (InterruptedException e) { - Log.e(TAG, "setNotification_blocking: interrupted waiting for gattOperationSema"); - return rval; - } - if (mCurrentOperation != null) { - rval.resultCode = BLECommOperationResult.RESULT_BUSY; - } else { - if (bluetoothConnectionGatt.getService(serviceUUID) == null) { - // Catch if the service is not supported by the BLE device - rval.resultCode = BLECommOperationResult.RESULT_NONE; - Log.e(TAG, "BT Device not supported"); - // TODO: 11/07/2016 UI update for user - } else { - BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID).getCharacteristic(charaUUID); - // Tell Android that we want the notifications - bluetoothConnectionGatt.setCharacteristicNotification(chara, true); - List list = chara.getDescriptors(); - if (gattDebugEnabled) { - for (int i = 0; i < list.size(); i++) { - Log.d(TAG, "Found descriptor: " + list.get(i).toString()); - } - } - BluetoothGattDescriptor descr = list.get(0); - // Tell the remote device to send the notifications - mCurrentOperation = new DescriptorWriteOperation(bluetoothConnectionGatt, descr, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - mCurrentOperation.execute(this); - if (mCurrentOperation.timedOut) { - rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; - } else if (mCurrentOperation.interrupted) { - rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; - } else { - rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; - } - } - mCurrentOperation = null; - gattOperationSema.release(); - } - } else { - Log.e(TAG,"setNotification_blocking: not configured!"); - rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; - } - return rval; - } - - // call from main - public BLECommOperationResult writeCharacteristic_blocking(UUID serviceUUID, UUID charaUUID, byte[] value) { - BLECommOperationResult rval = new BLECommOperationResult(); - if (bluetoothConnectionGatt != null) { - rval.value = value; - try { - gattOperationSema.acquire(); - SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow - } catch (InterruptedException e) { - Log.e(TAG,"writeCharacteristic_blocking: interrupted waiting for gattOperationSema"); - return rval; - } - if (mCurrentOperation != null) { - rval.resultCode = BLECommOperationResult.RESULT_BUSY; - } else { - if (bluetoothConnectionGatt.getService(serviceUUID) == null) { - // Catch if the service is not supported by the BLE device - // GGW: Tue Jul 12 01:14:01 UTC 2016: This can also happen if the - // app that created the bluetoothConnectionGatt has been destroyed/created, - // e.g. when the user switches from portrait to landscape. - rval.resultCode = BLECommOperationResult.RESULT_NONE; - Log.e(TAG, "BT Device not supported"); - // TODO: 11/07/2016 UI update for user - } else { - BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID).getCharacteristic(charaUUID); - mCurrentOperation = new CharacteristicWriteOperation(bluetoothConnectionGatt, chara, value); - mCurrentOperation.execute(this); - if (mCurrentOperation.timedOut) { - rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; - } else if (mCurrentOperation.interrupted) { - rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; - } else { - rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; - } - } - mCurrentOperation = null; - gattOperationSema.release(); - } - } else { - Log.e(TAG,"writeCharacteristic_blocking: not configured!"); - rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; - } - return rval; - } - - public BLECommOperationResult readCharacteristic_blocking(UUID serviceUUID, UUID charaUUID) { - BLECommOperationResult rval = new BLECommOperationResult(); - if (bluetoothConnectionGatt != null) { - try { - gattOperationSema.acquire(); - SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow - } catch (InterruptedException e) { - Log.e(TAG, "readCharacteristic_blocking: Interrupted waiting for gattOperationSema"); - return rval; - } - if (mCurrentOperation != null) { - rval.resultCode = BLECommOperationResult.RESULT_BUSY; - } else { - BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID).getCharacteristic(charaUUID); - mCurrentOperation = new CharacteristicReadOperation(bluetoothConnectionGatt, chara); - mCurrentOperation.execute(this); - if (mCurrentOperation.timedOut) { - rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; - } else if (mCurrentOperation.interrupted) { - rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; - } else { - rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; - rval.value = mCurrentOperation.getValue(); - } - } - mCurrentOperation = null; - gattOperationSema.release(); - } else { - Log.e(TAG,"readCharacteristic_blocking: not configured!"); - rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; - } - return rval; - } - - private String getGattStatusMessage(final int status) { - final String statusMessage; - if (status == BluetoothGatt.GATT_SUCCESS) { - statusMessage = "SUCCESS"; - } else if (status == BluetoothGatt.GATT_FAILURE) { - statusMessage = "FAILED"; - } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { - statusMessage = "NOT PERMITTED"; - } else if (status == 133) { - statusMessage = "Found the strange 133 bug"; - } else { - statusMessage = "UNKNOWN (" + status + ")"; - } - - return statusMessage; - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripService.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripService.java deleted file mode 100644 index 91ca9bc825..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripService.java +++ /dev/null @@ -1,638 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService; - -import android.app.Service; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Message; -import android.os.Parcel; -import android.os.PowerManager; -import android.preference.PreferenceManager; -import android.support.annotation.Nullable; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.widget.Toast; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.RileyLink.PumpManager; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RFSpy; -import com.gxwtech.roundtrip2.RoundtripService.RileyLinkBLE.RileyLinkBLE; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.DiscoverGattServicesTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.FetchPumpHistoryTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.InitializePumpManagerTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ReadBolusWizardCarbProfileTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ReadISFProfileTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ReadPumpClockTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.RetrieveHistoryPageTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTaskExecutor; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.UpdatePumpStatusTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.WakeAndTuneTask; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.ISFTable; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.Page; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.PumpHistoryManager; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; -import com.gxwtech.roundtrip2.util.ByteUtil; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; - -/** - * RoundtripService is intended to stay running when the gui-app is closed. - */ -public class RoundtripService extends Service { - private static final String TAG="RoundtripService"; - private static RoundtripService instance; - private static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock"; - private static volatile PowerManager.WakeLock lockStatic = null; - - private boolean needBluetoothPermission = true; - - private BroadcastReceiver mBroadcastReceiver; - private Context mContext; - private RoundtripServiceIPCConnection serviceConnection; - private BluetoothManager mBluetoothManager; - private BluetoothAdapter mBluetoothAdapter; - - - // saved settings - - public SharedPreferences sharedPref; - private String pumpIDString; - private byte[] pumpIDBytes; - private String mRileylinkAddress; - - // cache of most recently received set of pump history pages. Probably shouldn't be here. - ArrayList mHistoryPages; - PumpHistoryManager pumpHistoryManager; - - - // Our hardware/software connection - public RileyLinkBLE rileyLinkBLE; // android-bluetooth management - private RFSpy rfspy; // interface for 916MHz radio. - public PumpManager pumpManager; // interface to Minimed - private static ServiceTask currentTask = null; - - public RoundtripService() { - super(); - instance = this; - Log.d(TAG, "RoundtripService newly constructed"); - } - - public static RoundtripService getInstance() { - return instance; - } - - public void onCreate() { - super.onCreate(); - Log.d(TAG, "onCreate"); - mContext = getApplicationContext(); - serviceConnection = new RoundtripServiceIPCConnection(mContext); - - //sharedPref = mContext.getSharedPreferences(RT2Const.serviceLocal.sharedPreferencesKey, Context.MODE_PRIVATE); - sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - - // get most recently used pumpID - pumpIDString = sharedPref.getString(RT2Const.serviceLocal.pumpIDKey,"000000"); - pumpIDBytes = ByteUtil.fromHexString(pumpIDString); - if (pumpIDBytes == null) { - Log.e(TAG,"Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes)); - pumpIDBytes = new byte[] {0,0,0}; - pumpIDString = "000000"; - } - if (pumpIDBytes.length != 3) { - Log.e(TAG,"Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes)); - pumpIDBytes = new byte[] {0,0,0}; - pumpIDString = "000000"; - } - if (pumpIDString.equals("000000")) { - Log.e(TAG,"Using pump ID "+pumpIDString); - } else { - Log.i(TAG,"Using pump ID "+pumpIDString); - } - - // get most recently used RileyLink address - mRileylinkAddress = sharedPref.getString(RT2Const.serviceLocal.rileylinkAddressKey,""); - - pumpHistoryManager = new PumpHistoryManager(getApplicationContext()); - rileyLinkBLE = new RileyLinkBLE(this); - rfspy = new RFSpy(mContext,rileyLinkBLE); - rfspy.startReader(); - pumpManager = new PumpManager(mContext,rfspy,pumpIDBytes); - - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - /* here we can listen for local broadcasts, then send ourselves - * a specific intent to deal with them, if we wish - */ - if (intent == null) { - Log.e(TAG,"onReceive: received null intent"); - } else { - String action = intent.getAction(); - if (action == null) { - Log.e(TAG,"onReceive: null action"); - } else { - if (action.equals(RT2Const.serviceLocal.bluetooth_connected)) { - Log.w(TAG,"serviceLocal.bluetooth_connected"); - serviceConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink),null); - ServiceTaskExecutor.startTask(new DiscoverGattServicesTask()); - // If this is successful, - // We will get a broadcast of RT2Const.serviceLocal.BLE_services_discovered - } else if (action.equals(RT2Const.serviceLocal.BLE_services_discovered)) { - Log.w(TAG,"serviceLocal.BLE_services_discovered"); - serviceConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_WakingPump),null); - rileyLinkBLE.enableNotifications(); - rfspy.startReader(); // call startReader from outside? - ServiceTask task = new InitializePumpManagerTask(); - ServiceTaskExecutor.startTask(task); - Log.i(TAG, "Announcing RileyLink open For business"); - } else if (action.equals(RT2Const.serviceLocal.ipcBound)) { - // If we still need permission for bluetooth, ask now. - if (needBluetoothPermission) { - sendBLERequestForAccess(); - } - - } else if (RT2Const.IPC.MSG_BLE_accessGranted.equals(action)) { - //initializeLeAdapter(); - //BluetoothInit(); - } else if (RT2Const.IPC.MSG_BLE_accessDenied.equals(action)) { - stopSelf(); // This will stop the service. - } else if (action.equals(RT2Const.IPC.MSG_PUMP_tunePump)) { - doTunePump(); - } else if (action.equals(RT2Const.IPC.MSG_PUMP_quickTune)) { - doTunePump(); - } else if (action.equals(RT2Const.IPC.MSG_PUMP_fetchHistory)) { - mHistoryPages = pumpManager.getAllHistoryPages(); - final boolean savePages = true; - if (savePages) { - for (int i = 0; i < mHistoryPages.size(); i++) { - String filename = "PumpHistoryPage-" + i; - Log.w(TAG, "Saving history page to file " + filename); - FileOutputStream outputStream; - try { - outputStream = openFileOutput(filename, 0); - byte[] rawData= mHistoryPages.get(i).getRawData(); - if (rawData != null) { - outputStream.write(rawData); - } - outputStream.close(); - } catch (FileNotFoundException fnf) { - fnf.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - } - - Message msg = Message.obtain(null, RT2Const.IPC.MSG_IPC, 0, 0); - // Create a bundle with the data - Bundle bundle = new Bundle(); - bundle.putString(RT2Const.IPC.messageKey, RT2Const.IPC.MSG_PUMP_history); - ArrayList packedPages = new ArrayList<>(); - for (Page page : mHistoryPages) { - packedPages.add(page.pack()); - } - bundle.putParcelableArrayList(RT2Const.IPC.MSG_PUMP_history_key, packedPages); - - // save it to SQL. - pumpHistoryManager.clearDatabase(); - pumpHistoryManager.initFromPages(bundle); - // write html page to documents folder - pumpHistoryManager.writeHtmlPage(); - - // Set payload - msg.setData(bundle); - serviceConnection.sendMessage(msg,null/*broadcast*/); - Log.d(TAG, "sendMessage: sent Full history report"); - } else if (RT2Const.IPC.MSG_PUMP_fetchSavedHistory.equals(action)) { - Log.i(TAG,"Fetching saved history"); - FileInputStream inputStream; - ArrayList storedHistoryPages = new ArrayList<>(); - for (int i = 0; i < 16; i++) { - - String filename = "PumpHistoryPage-" + i; - try { - inputStream = openFileInput(filename); - byte[] buffer = new byte[1024]; - int numRead = inputStream.read(buffer, 0, 1024); - if (numRead == 1024) { - Page p = new Page(); - //p.parseFrom(buffer, PumpModel.MM522); - p.parseFrom(buffer, PumpModel.MM522); - storedHistoryPages.add(p); - } else { - Log.e(TAG, filename + " error: short file"); - } - } catch (FileNotFoundException fnf) { - Log.e(TAG, "Failed to open " + filename + " for reading."); - } catch (IOException e) { - Log.e(TAG, "Failed to read " + filename); - } catch (Exception e) { - e.printStackTrace(); - } - } - mHistoryPages = storedHistoryPages; - if (storedHistoryPages.isEmpty()) { - Log.e(TAG, "No stored history pages loaded"); - } else { - Message msg = Message.obtain(null, RT2Const.IPC.MSG_IPC, 0, 0); - // Create a bundle with the data - Bundle bundle = new Bundle(); - bundle.putString(RT2Const.IPC.messageKey, RT2Const.IPC.MSG_PUMP_history); - ArrayList packedPages = new ArrayList<>(); - for (Page page : mHistoryPages) { - packedPages.add(page.pack()); - } - bundle.putParcelableArrayList(RT2Const.IPC.MSG_PUMP_history_key, packedPages); - - // save it to SQL. - pumpHistoryManager.clearDatabase(); - pumpHistoryManager.initFromPages(bundle); - // write html page to documents folder - pumpHistoryManager.writeHtmlPage(); - - // Set payload - msg.setData(bundle); - serviceConnection.sendMessage(msg,null/*broadcast*/); - - } - } else if (RT2Const.IPC.MSG_ServiceCommand.equals(action)) { - Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); - - handleIncomingServiceTransport(new ServiceTransport(bundle)); - } else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) { - Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); - if (bundle != null) { - ServiceTransport transport = new ServiceTransport(bundle); - serviceConnection.sendTransport(transport, transport.getSenderHashcode()); - } else { - Log.e(TAG,"sessionCompleted: no bundle!"); - } - } else { - Log.e(TAG, "Unhandled broadcast: action=" + action); - } - } - } - } - }; - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(RT2Const.serviceLocal.bluetooth_connected); - intentFilter.addAction(RT2Const.serviceLocal.bluetooth_disconnected); - intentFilter.addAction(RT2Const.serviceLocal.BLE_services_discovered); - intentFilter.addAction(RT2Const.serviceLocal.ipcBound); - intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessGranted); - intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessDenied); - intentFilter.addAction(RT2Const.IPC.MSG_BLE_useThisDevice); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_tunePump); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_fetchHistory); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_useThisAddress); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_fetchSavedHistory); - intentFilter.addAction(RT2Const.IPC.MSG_ServiceCommand); - intentFilter.addAction(RT2Const.serviceLocal.INTENT_sessionCompleted); - - LocalBroadcastManager.getInstance(mContext).registerReceiver(mBroadcastReceiver, intentFilter); - - Log.d(TAG, "onCreate(): It's ALIVE!"); - } - - @Override - public boolean onUnbind(Intent intent) { - Log.w(TAG,"onUnbind"); - return super.onUnbind(intent); - } - - @Override - public void onRebind(Intent intent) { - Log.w(TAG,"onRebind"); - super.onRebind(intent); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - Log.w(TAG,"onConfigurationChanged"); - super.onConfigurationChanged(newConfig); - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return serviceConnection.doOnBind(intent); - } - - // Here is where the wake-lock begins: - // We've received a service startCommand, we grab the lock. - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.d(TAG, "onStartCommand"); - if (intent != null) { - PowerManager.WakeLock lock = getLock(this.getApplicationContext()); - - if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) { - lock.acquire(); - } - - // This will end up running onHandleIntent - super.onStartCommand(intent, flags, startId); - } else { - Log.e(TAG, "Received null intent?"); - } - BluetoothInit(); // this kicks off our process of device discovery. - return (START_REDELIVER_INTENT | START_STICKY); - } - - synchronized private static PowerManager.WakeLock getLock(Context context) { - if (lockStatic == null) { - PowerManager mgr = - (PowerManager) context.getSystemService(Context.POWER_SERVICE); - - lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCKNAME); - lockStatic.setReferenceCounted(true); - } - - return lockStatic; - } - - // FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc. - private void doTunePump() { - double lastGoodFrequency = sharedPref.getFloat(RT2Const.serviceLocal.prefsLastGoodPumpFrequency,(float)0.0); - double newFrequency; - if (lastGoodFrequency != 0.0) { - Log.i(TAG,String.format("Checking for pump near last saved frequency of %.2fMHz",lastGoodFrequency)); - // we have an old frequency, so let's start there. - newFrequency = pumpManager.quickTuneForPump(lastGoodFrequency); - if (newFrequency == 0.0) { - // quick scan failed to find pump. Try full scan - Log.w(TAG,String.format("Failed to find pump near last saved frequency, doing full scan")); - newFrequency = pumpManager.tuneForPump(); - } - } else { - Log.w(TAG,"No saved frequency for pump, doing full scan."); - // we don't have a saved frequency, so do the full scan. - newFrequency = pumpManager.tuneForPump(); - - } - if ((newFrequency!=0.0) && (newFrequency != lastGoodFrequency)) { - Log.i(TAG,String.format("Saving new pump frequency of %.2fMHz",newFrequency)); - SharedPreferences.Editor ed = sharedPref.edit(); - ed.putFloat(RT2Const.serviceLocal.prefsLastGoodPumpFrequency, (float)newFrequency); - ed.apply(); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - Log.e(TAG, "I die! I die!"); - } - - /* private functions */ - - void BluetoothInit() { - if (mBluetoothManager == null) { - mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); - if (mBluetoothManager == null) { - Log.e(TAG, "Unable to initialize BluetoothManager."); - } - } - // Ensures Bluetooth is available on the device and it is enabled. If not, - // displays a dialog requesting user permission to enable Bluetooth. - if ((mBluetoothAdapter==null) || (!mBluetoothAdapter.isEnabled())) { - sendBLERequestForAccess(); - } else { - needBluetoothPermission = false; - initializeLeAdapter(); - } - } - - public boolean initializeLeAdapter() { - Log.d(TAG,"initializeLeAdapter: attempting to get an adapter"); - mBluetoothAdapter = mBluetoothManager.getAdapter(); - if (mBluetoothAdapter == null) { - Log.e(TAG, "Unable to obtain a BluetoothAdapter."); - return false; - } else if (!mBluetoothAdapter.isEnabled()) { - // NOTE: This does not work! - Log.e(TAG, "Bluetooth is not enabled."); - } - return true; - } - - private void setPumpIDString(String idString) { - if (idString.length() != 6) { - Log.e(TAG,"setPumpIDString: invalid pump id string: " + idString); - } - pumpIDString = idString; - pumpIDBytes = ByteUtil.fromHexString(pumpIDString); - SharedPreferences prefs = mContext.getSharedPreferences(RT2Const.serviceLocal.sharedPreferencesKey, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(RT2Const.serviceLocal.pumpIDKey,pumpIDString); - editor.apply(); - Log.i(TAG,"setPumpIDString: saved pumpID "+pumpIDString); - } - - private void sendBLERequestForAccess() { - //serviceConnection.sendMessage(RT2Const.IPC.MSG_BLE_requestAccess); - } - - private void reportPumpFound() { - //serviceConnection.sendMessage(RT2Const.IPC.MSG_PUMP_pumpFound); - } - - public void setCurrentTask(ServiceTask task) { - if (currentTask == null) { - currentTask = task; - } else { - Log.e(TAG,"setCurrentTask: Cannot replace current task"); - } - } - - public void finishCurrentTask(ServiceTask task) { - if (task != currentTask) { - Log.e(TAG,"finishCurrentTask: task does not match"); - } - // hack to force deep copy of transport contents - ServiceTransport transport = task.getServiceTransport().clone(); - - if (transport.hasServiceResult()) { - sendServiceTransportResponse(transport,transport.getServiceResult()); - } - currentTask = null; - } - - private void handleIncomingServiceTransport(ServiceTransport serviceTransport) { - if (serviceTransport.getServiceCommand().isPumpCommand()) { - switch (serviceTransport.getOriginalCommandName()) { - case "ReadPumpClock": - ServiceTaskExecutor.startTask(new ReadPumpClockTask(serviceTransport)); - break; - case "FetchPumpHistory": - ServiceTaskExecutor.startTask(new FetchPumpHistoryTask(serviceTransport)); - break; - case "RetrieveHistoryPage": - ServiceTask task = new RetrieveHistoryPageTask(serviceTransport); - ServiceTaskExecutor.startTask(task); - break; - case "ReadISFProfile": - ServiceTaskExecutor.startTask(new ReadISFProfileTask(serviceTransport)); - /* - ISFTable table = pumpManager.getPumpISFProfile(); - ServiceResult result = new ServiceResult(); - if (table.isValid()) { - // convert from ISFTable to ISFProfile - Bundle map = result.getMap(); - map.putIntArray("times", table.getTimes()); - map.putFloatArray("rates", table.getRates()); - map.putString("ValidDate", TimeFormat.standardFormatter().print(table.getValidDate())); - result.setMap(map); - result.setResultOK(); - } - sendServiceTransportResponse(serviceTransport,result); - */ - break; - case "ReadBolusWizardCarbProfile": - ServiceTaskExecutor.startTask(new ReadBolusWizardCarbProfileTask()); - break; - case "UpdatePumpStatus": - ServiceTaskExecutor.startTask(new UpdatePumpStatusTask()); - break; - case "WakeAndTune": - ServiceTaskExecutor.startTask(new WakeAndTuneTask()); - default: - Log.e(TAG,"Failed to handle pump command: " + serviceTransport.getOriginalCommandName()); - break; - } - } else { - switch (serviceTransport.getOriginalCommandName()) { - case "SetPumpID": - // This one is a command to RoundtripService, not to the PumpManager - String pumpID = serviceTransport.getServiceCommand().getMap().getString("pumpID", ""); - ServiceResult result = new ServiceResult(); - if ((pumpID != null) && (pumpID.length() == 6)) { - setPumpIDString(pumpID); - result.setResultOK(); - } else { - Log.e(TAG, "handleIncomingServiceTransport: SetPumpID bundle missing 'pumpID' value"); - result.setResultError(-1, "Invalid parameter (missing pumpID)"); - } - sendServiceTransportResponse(serviceTransport, result); - break; - case "UseThisRileylink": - // If we are not connected, connect using the given address. - // If we are connected and the addresses differ, disconnect, connect to new. - // If we are connected and the addresses are the same, ignore. - String deviceAddress = serviceTransport.getServiceCommand().getMap().getString("rlAddress", ""); - if ("".equals(deviceAddress)) { - Log.e(TAG, "handleIPCMessage: null RL address passed"); - } else { - reconfigureRileylink(deviceAddress); - } - break; - default: - Log.e(TAG, "handleIncomingServiceTransport: Failed to handle service command '" + serviceTransport.getOriginalCommandName() + "'"); - break; - } - } - } - - // returns true if our Rileylink configuration changed - public boolean reconfigureRileylink(String deviceAddress) { - if (rileyLinkBLE.isConnected()) { - if (deviceAddress.equals(mRileylinkAddress)) { - Log.i(TAG, "No change to RL address. Not reconnecting."); - return false; - } else { - Log.w(TAG, "Disconnecting from old RL (" + mRileylinkAddress + "), reconnecting to new: " + deviceAddress); - rileyLinkBLE.disconnect(); - // prolly need to shut down listening thread too? - SharedPreferences.Editor ed = sharedPref.edit(); - ed.putString("rlAddress", deviceAddress); - ed.apply(); - mRileylinkAddress = deviceAddress; - rileyLinkBLE.findRileyLink(mRileylinkAddress); - return true; - } - } else { - Toast.makeText(mContext, "Using RL " + deviceAddress, Toast.LENGTH_SHORT).show(); - Log.d(TAG, "handleIPCMessage: Using RL " + deviceAddress); - if (mBluetoothAdapter == null) { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - } - if (mBluetoothAdapter != null) { - if (mBluetoothAdapter.isEnabled()) { - // FIXME: this may be a long running function: - rileyLinkBLE.findRileyLink(deviceAddress); - // If successful, we will get a broadcast from RileyLinkBLE: RT2Const.serviceLocal.bluetooth_connected - return true; - } else { - Log.e(TAG, "Bluetooth is not enabled."); - return false; - } - } else { - Log.e(TAG, "Failed to get adapter"); - return false; - } - } - } - - public void announceProgress(int progressPercent) { - if (currentTask != null) { - ServiceNotification note = new ServiceNotification(RT2Const.IPC.MSG_note_TaskProgress); - note.getMap().putInt("progress",progressPercent); - note.getMap().putString("task",currentTask.getServiceTransport().getOriginalCommandName()); - Integer senderHashcode = currentTask.getServiceTransport().getSenderHashcode(); - serviceConnection.sendNotification(note, senderHashcode); - } else { - Log.e(TAG,"announceProgress: No current task"); - } - } - - public void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) { - // get the key (hashcode) of the client who requested this - Integer clientHashcode = transport.getSenderHashcode(); - // make a new bundle to send as the message data - transport.setServiceResult(serviceResult); - transport.setTransportType(RT2Const.IPC.MSG_ServiceResult); - serviceConnection.sendTransport(transport,clientHashcode); - } - - public boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { - return serviceConnection.sendNotification(notification, clientHashcode); - } - - public void saveHistoryPage(int pagenumber, Page page) { - if ((page == null) || (page.getRawData() == null)) { - return; - } - String filename = "history-" + pagenumber; - FileOutputStream os; - try { - os = openFileOutput(filename, Context.MODE_PRIVATE); - os.write(page.getRawData()); - os.close(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripServiceIPCConnection.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripServiceIPCConnection.java deleted file mode 100644 index 73d2ac508e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/RoundtripServiceIPCConnection.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -import java.util.HashMap; - -/** - * Created by geoff on 6/11/16. - */ -public class RoundtripServiceIPCConnection { - private static final String TAG = "RTServiceIPC"; - private Context context; - //private ArrayList mClients = new ArrayList<>(); - private HashMap mClients = new HashMap<>(); - - private final Messenger mMessenger = new Messenger(new IncomingHandler()); - - public RoundtripServiceIPCConnection(Context context) { - this.context = context; - } - - class IncomingHandler extends Handler { - @Override - public void handleMessage(Message msg) { - Log.d(TAG, "handleMessage: Received message " + msg); - Bundle bundle = msg.getData(); - switch(msg.what) { - // This just helps sub-divide the message processing - case RT2Const.IPC.MSG_registerClient: - // send a reply, to let them know we're listening. - Message myReply = Message.obtain(null, RT2Const.IPC.MSG_clientRegistered,0,0); - try { - msg.replyTo.send(myReply); - mClients.put(mClients.hashCode(),msg.replyTo); - Log.v(TAG,"handleMessage: Registered client"); - } catch (RemoteException e) { - // I guess they aren't registered after all... - Log.e(TAG,"handleMessage: failed to send acknowledgement of registration"); - } - - break; - case RT2Const.IPC.MSG_unregisterClient: - Log.v(TAG,"Unregistered client"); - mClients.remove(msg.replyTo.hashCode()); - break; - case RT2Const.IPC.MSG_IPC: - // As the current thread is likely a GUI thread from some app, - // rebroadcast the message as a local item. - // Convert from Message to Intent - if (msg.replyTo != null) { - try { - ServiceTransport transport = new ServiceTransport(bundle); - Log.d(TAG, "Service received IPC message" + transport.describeContentsShort()); - transport.setSenderHashcode(msg.replyTo.hashCode()); - Intent intent = new Intent(transport.getTransportType()); - intent.putExtra(RT2Const.IPC.bundleKey, transport.getMap()); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); - } catch (IllegalArgumentException e) { - // This can happen on screen tilts... what else is wrong? - Log.e(TAG,"Malformed service bundle: " + bundle.toString()); - } - } - break; - /* - case RT2Const.MSG_ping: - String hello = (String)bundle.get("key_hello"); - Toast.makeText(mContext,hello, Toast.LENGTH_SHORT).show(); - break; - */ - default: - Log.e(TAG,"handleMessage: unknown 'what' in message: "+msg.what); - super.handleMessage(msg); - } - } - } - - public IBinder doOnBind(Intent intent) { - Log.d(TAG, "onBind"); - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(RT2Const.serviceLocal.ipcBound)); - return mMessenger.getBinder(); - } - - public boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { - ServiceTransport transport = new ServiceTransport(); - transport.setServiceNotification(notification); - transport.setTransportType(RT2Const.IPC.MSG_ServiceNotification); - return sendTransport(transport,clientHashcode); - } - - // if clientHashcode is null, broadcast to all clients - public boolean sendMessage(Message msg, Integer clientHashcode) { - Messenger clientMessenger = null; - - if (mClients.isEmpty()) { - if (msg.what == RT2Const.IPC.MSG_IPC) { - Log.e(TAG, "sendMessage: no clients, cannot send: " + msg.getData().getString(RT2Const.IPC.messageKey, "(unknown)")); - } else { - Log.e(TAG, "sendMessage: no clients, cannot send: what=" + msg.what); - } - } else { - if (clientHashcode != null) { - clientMessenger = mClients.get(clientHashcode); - } - try { - if (clientMessenger != null) { - // sending to just one client - clientMessenger.send(msg); - } else { - // send to all clients - for (Integer clientHash : mClients.keySet()) { - Message m2 = Message.obtain(msg); - mClients.get(clientHash).send(m2); - } - } - } catch (RemoteException e) { - e.printStackTrace(); - } - /* - catch (IllegalStateException e) { - // This happens every time we are in a bluetooth operation and the screen is turned. - Log.e(TAG,"sendMessage: IllegalStateException"); - } - */ - } - return true; - } - - /* - public void sendMessage(String messageType) { - Message msg = Message.obtain(null, RT2Const.IPC.MSG_IPC,0,0); - // Create a bundle with the data - Bundle bundle = new Bundle(); - bundle.putString(RT2Const.IPC.messageKey, messageType); - - // Set payload - msg.setData(bundle); - sendMessage(msg, null); - Log.d(TAG,"sendMessage: sent "+messageType); - } - */ - - public boolean sendTransport(ServiceTransport transport, Integer clientHashcode) { - Message msg = Message.obtain(null, RT2Const.IPC.MSG_IPC,0,0); - // Set payload - msg.setData(transport.getMap()); - Log.d(TAG,"Service sending message to " + String.valueOf(clientHashcode) + ": " + transport.describeContentsShort()); - if ((clientHashcode != null) && (clientHashcode == 0)) { - return sendMessage(msg, null); - } - return sendMessage(msg, clientHashcode); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/DiscoverGattServicesTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/DiscoverGattServicesTask.java deleted file mode 100644 index 8276279fb0..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/DiscoverGattServicesTask.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; - -/** - * Created by geoff on 7/9/16. - */ -public class DiscoverGattServicesTask extends ServiceTask { - public DiscoverGattServicesTask() {} - - @Override - public void run() { - RoundtripService.getInstance().rileyLinkBLE.discoverServices(); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/FetchPumpHistoryTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/FetchPumpHistoryTask.java deleted file mode 100644 index 8d9f529462..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/FetchPumpHistoryTask.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.Page; -import com.gxwtech.roundtrip2.ServiceData.FetchPumpHistoryResult; -import com.gxwtech.roundtrip2.ServiceData.RetrieveHistoryPageResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -import java.net.MalformedURLException; -import java.util.ArrayList; - -/** - * Created by geoff on 7/16/16. - */ -public class FetchPumpHistoryTask extends PumpTask { - public FetchPumpHistoryTask() { } - public FetchPumpHistoryTask(ServiceTransport transport) { - super(transport); - } - private FetchPumpHistoryResult result = new FetchPumpHistoryResult(); - - @Override - public void run() { - ArrayList ra = new ArrayList<>(); - for (int i=0; i<16; i++) { - Page page = RoundtripService.getInstance().pumpManager.getPumpHistoryPage(i); - if (page != null) { - ra.add(page); - RoundtripService.getInstance().saveHistoryPage(i,page); - } - } - - result.setMap(getServiceTransport().getServiceResult().getMap()); - result.setResultOK(); - result.setPageArray(ra); - getServiceTransport().setServiceResult(result); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/InitializePumpManagerTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/InitializePumpManagerTask.java deleted file mode 100644 index 7b5200259e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/InitializePumpManagerTask.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.RileyLink.PumpManager; -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/9/16. - * - * This class is intended to be run by the Service, for the Service. - * Not intended for clients to run. - */ -public class InitializePumpManagerTask extends ServiceTask { - private static final String TAG = "InitPumpManagerTask"; - public InitializePumpManagerTask() { super(); } - public InitializePumpManagerTask(ServiceTransport transport) { super(transport); } - - @Override - public void run() { - SharedPreferences sharedPref = RoundtripService.getInstance().getApplicationContext().getSharedPreferences(RT2Const.serviceLocal.sharedPreferencesKey, Context.MODE_PRIVATE); - double lastGoodFrequency = sharedPref.getFloat(RT2Const.serviceLocal.prefsLastGoodPumpFrequency,(float)0.0); - if (lastGoodFrequency != 0) { - Log.i(TAG,String.format("Setting radio frequency to %.2fMHz",lastGoodFrequency)); - RoundtripService.getInstance().pumpManager.setRadioFrequencyForPump(lastGoodFrequency); - } - - PumpModel reportedPumpModel = RoundtripService.getInstance().pumpManager.getPumpModel(); - if (!reportedPumpModel.equals(PumpModel.UNSET)) { - RoundtripService.getInstance().sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpFound),null); - } else { - RoundtripService.getInstance().sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpLost),null); - } - RoundtripService.getInstance().sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_Idle),null); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/PumpTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/PumpTask.java deleted file mode 100644 index 5351ad42d7..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/PumpTask.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/10/16. - */ -public class PumpTask extends ServiceTask { - public PumpTask() {super();} - public PumpTask(ServiceTransport transport) { - super(transport); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadBolusWizardCarbProfileTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadBolusWizardCarbProfileTask.java deleted file mode 100644 index f887cbfc19..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadBolusWizardCarbProfileTask.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpMessage; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/10/16. - */ -public class ReadBolusWizardCarbProfileTask extends PumpTask { - public ReadBolusWizardCarbProfileTask() { super(); } - public ReadBolusWizardCarbProfileTask(ServiceTransport transport) { - super(transport); - } - - @Override - public void run() { - PumpMessage msg = RoundtripService.getInstance().pumpManager.getBolusWizardCarbProfile(); - ServiceResult result = getServiceTransport().getServiceResult(); - // interpret msg here. - getServiceTransport().setServiceResult(result); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadISFProfileTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadISFProfileTask.java deleted file mode 100644 index 554e894674..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadISFProfileTask.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.ISFTable; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/10/16. - */ -public class ReadISFProfileTask extends PumpTask { - public ReadISFProfileTask() {} - public ReadISFProfileTask(ServiceTransport transport) { super(transport); } - @Override - public void preOp() { - } - - @Override - public void run() { - ISFTable table = RoundtripService.getInstance().pumpManager.getPumpISFProfile(); - ServiceResult result = getServiceTransport().getServiceResult(); - if (table.isValid()) { - // convert from ISFTable to ISFProfile - Bundle map = result.getMap(); - map.putIntArray("times", table.getTimes()); - map.putFloatArray("rates", table.getRates()); - map.putString("ValidDate", TimeFormat.standardFormatter().print(table.getValidDate())); - result.setMap(map); - result.setResultOK(); - getServiceTransport().setServiceResult(result); - } - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadPumpClockTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadPumpClockTask.java deleted file mode 100644 index 9a45e41509..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ReadPumpClockTask.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.ServiceData.ReadPumpClockResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/9/16. - */ -public class ReadPumpClockTask extends PumpTask { - private static final String TAG = "ReadPumpClockTask"; - public ReadPumpClockTask() { } - public ReadPumpClockTask(ServiceTransport transport) { - super(transport); - } - - @Override - public void run() { - ReadPumpClockResult pumpResponse = RoundtripService.getInstance().pumpManager.getPumpRTC(); - if (pumpResponse != null) { - Log.i(TAG, "ReadPumpClock: " + pumpResponse.getTimeString()); - } else { - Log.e(TAG, "handleServiceCommand(" + mTransport.getOriginalCommandName() + ") pumpResponse is null"); - } - getServiceTransport().setServiceResult(pumpResponse); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/RetrieveHistoryPageTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/RetrieveHistoryPageTask.java deleted file mode 100644 index 87c8efa485..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/RetrieveHistoryPageTask.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.Page; -import com.gxwtech.roundtrip2.ServiceData.RetrieveHistoryPageResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/9/16. - */ -public class RetrieveHistoryPageTask extends PumpTask { - public RetrieveHistoryPageTask() { } - public RetrieveHistoryPageTask(ServiceTransport transport) { - super(transport); - } - private Page page; - private RetrieveHistoryPageResult result; - private int pageNumber; - - @Override - public void preOp() { - // This is to avoid allocating any memory from async thread, though I'm not sure it's necessary. - RetrieveHistoryPageResult result = new RetrieveHistoryPageResult(); - getServiceTransport().setServiceResult(result); - } - - @Override - public void run() { - pageNumber = mTransport.getServiceCommand().getMap().getInt("pageNumber"); - page = RoundtripService.getInstance().pumpManager.getPumpHistoryPage(pageNumber); - result = (RetrieveHistoryPageResult) getServiceTransport().getServiceResult(); - result.setResultOK(); - result.setPageNumber(pageNumber); - result.setPageBundle(page.pack()); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTask.java deleted file mode 100644 index 2b7c0ea546..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTask.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.os.AsyncTask; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/9/16. - */ -public class ServiceTask implements Runnable { - private static final String TAG = "ServiceTask(base)"; - protected ServiceTransport mTransport; - public boolean completed = false; - public ServiceTask() { - init(new ServiceTransport()); - } - public ServiceTask(ServiceTransport transport) { - init(transport); - } - - public void init(ServiceTransport transport) { - mTransport = transport; - } - - @Override - public void run() { - } - - public void preOp() { - // This function is called by UI thread before running asynch thread. - } - - public void postOp() { - // This function is called by UI thread after running asynch thread. - } - - public ServiceTransport getServiceTransport() { - return mTransport; - } - - /* - protected void sendResponse(ServiceResult result) { - RoundtripService.getInstance().sendServiceTransportResponse(mTransport,result); - } - */ -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTaskExecutor.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTaskExecutor.java deleted file mode 100644 index 2817ba1517..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/ServiceTaskExecutor.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Created by geoff on 7/9/16. - */ -public class ServiceTaskExecutor extends ThreadPoolExecutor { - private static final String TAG = "ServiceTaskExecutor"; - private static ServiceTaskExecutor instance; - private static LinkedBlockingQueue taskQueue = new LinkedBlockingQueue<>(); - static { - instance = new ServiceTaskExecutor(); - } - private ServiceTaskExecutor() { - super(1,1,10000, TimeUnit.MILLISECONDS,taskQueue); - } - public static ServiceTask startTask(ServiceTask task) { - instance.execute(task); // task will be run on async thread from pool. - return task; - } - protected void beforeExecute(Thread t, Runnable r) { - // This is run on either caller UI thread or Service UI thread. - ServiceTask task = (ServiceTask) r; - Log.v(TAG,"About to run task " + task.getClass().getSimpleName()); - RoundtripService.getInstance().setCurrentTask(task); - task.preOp(); - } - protected void afterExecute(Runnable r, Throwable t) { - // This is run on either caller UI thread or Service UI thread. - ServiceTask task = (ServiceTask) r; - task.postOp(); - Log.v(TAG,"Finishing task " + task.getClass().getSimpleName()); - RoundtripService.getInstance().finishCurrentTask(task); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/UpdatePumpStatusTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/UpdatePumpStatusTask.java deleted file mode 100644 index e4f699722e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/UpdatePumpStatusTask.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLink.PumpManagerStatus; -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.ServiceData.PumpStatusResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/16/16. - */ -public class UpdatePumpStatusTask extends PumpTask { - private static final String TAG = "UpdatePumpStatusTask"; - public UpdatePumpStatusTask() { } - public UpdatePumpStatusTask(ServiceTransport transport) { - super(transport); - } - - @Override - public void run() { - // force pump to update everything it can - RoundtripService.getInstance().pumpManager.updatePumpManagerStatus(); - // get the newly cached status - PumpManagerStatus status = RoundtripService.getInstance().pumpManager.getPumpManagerStatus(); - // fill a PumpStatusResult message with the goods - PumpStatusResult result = new PumpStatusResult(); - /* - double remainBattery; - double remainUnits; - double currentBasal; - double lastBolusAmount; - String lastBolusTime; - int tempBasalInProgress; - double tempBasalRatio; - double tempBasalRemainMin; - String tempBasalStart; - String time; - String timeLastSync; - */ - - result.setRemainBattery(status.remainBattery); - result.setRemainUnits(status.remainUnits); - result.setCurrentBasal(status.currentBasal); - result.setLastBolusAmount(status.last_bolus_amount); - result.setLastBolusTime(status.last_bolus_time.toString()); - result.setTempBasalInProgress(status.tempBasalInProgress); - result.setTempBasalRatio(status.tempBasalRatio); - result.setTempBasalRemainMin(status.tempBasalRemainMin); - result.setTempBasalStart(status.tempBasalStart.toString()); - result.setTime(status.time.toString()); - result.setTimeLastSync(""); - getServiceTransport().setServiceResult(result); - - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/WakeAndTuneTask.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/WakeAndTuneTask.java deleted file mode 100644 index 6900489682..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/Tasks/WakeAndTuneTask.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.Tasks; - -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -/** - * Created by geoff on 7/16/16. - */ -public class WakeAndTuneTask extends PumpTask { - private static final String TAG = "WakeAndTuneTask"; - public WakeAndTuneTask() { } - public WakeAndTuneTask(ServiceTransport transport) { - super(transport); - } - - @Override - public void run() { - RoundtripService.getInstance().pumpManager.wakeup(6); - RoundtripService.getInstance().pumpManager.tuneForPump(); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/ButtonPressCarelinkMessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/ButtonPressCarelinkMessageBody.java deleted file mode 100644 index 5564813616..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/ButtonPressCarelinkMessageBody.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 6/2/16. - */ -public class ButtonPressCarelinkMessageBody extends CarelinkLongMessageBody { - public static final byte BUTTON_EASY = 0x00; - public static final byte BUTTON_ESC = 0x01; - public static final byte BUTTON_ACT = 0x02; - public static final byte BUTTON_UP = 0x03; - public static final byte BUTTON_DOWN = 0x04; - - public ButtonPressCarelinkMessageBody(int which) { - init(which); - } - - public void init(int buttonType) { - int numArgs = 1; - super.init(new byte[] {(byte)numArgs,(byte)buttonType}); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/CarelinkLongMessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/CarelinkLongMessageBody.java deleted file mode 100644 index bc55acd877..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/CarelinkLongMessageBody.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 6/2/16. - */ -public class CarelinkLongMessageBody extends MessageBody { - public static final int LONG_MESSAGE_BODY_LENGTH = 65; - protected byte[] data; - - public CarelinkLongMessageBody() { - init(new byte[0]); - } - - public CarelinkLongMessageBody(byte[] payload) { - init(payload); - } - - public void init(byte[] rxData) { - data = new byte[LONG_MESSAGE_BODY_LENGTH]; - if (rxData != null) { - int size = rxData.length < LONG_MESSAGE_BODY_LENGTH ? rxData.length : LONG_MESSAGE_BODY_LENGTH; - for (int i=0; i 0) { - return data[0] & 0x7f; - } - return 255; - } - - public boolean wasLastFrame() { - return (data[0] & 0x80) != 0; - } - - public byte[] getFrameData() { - return ByteUtil.substring(data,1,data.length-1); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/GetPumpModelCarelinkMessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/GetPumpModelCarelinkMessageBody.java deleted file mode 100644 index 271df7650f..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/GetPumpModelCarelinkMessageBody.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 5/29/16. - */ -public class GetPumpModelCarelinkMessageBody extends MessageBody { - - public int getLength() { - return 1; - } - - public void init(byte[] rxData) { - - } - - public byte[] getRxData() { - return new byte[] { 0 }; - } - - public void setRxData(byte[] rxData) { - - } - - public byte[] getTxData() { - return new byte[] { 0 }; - } - - public void setTxData(byte[] txData) { - - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageBody.java deleted file mode 100644 index 61488be9fe..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageBody.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 5/29/16. - */ -public class MessageBody { - public int getLength() { return 0; } - public void init(byte[] rxData) { } - public byte[] getTxData() { return new byte[] {}; } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageType.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageType.java deleted file mode 100644 index 9c0c4e342e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/MessageType.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 5/29/16. - */ -public class MessageType { - public static final byte Invalid = (byte)0x00; - public static final byte Alert = (byte)0x01; - public static final byte AlertCleared = (byte)0x02; - public static final byte DeviceTest = (byte)0x03; - public static final byte PumpStatus = (byte)0x04; - public static final byte PumpAck = (byte)0x06; - public static final byte PumpBackfill = (byte)0x08; - public static final byte FindDevice = (byte)0x09; - public static final byte DeviceLink = (byte)0x0a; - public static final byte ChangeTime = (byte)0x40; - public static final byte Bolus = (byte)0x42; - public static final byte ChangeTempBasal = (byte)0x4c; - public static final byte ButtonPress = (byte)0x5b; - public static final byte PowerOn = (byte)0x5d; - public static final byte ReadTime = (byte)0x70; - public static final byte GetBattery = (byte)0x72; - public static final byte GetHistoryPage = (byte)0x80; - public static final byte GetISFProfile = (byte)0x8b; - public static final byte GetPumpModel = (byte)0x8d; - public static final byte ReadTempBasal = (byte)0x98; - public static final byte ReadSettings = (byte)0xc0; - - // The above codes include codes that are not 522/722 specific. - - // The codes below here are Medtronic pump specific. - // from Roundtrip.Carelink: - public static final byte CMD_M_PACKET_LENGTH = ((byte)7); // 0x07 - public static final byte CMD_M_BEGIN_PARAMETER_SETTING = ((byte)38); // 0x26 - public static final byte CMD_M_END_PARAMETER_SETTING = ((byte)39); // 0x27 - public static final byte CMD_M_SET_A_PROFILE = ((byte)48); // 0x30 - public static final byte CMD_M_SET_B_PROFILE = ((byte)49); // 0x31 - public static final byte CMD_M_SET_LOGIC_LINK_ID = ((byte)50); // 0x32 - public static final byte CMD_M_SET_LOGIC_LINK_ENABLE = ((byte)51); // 0x33 - public static final byte CMD_M_SET_RTC = ((byte)64); // 0x40 - public static final byte CMD_M_SET_MAX_BOLUS = ((byte)65); // 0x41 - public static final byte CMD_M_BOLUS = ((byte)66); // 0x42 - public static final byte CMD_M_SET_VAR_BOLUS_ENABLE = ((byte)69); // 0x45 - public static final byte CMD_M_SET_CURRENT_PATTERN = ((byte)74); // 0x4a - public static final byte CMD_M_TEMP_BASAL_RATE = ((byte)76); // 0x4c - public static final byte CMD_M_SUSPEND_RESUME = ((byte)77); // 0x4d - public static final byte CMD_M_SET_AUTO_OFF = ((byte)78); // 0x4e - public static final byte CMD_M_SET_EASY_BOLUS_ENABLE = ((byte)79); // 0x4f - public static final byte CMD_M_SET_RF_REMOTE_ID = ((byte)81); // 0x51 - public static final byte CMD_M_SET_BLOCK_ENABLE = ((byte)82); // 0x52 - public static final byte CMD_M_SET_ALERT_TYPE = ((byte)84); // 0x54 - public static final byte CMD_M_SET_PATTERNS_ENABLE = ((byte)85); // 0x55 - public static final byte CMD_M_SET_RF_ENABLE = ((byte)87); // 0x57 - public static final byte CMD_M_SET_INSULIN_ACTION_TYPE = ((byte)88); // 0x58 - public static final byte CMD_M_KEYPAD_PUSH = ((byte)91); // 0x5b - public static final byte CMD_M_SET_TIME_FORMAT = ((byte)92); // 0x5c - public static final byte CMD_M_POWER_CTRL = ((byte)93); // 0x5d - public static final byte CMD_M_SET_BOLUS_WIZARD_SETUP = ((byte)94); // 0x5e - public static final byte CMD_M_SET_BG_ALARM_ENABLE = ((byte)103);// 0x67 - public static final byte CMD_M_SET_TEMP_BASAL_TYPE = ((byte)104);// 0x68 - public static final byte CMD_M_SET_RESERVOIR_WARNING = ((byte)106);// 0x6a - public static final byte CMD_M_SET_BG_ALARM_CLOCKS = ((byte)107);// 0x6b - public static final byte CMD_M_SET_BG_REMINDER_ENABLE = ((byte)108);// 0x6c - public static final byte CMD_M_SET_MAX_BASAL = ((byte)110);// 0x6e - public static final byte CMD_M_SET_STD_PROFILE = ((byte)111);// 0x6f - public static final byte CMD_M_READ_RTC = ((byte)112);// 0x70 - public static final byte CMD_M_READ_PUMP_ID = ((byte)113);// 0x71 - public static final byte CMD_M_READ_INSULIN_REMAINING = ((byte)115);// 0x73 - public static final byte CMD_M_READ_FIRMWARE_VER = ((byte)116);// 0x74 - public static final byte CMD_M_READ_ERROR_STATUS = ((byte)117);// 0x75 - public static final byte CMD_M_READ_REMOTE_CTRL_IDS = ((byte)118);// 0x76 - public static final byte CMD_M_READ_HISTORY = ((byte)128);// 0x80 - public static final byte CMD_M_READ_PUMP_STATE = ((byte)131);// 0x83 - public static final byte CMD_M_READ_BOLUS_WIZARD_SETUP_STATUS = ((byte)135);// 0x87 - public static final byte CMD_M_READ_CARB_UNITS = ((byte)136);// 0x88 - public static final byte CMD_M_READ_BG_UNITS = ((byte)137);// 0x89 - public static final byte CMD_M_READ_CARB_RATIOS = ((byte)138);// 0x8a - public static final byte CMD_M_READ_INSULIN_SENSITIVITIES = ((byte)139);// 0x8b - public static final byte CMD_M_READ_BG_TARGETS = ((byte)140);// 0x8c - public static final byte CMD_M_READ_PUMP_MODEL_NUMBER = ((byte)141);// 0x8d - public static final byte CMD_M_READ_BG_ALARM_CLOCKS = ((byte)142);// 0x8e - public static final byte CMD_M_READ_RESERVOIR_WARNING = ((byte)143);// 0x8f - public static final byte CMD_M_READ_BG_REMINDER_ENABLE = ((byte)144);// 0x90 - public static final byte CMD_M_READ_SETTINGS = ((byte)145);// 0x91 - public static final byte CMD_M_READ_STD_PROFILES = ((byte)146);// 0x92 - public static final byte CMD_M_READ_A_PROFILES = ((byte)147);// 0x93 - public static final byte CMD_M_READ_B_PROFILES = ((byte)148);// 0x94 - public static final byte CMD_M_READ_LOGIC_LINK_IDS = ((byte)149);// 0x95 - public static final byte CMD_M_READ_BG_ALARM_ENABLE = ((byte)151);// 0x97 - public static final byte CMD_M_READ_TEMP_BASAL = ((byte)152);// 0x98 - public static final byte CMD_M_READ_PUMP_SETTINGS = ((byte)192);// 0xc0 - public static final byte CMD_M_READ_PUMP_STATUS = ((byte)206);// 0xce - - public byte mtype; - public MessageType(byte mtype) { - this.mtype = mtype; - } - - public static MessageBody constructMessageBody(MessageType messageType, byte[] bodyData) { - switch (messageType.mtype) { - case PumpAck: return new PumpAckMessageBody(bodyData); - default: return new UnknownMessageBody(bodyData); - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/PumpAckMessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/PumpAckMessageBody.java deleted file mode 100644 index cb2f3ec307..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/PumpAckMessageBody.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 5/29/16. - */ -public class PumpAckMessageBody extends CarelinkShortMessageBody { - public PumpAckMessageBody() { init(new byte[] {0}); } - public PumpAckMessageBody(byte[] bodyData) { - init(bodyData); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/UnknownMessageBody.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/UnknownMessageBody.java deleted file mode 100644 index 086af96d20..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/Messages/UnknownMessageBody.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.Messages; - -/** - * Created by geoff on 5/29/16. - */ -public class UnknownMessageBody extends MessageBody { - public byte[] rxData; - - public int getLength() { - return 0; - } - - public UnknownMessageBody(byte[] data) { - this.rxData = data; - } - - public void init(byte[] rxData) { - } - - public byte[] getRxData() { - return rxData; - } - - public void setRxData(byte[] rxData) { - this.rxData = rxData; - } - - public byte[] getTxData() { - return rxData; - } - - public void setTxData(byte[] txData) { - this.rxData = txData; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PacketType.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PacketType.java deleted file mode 100644 index d9d519c79d..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PacketType.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic; - -/** - * Created by geoff on 5/29/16. - */ -public class PacketType { - public static final short Invalid = 0x00; - public static final short MySentry = 0xa2; - public static final short Meter = 0xa5; - public static final short Carelink = 0xa7; - public static final short Sensor = 0xa8; - - public short value = 0; - public PacketType() { - } - public PacketType(short value) { - this.value = value; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfile.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfile.java deleted file mode 100644 index cf091b1bb8..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/BasalProfile.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -import android.util.Log; - -import org.joda.time.Instant; - -import java.util.ArrayList; - -/** - * Created by geoff on 6/1/15. - * - * There are three basal profiles stored on the pump. (722 only?) - * They are all parsed the same, the user just has 3 to choose from: - * Standard, A, and B - * - * The byte array seems to be 21 three byte entries long, plus a zero? - * If the profile is completely empty, it should have one entry: [0,0,0x3F] (?) - * The first entry of [0,0,0] marks the end of the used entries. - * - * Each entry is assumed to span from the specified start time to the start time of the - * next entry, or to midnight if there are no more entries. - * - * Individual entries are of the form [r,z,m] where - * r is the rate (in 0.025 U increments) - * z is zero (?) - * m is the start time-of-day for the basal rate period (in 30 minute increments?) - */ -public class BasalProfile { - private static final String TAG = "BasalProfile"; - private static final boolean DEBUG_BASALPROFILE = false; - protected static final int MAX_RAW_DATA_SIZE = (21 * 3) + 1; - protected byte[] mRawData; // store as byte array to make transport (via parcel) easier - public BasalProfile() { - init(); - } - public void init() { - mRawData = new byte[MAX_RAW_DATA_SIZE]; - mRawData[0] = 0; - mRawData[1] = 0; - mRawData[2] = 0x3f; - } - // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. - protected static int readUnsignedByte(byte b) { return (b<0)?b+256:b; } - public boolean setRawData(byte[] data) { - if (data == null) { - Log.e(TAG,"setRawData: buffer is null!"); - return false; - } - int len = Math.min(MAX_RAW_DATA_SIZE, data.length); - System.arraycopy(data, 0, mRawData, 0, len); - if (DEBUG_BASALPROFILE) { - Log.v(TAG, String.format("setRawData: copied raw data buffer of %d bytes.", len)); - } - return true; - } - - public void dumpBasalProfile() { - Log.v(TAG, "Basal Profile entries:"); - ArrayList entries = getEntries(); - for (int i=0; i< entries.size(); i++) { - BasalProfileEntry entry = entries.get(i); - String startString = entry.startTime.toString("HH:mm"); - Log.v(TAG, String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", - i+1, entry.rate, entry.rate_raw, - startString, entry.startTime_raw)); - - } - } - - // TODO: this function must be expanded to include changes in which profile is in use. - // and changes to the profiles themselves. - public BasalProfileEntry getEntryForTime(Instant when) { - BasalProfileEntry rval = new BasalProfileEntry(); - ArrayList entries = getEntries(); - if (entries.size() == 0) { - Log.w(TAG, String.format("getEntryForTime(%s): table is empty", - when.toDateTime().toLocalTime().toString("HH:mm"))); - return rval; - } - //Log.w(TAG,"Assuming first entry"); - rval = entries.get(0); - if (entries.size() == 1) { - Log.v(TAG,"getEntryForTime: Only one entry in profile"); - return rval; - } - - int localMillis = when.toDateTime().toLocalTime().getMillisOfDay(); - boolean done = false; - int i=1; - while (!done) { - BasalProfileEntry entry = entries.get(i); - if (DEBUG_BASALPROFILE) { - Log.v(TAG, String.format("Comparing 'now'=%s to entry 'start time'=%s", - when.toDateTime().toLocalTime().toString("HH:mm"), - entry.startTime.toString("HH:mm"))); - } - if (localMillis >= entry.startTime.getMillisOfDay()) { - rval = entry; - if (DEBUG_BASALPROFILE) Log.v(TAG,"Accepted Entry"); - } else { - // entry at i has later start time, keep older entry - if (DEBUG_BASALPROFILE) Log.v(TAG,"Rejected Entry"); - done = true; - } - i++; - if (i >= entries.size()) { - done = true; - } - } - if (DEBUG_BASALPROFILE) { - Log.v(TAG, String.format("getEntryForTime(%s): Returning entry: rate=%.3f (%d), start=%s (%d)", - when.toDateTime().toLocalTime().toString("HH:mm"), - rval.rate, rval.rate_raw, - rval.startTime.toString("HH:mm"), rval.startTime_raw)); - } - return rval; - } - - public ArrayList getEntries() { - ArrayList entries = new ArrayList<>(); - if (mRawData[2] == 0x3f) { - Log.w(TAG,"Raw Data is empty."); - return entries; // an empty list - } - int i = 0; - boolean done = false; - int r,st; - while (!done) { - r = readUnsignedByte(mRawData[i]); - // What is mRawData[i+1]? Not used in decocare. - st = readUnsignedByte(mRawData[i+2]); - entries.add(new BasalProfileEntry(r,st)); - i=i+3; - if (i>=MAX_RAW_DATA_SIZE) { - done=true; - } else if ((mRawData[i]==0) && (mRawData[i+1]==0) && (mRawData[i+2]==0)) { - done = true; - } - } - return entries; - } - - public static void testParser() { - byte[] testData = new byte[] { - 32, 0, 0, - 38, 0, 13, - 44, 0, 19, - 38, 0, 28, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - /* from decocare: - _test_schedule = {'total': 22.50, 'schedule': [ - { 'start': '12:00A', 'rate': 0.80 }, - { 'start': '6:30A', 'rate': 0.95 }, - { 'start': '9:30A', 'rate': 1.10 }, - { 'start': '2:00P', 'rate': 0.95 }, - ]} - */ - BasalProfile profile = new BasalProfile(); - profile.setRawData(testData); - ArrayList entries = profile.getEntries(); - if (entries.isEmpty()) { - Log.e(TAG,"testParser: failed"); - } else { - for (int i=0; i mBolusWizardEvents; - public ArrayList mBasalEvents; - public HistoryReport() { - mBolusWizardEvents = new ArrayList<>(); - mBasalEvents = new ArrayList<>(); - } - public void addBolusWizardEvent(BolusWizardBolusEstimatePumpEvent event) { - mBolusWizardEvents.add(event); - } - public void addTempBasalEvent(TempBasalEvent event) - { - mBasalEvents.add(event); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlByte.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlByte.java deleted file mode 100644 index 634a480642..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlByte.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -public class HtmlByte extends HtmlElement { - private byte data = 0; - public HtmlByte() {} - public HtmlByte(byte b) { data = b; } - public String toString() {return String.format("%02x",data);} -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagEnd.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagEnd.java deleted file mode 100644 index 9f6855fa89..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagEnd.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -public class HtmlCodeTagEnd extends HtmlElement { - public HtmlCodeTagEnd() {} - public String toString() { return ""; } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagStart.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagStart.java deleted file mode 100644 index 3a92602f98..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlCodeTagStart.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -public class HtmlCodeTagStart extends HtmlElement { - String title = ""; - String color = ""; - public HtmlCodeTagStart(String title, String bgColor) { - this.title = title; - this.color = bgColor; - } - public String toString() { - StringBuilder b = new StringBuilder(); - b.append(" 0)) { - b.append(" title=\""); - b.append(title); - b.append("\""); - } - if ((color != null) && (color.length() > 0)) { - b.append(" style=\"background-color:"); - b.append(color); - b.append(";\""); - } - b.append(">"); - return b.toString(); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElement.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElement.java deleted file mode 100644 index f1fa7ecfdb..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElement.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -abstract public class HtmlElement { - public HtmlElement() {} - abstract public String toString(); -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElementGeneric.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElementGeneric.java deleted file mode 100644 index 5c49956de5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlElementGeneric.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -public class HtmlElementGeneric extends HtmlElement { - String s = ""; - public HtmlElementGeneric() {} - public HtmlElementGeneric(String s) { - this.s = s; - } - public String toString() { - return s; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlHistoryPageStart.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlHistoryPageStart.java deleted file mode 100644 index 86f95ca1e1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/HtmlHistoryPageStart.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 6/24/16. - */ -public class HtmlHistoryPageStart extends HtmlElement { - int pagenum = 0; - public HtmlHistoryPageStart() {} - public HtmlHistoryPageStart(int num) { - pagenum = num; - } - public String toString() { - return "

History Page " + pagenum + "

\n"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/ISFTable.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/ISFTable.java deleted file mode 100644 index 3f1eacc060..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/ISFTable.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -import com.gxwtech.roundtrip2.util.ByteUtil; - -import org.joda.time.LocalDateTime; - -/** - * Created by geoff on 7/2/16. - * - * This class exists to map the Minimed byte response to "Get sensitivity factors" - * into a more usable form. - */ -public class ISFTable { - boolean mIsValid = false; - - LocalDateTime validDate; - byte[] header; - int[] times; - float[] rates; - public ISFTable() {} - public boolean parseFrom(byte[] responseBytes) { - // example format: { 7, 1, 0, 45, 12, 30, 42, 50, 0, 0 } - // means value pairs: {0, 45}, {12, 30}, {42, 50} - // means: at midnight, the amount is 45, - // at 6am, the about is 30 - // at 9pm, the amount is 50 - if (responseBytes == null) return false; - // minimum of two bytes in header - if (responseBytes.length < 2) { - return false; - } - // Must be an even number of times and rates - if (responseBytes.length % 2 != 0) { - return false; - } - mIsValid = true; - header = ByteUtil.substring(responseBytes,0,2); - // find end of list - int index = 2; - while (true) { - if (index + 1 > responseBytes.length) { - break; - } - if ((responseBytes[index]==0) && (responseBytes[index+1]==0)) { - break; - } - index += 2; - } - if (index == 2) { - // no entries. - times = new int[]{}; - rates = new float[]{}; - } else { - int numEntries = (index - 2) / 2; - times = new int[numEntries]; - rates = new float[numEntries]; - for (int i=0; i mRecordList; - - public Page() { - this.model = PumpModel.UNSET; - mRecordList = new ArrayList<>(); - } - - public byte[] getRawData() { - if (data == null) { - return crc; - } - if (crc == null) { - return data; - } - return ByteUtil.concat(data,crc); - } - - protected PumpTimeStamp collectTimeStamp(byte[] data, int offset) { - try { - PumpTimeStamp timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, offset)); - return timestamp; - } catch (org.joda.time.IllegalFieldValueException e) { - return null; - } - } - - public boolean parsePicky(byte[] rawPage, PumpModel model) { - mRecordList = new ArrayList<>(); - this.model = model; - int pageOffset = 0; - - if ((rawPage == null) || (rawPage.length == 0)) return false; - this.data = Arrays.copyOfRange(rawPage, 0, rawPage.length-2); - this.crc = Arrays.copyOfRange(rawPage, rawPage.length-2, rawPage.length); - byte[] expectedCrc = CRC.calculate16CCITT(this.data); - if (DEBUG_PAGE) { - Log.i(TAG, String.format("Data length: %d", data.length)); - } - if (!Arrays.equals(crc, expectedCrc)) { - Log.w(TAG, String.format("CRC does not match expected value. Expected: %s Was: %s", HexDump.toHexString(expectedCrc), HexDump.toHexString(crc))); - } else { - if (DEBUG_PAGE) { - Log.i(TAG, "CRC OK"); - } - } - - Record record = null; - while (pageOffset < data.length) { - if (data[pageOffset] == 0) { - if (record != null) { - Log.i(TAG,String.format("End of page or Previous parse fail: prev opcode 0x%02x, curr offset %d, %d bytes remaining", - record.getRecordOp(),pageOffset,data.length - pageOffset + 1)); - break; - } else { - Log.i(TAG, "WTF?"); - } - } - try { - record = attemptParseRecord(data, pageOffset); - } catch (org.joda.time.IllegalFieldValueException e) { - record = null; - } - if (record == null) { - Log.i(TAG, "PARSE FAIL"); - pageOffset++; - } else { - mRecordList.add(record); - pageOffset+=record.getLength(); - } - } - ArrayList pickyRecords = new ArrayList<>(); - pickyRecords.addAll(mRecordList); - parseByDates(rawPage,model); - for (Record r : mRecordList) { - for (Record r2 : pickyRecords) { - if (r.getFoundAtOffset() == r2.getFoundAtOffset()) { - Log.v(TAG,"Found matching record at offset " + r.getFoundAtOffset()); - } - } - } - return true; - } - - public boolean parseByDates(byte[] rawPage, PumpModel model) { - mRecordList = new ArrayList<>(); - if (rawPage.length != 1024) { - Log.e(TAG,"Unexpected page size. Expected: 1024 Was: " + rawPage.length); - //return false; - } - this.model = model; - if (DEBUG_PAGE) { - Log.i(TAG, "Parsing page"); - } - - if (rawPage.length < 4) { - Log.e(TAG,"Page too short, need at least 4 bytes"); - return false; - } - - this.data = Arrays.copyOfRange(rawPage, 0, rawPage.length-2); - this.crc = Arrays.copyOfRange(rawPage, rawPage.length-2, rawPage.length); - byte[] expectedCrc = CRC.calculate16CCITT(this.data); - if (DEBUG_PAGE) { - Log.i(TAG, String.format("Data length: %d", data.length)); - } - if (!Arrays.equals(crc, expectedCrc)) { - Log.w(TAG, String.format("CRC does not match expected value. Expected: %s Was: %s", HexDump.toHexString(expectedCrc), HexDump.toHexString(crc))); - } else { - if (DEBUG_PAGE) { - Log.i(TAG, "CRC OK"); - } - } - - int pageOffset = 0; - PumpTimeStamp lastPumpTimeStamp = new PumpTimeStamp(); - while (pageOffset < this.data.length - 7) { - PumpTimeStamp timestamp = collectTimeStamp(data,pageOffset+2); - if (timestamp!=null) { - String year = timestamp.toString().substring(0,3); - Record record; - if ("201".equals(year)) { - // maybe found a record. - try { - record = attemptParseRecord(data, pageOffset); - } catch (org.joda.time.IllegalFieldValueException e) { - record = null; - } - if (record != null) { - if (timestamp.getLocalDateTime().compareTo(lastPumpTimeStamp.getLocalDateTime()) >= 0) { - Log.i(TAG, "Timestamp is increasing"); - lastPumpTimeStamp = timestamp; - mRecordList.add(record); - } else { - Log.e(TAG, "Timestamp is decreasing"); - } - } - } - } - pageOffset++; - } - - - - return true; - } - - public boolean parseFrom(byte[] rawPage, PumpModel model) { - mRecordList = new ArrayList<>(); // wipe old contents each time when parsing. - if (rawPage.length != 1024) { - Log.e(TAG,"Unexpected page size. Expected: 1024 Was: " + rawPage.length); - //return false; - } - this.model = model; - if (DEBUG_PAGE) { - Log.i(TAG, "Parsing page"); - } - - if (rawPage.length < 4) { - Log.e(TAG,"Page too short, need at least 4 bytes"); - return false; - } - - this.data = Arrays.copyOfRange(rawPage, 0, rawPage.length-2); - this.crc = Arrays.copyOfRange(rawPage, rawPage.length-2, rawPage.length); - byte[] expectedCrc = CRC.calculate16CCITT(this.data); - if (DEBUG_PAGE) { - Log.i(TAG, String.format("Data length: %d", data.length)); - } - if (!Arrays.equals(crc, expectedCrc)) { - Log.w(TAG, String.format("CRC does not match expected value. Expected: %s Was: %s", HexDump.toHexString(expectedCrc), HexDump.toHexString(crc))); - } else { - if (DEBUG_PAGE) { - Log.i(TAG, "CRC OK"); - } - } - - int dataIndex = 0; - boolean done = false; - while (!done) { - Record record = null; - if (data[dataIndex] != 0) { - // If the data byte is zero, assume that means end of page - try { - record = attemptParseRecord(data, dataIndex); - } catch (org.joda.time.IllegalFieldValueException e) { - record = null; - } - } else { - Log.v(TAG,"Zero opcode encountered -- end of page. " + (rawPage.length - dataIndex) + " bytes remaining."); - break; - } - if (record != null) { - Log.v(TAG,"parseFrom: found event "+record.getClass().getSimpleName() + " length=" + record.getLength() + " offset=" + record.getFoundAtOffset()); - mRecordList.add(record); - dataIndex += record.getLength(); - } else { - Log.e(TAG,String.format("parseFrom: Failed to parse opcode 0x%02x, offset=%d",data[dataIndex],dataIndex)); - done = true; - } - if (dataIndex >= data.length - 2) { - done = true; - } - } - if (DEBUG_PAGE) { - Log.i(TAG, String.format("Number of records: %d", mRecordList.size())); - int index = 1; - for (Record r : mRecordList) { - Log.v(TAG, String.format("Record #%d: %s", index,r.getShortTypeName())); - index += 1; - } - } - return true; - } - - /* attemptParseRecord will attempt to create a subclass of Record from the given - * data and offset. It will return NULL if it fails. If it succeeds, the returned - * subclass of Record can be examined for its length, so that the next attempt can be made. - */ - public static T attemptParseRecord(byte[] data, int offsetStart) { - // no data? - if (data == null) { - return null; - } - // invalid offset? - if (data.length < offsetStart) { - return null; - } - //Log.d(TAG,String.format("checking for handler for record type 0x%02X at index %d",data[offsetStart],offsetStart)); - RecordTypeEnum en = RecordTypeEnum.fromByte(data[offsetStart]); - T record = en.getRecordClassInstance(PumpModel.MM522); - if (record != null) { - // have to do this to set the record's opCode - byte[] tmpData = new byte[data.length]; - System.arraycopy(data, offsetStart, tmpData, 0, data.length - offsetStart); - boolean didParse = record.parseWithOffset(tmpData, PumpModel.MM522, offsetStart); - if (!didParse) { - Log.e(TAG,String.format("attemptParseRecord: class %s (opcode 0x%02X) failed to parse at offset %d",record.getShortTypeName(),data[offsetStart],offsetStart)); - } - } - return record; - } - - public static DateTime parseSimpleDate(byte[] data, int offset) { - DateTime timeStamp = null; - int seconds = 0; - int minutes = 0; - int hour = 0; - //int high = data[0] >> 4; - int low = data[0 + offset] & 0x1F; - //int year_high = data[1] >> 4; - int mhigh = (data[0 + offset] & 0xE0) >> 4; - int mlow = (data[1 + offset] & 0x80) >> 7; - int month = mhigh + mlow; - int dayOfMonth = low + 1; - // python code says year is data[1] & 0x0F, but that will cause problem in 2016. - // Hopefully, the remaining bits are part of the year... - int year = data[1 + offset] & 0x3F; - /* - Log.w(TAG, String.format("Attempting to create DateTime from: %04d-%02d-%02d %02d:%02d:%02d", - year + 2000, month, dayOfMonth, hour, minutes, seconds)); - */ - try { - timeStamp = new DateTime(year + 2000, month, dayOfMonth, hour, minutes, seconds); - } catch (org.joda.time.IllegalFieldValueException e) { - //Log.e(TAG,"Illegal DateTime field"); - //e.printStackTrace(); - return null; - } - return timeStamp; - } - - public static void discoverRecords(byte[] data) { - int i = 0; - boolean done = false; - - ArrayList keyLocations= new ArrayList(); - while (!done) { - RecordTypeEnum en = RecordTypeEnum.fromByte(data[i]); - if (en != RecordTypeEnum.RECORD_TYPE_NULL) { - keyLocations.add(i); - Log.v(TAG, String.format("Possible record of type %s found at index %d", en, i)); - } - /* - DateTime ts = parseSimpleDate(data,i); - if (ts != null) { - if (ts.year().get() == 2015) { - Log.w(TAG, String.format("Possible simple date at index %d", i)); - } - } - */ - i = i + 1; - done = (i >= data.length-2); - } - // for each of the discovered key locations, attempt to parse a sequence of records - for(RecordTypeEnum en : RecordTypeEnum.values()) { - - } - for (int ix = 0; ix < keyLocations.size(); ix++) { - - } - } - - /* - * - * For IPC serialization - * - */ - - /* - private byte[] crc; - private byte[] data; - protected PumpModel model; - public List mRecordList; - */ - - public Bundle pack() { - Bundle bundle = new Bundle(); - bundle.putByteArray("crc",crc); - bundle.putByteArray("data",data); - bundle.putString("model",PumpModel.toString(model)); - ArrayList records = new ArrayList<>(); - for (int i=0; i records = in.getParcelableArrayList("mRecordList"); - mRecordList = new ArrayList<>(); - if (records != null) { - for (int i=0; i list) { - SQLiteDatabase db = getWritableDatabase(); - for (ContentValues cvs : list) { - db.insert(DATABASE_TABLE_entries, null, cvs); - } - db.close(); - Log.d(TAG,"Database "+ DATABASE_NAME + " saved"); - } - - public void clearPumpHistoryDatabase() { - SQLiteDatabase db = getWritableDatabase(); - db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE_entries); - onCreate(db); - db.close(); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryManager.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryManager.java deleted file mode 100644 index 061776abb6..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryManager.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -import android.content.ContentValues; -import android.content.Context; -import android.os.Bundle; -import android.os.Environment; -import android.util.Log; - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records.Record; -import com.gxwtech.roundtrip2.util.StringUtil; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Array; -import java.util.ArrayList; - -/** - * Created by geoff on 6/17/16. - */ -public class PumpHistoryManager { - private static final String TAG = "PumpHistoryManager"; - private Context context; - private PumpHistoryDatabaseHandler phdb; - ArrayList dbContentValues = new ArrayList<>(); - ArrayList packedPages = null; - public PumpHistoryManager(Context context) { - this.context = context; - phdb = new PumpHistoryDatabaseHandler(context); - } - - public void initFromPages(Bundle historyBundle) { - packedPages = historyBundle.getParcelableArrayList(RT2Const.IPC.MSG_PUMP_history_key); - for (int i=0; i recordBundleList = pageBundle.getParcelableArrayList("mRecordList"); - for (Bundle b : recordBundleList) { - try { - PumpHistoryDatabaseEntry entry = new PumpHistoryDatabaseEntry(); - if (entry.initFromRecordBundle(i, b)) { - dbContentValues.add(entry.getContentValues()); - } - } catch (java.lang.NullPointerException e) { - e.printStackTrace(); - } - } - } - } - phdb.addContentValuesList(dbContentValues); - } - - public void clearDatabase() { - phdb.clearPumpHistoryDatabase(); - } - - /* Checks if external storage is available for read and write */ - public boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } - return false; - } - - public boolean timestampOK(String timestamp) { - if (timestamp == null) { - return false; - } - if (timestamp.length() < 4) { - return false; - } - if ("2015".equals(timestamp.substring(0,4))) { - return true; - } - if ("2016".equals(timestamp.substring(0,4))) { - return true; - } - return false; - } - - public HtmlCodeTagStart renderContexts(ArrayList relevantBundles) { - // search for all contexts that span this byte - // make a start tag that represents them. - StringBuilder titleBuilder = new StringBuilder(); - for (Bundle b : relevantBundles) { - String name = b.getString("_type"); - String timestamp = b.getString("timestamp"); - int length = b.getInt("length"); - int offset = b.getInt("foundAtOffset"); - titleBuilder.append(String.format("[%s%s %s l=%d o=%d]", - timestampOK(timestamp) ? "" : "BAD ", - name==null?"(null)":name, - timestamp == null?"(null)":timestamp, - length, offset)); - } - String colorString = null; - if (relevantBundles.size() == 1) { - if (timestampOK(relevantBundles.get(0).getString("timestamp"))) { - colorString = "#99ff99"; - } else { - colorString = "#F0E68C"; - } - } else if (relevantBundles.size() > 1) { - boolean allOK = relevantBundlesAllOK(relevantBundles); - boolean allBad = relevantBundlesAllBad(relevantBundles); - if (allOK) { - colorString = "#248f24"; - } else if (allBad) { - colorString = "#cc0000"; - } else { - colorString = "#b3b300"; - } - } - return new HtmlCodeTagStart(titleBuilder.toString(),colorString); - } - - public ArrayList findRelevantBundles(int pageNum, int pageOffset) { - ArrayList relevantBundles = new ArrayList<>(); - ArrayList recordBundleList = packedPages.get(pageNum).getParcelableArrayList("mRecordList"); - for (int i=0; i< recordBundleList.size(); i++) { - Bundle recordBundle = recordBundleList.get(i); - int offset = recordBundle.getInt("foundAtOffset"); - int length = recordBundle.getInt("length"); - if ((offset <= pageOffset) && (offset + length > pageOffset)) { - relevantBundles.add(recordBundle); - } - } - return relevantBundles; - } - - public boolean relevantBundlesAllOK(ArrayList bundles) { - for (Bundle b : bundles) { - String ts = b.getString("timestamp"); - if (ts == null) { - return false; - } - if (!timestampOK(ts)) { - return false; - } - - } - return true; - } - - public boolean relevantBundlesAllBad(ArrayList bundles) { - for (Bundle b : bundles) { - String ts = b.getString("timestamp"); - if (ts != null) { - if (timestampOK(ts)) { - return false; - } - } - } - return true; - } - - public boolean relevantBundlesSame(ArrayList bundles1, ArrayList bundles2) { - if (bundles1.size() != bundles2.size()) { - return false; - } - for (Bundle b : bundles1) { - if (!bundles2.contains(b)) { - return false; - } - } - for (Bundle b : bundles2) { - if (!bundles1.contains(b)) { - return false; - } - } - return true; - } - - public boolean relevantBundlesAllDifferent(ArrayList bundles1, ArrayList bundles2) { - for (Bundle b : bundles1) { - if (bundles2.contains(b)) { - return false; - } - } - for (Bundle b : bundles2) { - if (bundles1.contains(b)) { - return false; - } - } - return true; - } - - public ArrayList makeDom() { - ArrayList rval = new ArrayList<>(); - for (int pageNum = 0; pageNum < packedPages.size(); pageNum++) { - Log.i(TAG,"Rendering page " + pageNum); - rval.add(new HtmlHistoryPageStart(pageNum)); - byte[] pageData = packedPages.get(pageNum).getByteArray("data"); - if (pageData == null) { - return rval; - } - int pageSize = pageData.length; - byte[] crc = packedPages.get(pageNum).getByteArray("crc"); - if (pageSize != 1022) { - Log.e(TAG, "Page size is not 1022, it is " + pageSize); - } - int pageOffset = 0; - boolean done = false; - ArrayList currentBundles = findRelevantBundles(pageNum, pageOffset); - ArrayList nextBundles = new ArrayList<>(); - rval.add(renderContexts(currentBundles)); - while (!done) { - rval.add(new HtmlByte(pageData[pageOffset])); - if (pageOffset == pageSize - 1) { - done = true; - } else { - nextBundles = findRelevantBundles(pageNum, pageOffset + 1); - if (relevantBundlesSame(currentBundles, nextBundles)) { - // Not changing context - if (pageOffset % 32 == 31) { - rval.add(new HtmlElementGeneric("
\n")); - } else { - rval.add(new HtmlElementGeneric(" ")); - } - } else { - // Changing context - rval.add(new HtmlCodeTagEnd()); - if (relevantBundlesAllDifferent(currentBundles, nextBundles)) { - rval.add(new HtmlCodeTagStart("", "")); // - if (pageOffset % 32 == 31) { - rval.add(new HtmlElementGeneric("
\n")); - } else { - rval.add(new HtmlElementGeneric(" ")); - } - if (nextBundles.size() != 0) { - rval.add(new HtmlCodeTagEnd()); - rval.add(renderContexts(nextBundles)); - } - } else { - if (pageOffset % 32 == 31) { - rval.add(new HtmlElementGeneric("
\n")); - } else { - rval.add(new HtmlElementGeneric(" ")); - } - rval.add(new HtmlCodeTagEnd()); - rval.add(renderContexts(nextBundles)); - } - } - } - if (!done) { - pageOffset++; - currentBundles = nextBundles; - } - } - } - return rval; - } - - public void writeHtmlPage() { - - /* - final String key_timestamp = "timestamp"; - String timestampString; - final String key_pageNum = "pagenum"; - int pageNum; - final String key_pageOffset = "offset"; - int foundAtOffset; - final String key_recordType = "type"; - String recordType; - final String key_length = "length"; - int length; -*/ - if (!isExternalStorageWritable()) { - Log.e(TAG,"External storage not writable."); - return; - } - - String filename = "PumpHistoryBytes.html"; - - File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); - File pageFile = new File(path,filename); - - OutputStream os = null; - try { - os = new FileOutputStream(pageFile); - } catch (FileNotFoundException fnf) { - Log.e(TAG,"Failed to open " + filename + " for writing"); - } - if (os == null) { - return; - } - - // write header - try { - os.write("".getBytes()); - os.write("".getBytes()); - os.write("".getBytes()); - os.write("Page Title".getBytes()); - os.write("".getBytes()); - os.write("".getBytes()); - - byte[] pageData = packedPages.get(0).getByteArray("data"); - int pageSize = pageData.length; - //byte[] crc = packedPages.get(0).getByteArray("crc"); - if (pageSize != 1022) { - Log.e(TAG,"Page size is not 1022, it is " + pageSize); - } - - ArrayList dom = makeDom(); - Log.i(TAG,"There are " + dom.size() + " elements to render."); - for (HtmlElement e : dom) { - if (e != null) { - String elementString = e.toString(); - if (elementString != null) { - byte[] bytes = elementString.getBytes(); - if (bytes != null) { - os.write(bytes); - } else { - Log.e(TAG,"WriteHtmlPage: bytes is null"); - } - } else { - Log.e(TAG,"WriteHtmlPage: elementString is null"); - } - } else { - Log.e(TAG,"WriteHtmlPage: element is null"); - } - } - - os.write("".getBytes()); - os.close(); - } catch (FileNotFoundException fnf) { - fnf.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryPage.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryPage.java deleted file mode 100644 index 14dd971eb7..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryPage.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.util.ByteUtil; -import com.gxwtech.roundtrip2.util.CRC; - -/** - * Created by geoff on 6/18/16. - */ -public class PumpHistoryPage { - public byte[] data = new byte[0]; - private PumpModel model = PumpModel.MM522; - private int pageNumber; - public PumpHistoryPage() {} - public PumpHistoryPage(byte[] data, PumpModel model, int pageNumber) { - init(data,model,pageNumber); - } - public void init(byte[] data, PumpModel model, int pageNumber) { - this.data = data; - this.model = model; - this.pageNumber = pageNumber; - } - public int getPageNumber() { return pageNumber; } - public boolean isValid() { - return isCRCValid(); - } - public boolean isCRCValid() { - if (data == null) { - return false; - } - if (data.length < 3) { - return false; - } - byte[] crc16 = CRC.calculate16CCITT(ByteUtil.substring(data,0,data.length-2)); - if (crc16 == null) { - return false; - } - if ((crc16[0] == data[data.length-2]) && (crc16[1]==data[data.length-1])) { - return true; - } - return false; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryParser.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryParser.java deleted file mode 100644 index d277bb56df..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpHistoryParser.java +++ /dev/null @@ -1,263 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -import android.os.Bundle; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; -import com.gxwtech.roundtrip2.util.ByteUtil; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Created by geoff on 6/18/16. - * - * - * - * This class is not in use -- it may become a replacement for the history object heirarchy parser - * - * - * - * - * - * - * - */ -@Deprecated -public class PumpHistoryParser { - private static final String TAG = "PumpHistoryParser"; - public PumpModel model; - public ArrayList pages = new ArrayList<>(); - public ArrayList entries = new ArrayList<>(); - public PumpHistoryParser(PumpModel model) { - initOpcodes(); - } - public void parsePage(byte[] rawData) { - PumpHistoryPage page = new PumpHistoryPage(rawData,model,pages.size()+1); - pages.add(page); - if (page.isCRCValid() == false) { - Log.e(TAG,"CRC16 for page " + page.getPageNumber() + " is invalid."); - } - if (page.data.length != 1024) { - Log.w(TAG,String.format("Page %d has length %d, expected 1024",page.getPageNumber(),page.data.length)); - } - int currentOffset = 0; - boolean done = false; - while (!done) { - Bundle b = attemptParseRecord(page.getPageNumber(),currentOffset); - if (b == null) { - // then the parse failed. - } - } - } - - static int asUINT8(byte b) { - return (b < 0) ? b + 256 : b; - } - - static double insulinDecode(int a, int b) { - return ((a << 8) + b) / 40.0; - } - - public Bundle attemptParseRecord(int pageNum, int offset) { - byte[] dataPage = pages.get(pageNum).data; - int opcode = pages.get(pageNum).data[offset]; - Bundle record = new Bundle(); - String typename = opCodeNames.get(opcode); - if (typename != null) { - record.putInt("opcode",opcode); - record.putString("type",typename); - record.putInt("page",pageNum); - record.putInt("offset",offset); - record.putString("indexer",String.format("%02d%04d",pageNum,offset)); - } else { - return null; - } - int length = 0; - int dateOffset = 0; - PumpTimeStamp timestamp; - byte[] data = ByteUtil.substring(dataPage,offset,dataPage.length - 2 - offset); - switch (opcode) { - case RECORD_TYPE_BolusNormal: { - length = PumpModel.isLargerFormat(model) ? 13 : 9; - if (length + offset > data.length) return null; - record.putInt("length",length); - double programmedAmount; - double deliveredAmount; - double unabsorbedInsulinTotal; - int duration; - String bolusType; - if (PumpModel.isLargerFormat(model)) { - programmedAmount = insulinDecode(asUINT8(data[1]),asUINT8(data[2])); - deliveredAmount = insulinDecode(asUINT8(data[3]),asUINT8(data[4])); - unabsorbedInsulinTotal = insulinDecode(asUINT8(data[5]),asUINT8(data[6])); - duration = asUINT8(data[7]) * 30; - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, 8)); - } catch (org.joda.time.IllegalFieldValueException e) { - timestamp = new PumpTimeStamp(); - } - } else { - programmedAmount = asUINT8(data[1]) / 10.0f; - deliveredAmount = asUINT8(data[2]) / 10.0f; - duration = asUINT8(data[3]) * 30; - unabsorbedInsulinTotal = 0; - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, 4)); - } catch (org.joda.time.IllegalFieldValueException e) { - timestamp = new PumpTimeStamp(); - } - } - bolusType = (duration > 0) ? "square" : "normal"; - record.putDouble("programmedAmount",programmedAmount); - record.putDouble("deliveredAmount",deliveredAmount); - record.putInt("duration",duration); - record.putDouble("unabsorbedInsulinTotal",unabsorbedInsulinTotal); - record.putString("bolusType",bolusType); - record.putString("timestamp",timestamp.getLocalDateTime().toString()); - - } break; - case RECORD_TYPE_AlarmSensor: - length = 8; - if (length + offset > data.length) return null; - record.putInt("length",length); - case RECORD_TYPE_Resume: - case RECORD_TYPE_AlarmClockReminder: - length = 7; - if (length + offset > data.length) return null; - record.putInt("length",length); - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, 2)); - } catch (org.joda.time.IllegalFieldValueException e) { - timestamp = new PumpTimeStamp(); - } - record.putString("timestamp",timestamp.getLocalDateTime().toString()); - default: - record.putInt("length",0); - record.putString("comment","unparsed"); - } - return record; - } - - HashMap opCodeNames = new HashMap<>(); - HashMap opCodeNumbers = new HashMap<>(); - - private void initOpcode(int number, String name) { - opCodeNames.put(number,name); - opCodeNumbers.put(name,number); - } - - public static final int RECORD_TYPE_BolusNormal = 0x01; - public static final int RECORD_TYPE_Prime = 0x03; - public static final int RECORD_TYPE_PumpAlarm = 0x06; - public static final int RECORD_TYPE_ResultDailyTotal = 0x07; - public static final int RECORD_TYPE_ChangeBasalProfilePattern = 0x08; - public static final int RECORD_TYPE_ChangeBasalProfile = 0x09; - public static final int RECORD_TYPE_CalBgForPh = 0x0A; - public static final int RECORD_TYPE_AlarmSensor = 0x0B; - public static final int RECORD_TYPE_ClearAlarm = 0x0C; - public static final int RECORD_TYPE_SelectBasalProfile = 0x14; - public static final int RECORD_TYPE_TempBasalDuration = 0x16; - public static final int RECORD_TYPE_ChangeTime = 0x17; - public static final int RECORD_TYPE_NewTimeSet = 0x18; - public static final int RECORD_TYPE_JournalEntryPumpLowBattery = 0x19; - public static final int RECORD_TYPE_Battery = 0x1A; - public static final int RECORD_TYPE_Suspend = 0x1E; - public static final int RECORD_TYPE_Resume = 0x1F; - public static final int RECORD_TYPE_Rewind = 0x21; - public static final int RECORD_TYPE_ChangeChildBlockEnable = 0x23; - public static final int RECORD_TYPE_ChangeMaxBolus = 0x24; - public static final int RECORD_TYPE_EnableDisableRemote = 0x26; - public static final int RECORD_TYPE_TempBasalRate = 0x33; - public static final int RECORD_TYPE_JournalEntryPumpLowReservoir = 0x34; - public static final int RECORD_TYPE_AlarmClockReminder = 0x35; - public static final int RECORD_TYPE_BGReceived = 0x3F; - public static final int RECORD_TYPE_JournalEntryExerciseMarker = 0x41; - public static final int RECORD_TYPE_ChangeSensorSetup2 = 0x50; - public static final int RECORD_TYPE_ChangeSensorRateOfChangeAlertSetup = 0x56; - public static final int RECORD_TYPE_ChangeBolusScrollStepSize = 0x57; - public static final int RECORD_TYPE_ChangeBolusWizardSetup = 0x5A; - public static final int RECORD_TYPE_BolusWizardBolusEstimate = 0x5B; - public static final int RECORD_TYPE_UnabsorbedInsulin = 0x5C; - public static final int RECORD_TYPE_ChangeVariableBolus = 0x5e; - public static final int RECORD_TYPE_ChangeAudioBolus = 0x5f; - public static final int RECORD_TYPE_ChangeBGReminderEnable = 0x60; - public static final int RECORD_TYPE_ChangeAlarmClockEnable = 0x61; - public static final int RECORD_TYPE_ChangeTempBasalType = 0x62; - public static final int RECORD_TYPE_ChangeAlarmNotifyMode = 0x63; - public static final int RECORD_TYPE_ChangeTimeFormat = 0x64; - public static final int RECORD_TYPE_ChangeReservoirWarningTime = 0x65; - public static final int RECORD_TYPE_ChangeBolusReminderEnable = 0x66; - public static final int RECORD_TYPE_ChangeBolusReminderTime = 0x67; - public static final int RECORD_TYPE_DeleteBolusReminderTime = 0x68; - public static final int RECORD_TYPE_DeleteAlarmClockTime = 0x6a; - public static final int RECORD_TYPE_Model522ResultTotals = 0x6D; - public static final int RECORD_TYPE_Sara6E = 0x6E; - public static final int RECORD_TYPE_ChangeCarbUnits = 0x6f; - public static final int RECORD_TYPE_BasalProfileStart = 0x7B; - public static final int RECORD_TYPE_ChangeWatchdogEnable = 0x7c; - public static final int RECORD_TYPE_ChangeOtherDeviceID = 0x7d; - public static final int RECORD_TYPE_ChangeWatchdogMarriageProfile = 0x81; - public static final int RECORD_TYPE_DeleteOtherDeviceID = 0x82; - public static final int RECORD_TYPE_ChangeCaptureEventEnable = 0x83; - - private void initOpcodes() { - initOpcode(0x01,"BolusNormal"); - initOpcode(0x03,"Prime"); - initOpcode(0x06,"PumpAlarm"); - initOpcode(0x07,"ResultDailyTotal"); - initOpcode(0x08,"ChangeBasalProfilePattern"); - initOpcode(0x09,"ChangeBasalProfile"); - initOpcode(0x0A,"CalBgForPh"); - initOpcode(0x0B,"AlarmSensor"); - initOpcode(0x0C,"ClearAlarm"); - //initOpcode(0x14,"SelectBasalProfile"); - initOpcode(0x16,"TempBasalDuration"); - initOpcode(0x17,"ChangeTime"); - //initOpcode(0x18,"NewTimeSet"); - initOpcode(0x19,"JournalEntryPumpLowBattery"); - initOpcode(0x1A,"Battery"); - initOpcode(0x1E,"Suspend"); - initOpcode(0x1F,"Resume"); - initOpcode(0x21,"Rewind"); - initOpcode(0x23,"ChangeChildBlockEnable"); - initOpcode(0x24,"ChangeMaxBolus"); - initOpcode(0x26,"EnableDisableRemote"); - initOpcode(0x33,"TempBasalRate"); - initOpcode(0x34,"JournalEntryPumpLowReservoir"); - initOpcode(0x35,"AlarmClockReminder"); - initOpcode(0x3F,"BGReceived"); - initOpcode(0x41,"JournalEntryExerciseMarker"); - initOpcode(0x50,"ChangeSensorSetup2"); - initOpcode(0x56,"ChangeSensorRateOfChangeAlertSetup"); - initOpcode(0x57,"ChangeBolusScrollStepSize"); - initOpcode(0x5A,"ChangeBolusWizardSetup"); - initOpcode(0x5B,"BolusWizardBolusEstimate"); - initOpcode(0x5C,"UnabsorbedInsulin"); - initOpcode(0x5e,"ChangeVariableBolus"); - initOpcode(0x5f,"ChangeAudioBolus"); - initOpcode(0x60,"ChangeBGReminderEnable"); - initOpcode(0x61,"ChangeAlarmClockEnable"); - initOpcode(0x62,"ChangeTempBasalType"); - initOpcode(0x63,"ChangeAlarmNotifyMode"); - initOpcode(0x64,"ChangeTimeFormat"); - initOpcode(0x65,"ChangeReservoirWarningTime"); - initOpcode(0x66,"ChangeBolusReminderEnable"); - initOpcode(0x67,"ChangeBolusReminderTime"); - initOpcode(0x68,"DeleteBolusReminderTime"); - initOpcode(0x6a,"DeleteAlarmClockTime"); - initOpcode(0x6D,"Model522ResultTotals"); - initOpcode(0x6E,"Sara6E"); - initOpcode(0x6f,"ChangeCarbUnits"); - initOpcode(0x7B,"BasalProfileStart"); - initOpcode(0x7c,"ChangeWatchdogEnable"); - initOpcode(0x7d,"ChangeOtherDeviceID"); - initOpcode(0x81,"ChangeWatchdogMarriageProfile"); - initOpcode(0x82,"DeleteOtherDeviceID"); - initOpcode(0x83,"ChangeCaptureEventEnable"); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpSettings.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpSettings.java deleted file mode 100644 index 6c8772ec20..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/PumpSettings.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 5/7/15. - * - * This class is intended to be very basic, and only hold the simple data. - * That way it will be portable, reusable. - * - * For instance, for the android UI, there is a parcelable version of this class - * (PumpSettingsParcel) but I don't want the pump implementation to be dependent - * on Android.Parcelable. - * - * For marshalling the data into other forms, I'm keeping the original - * byte array (mRawData) around. So if we have to save/reload this data object - * we can just write the raw data array, and reload from it. We already have to - * parse our values from it, so just keep it handy. Makes the Parcelable - * implementation very simple. - * - */ -@Deprecated -public class PumpSettings { - private static final String TAG = "PumpSettings"; - - // these values help with the parcel extension - protected static final int MINIMUM_DATA_LENGTH = 20; // bytes - protected static final int MAXIMUM_DATA_LENGTH = 64; // bytes - protected byte[] mRawData; - - public byte mAutoOffDuration_hours = 0; - public byte mAlarmMode = 0; - public byte mAlarmVolume = 0; - public boolean mAudioBolusEnable = false; - public double mAudioBolusSize = 0.0; - public boolean mVariableBolusEnable = false; - public double mMaxBolus = 0.0; // MM23 is different (?) - // MM512 and up (?) - public double mMaxBasal = 0.0; - public byte mTimeFormat = 0; - public int mInsulinConcentration = 100; // 100 or 50 - public boolean mPatternsEnabled = false; - public BasalProfileTypeEnum mSelectedPattern = BasalProfileTypeEnum.STD; - public boolean mRFEnable = false; - public boolean mBlockEnable = false; - public byte mTempBasalType = 0; // 1 means Percent, 0 means UnitsPerHour - public byte mTempBasalRate = 0; // TODO: scaling? - public byte mParadigmEnable = 0; - // MM12 - // boolean mInsulinActionType (0='Fast' or 1='Regular') - // MM15 - public byte mInsulinActionType = 0; - public byte mLowReservoirWarnType = 0; - public byte mLowReservoirWarnPoint = 0; - public byte mKeypadLockStatus = 0; - - public PumpSettings() { - init(); - } - - public void init() { - // this data buffer has to be sized to maximum even when empty - // as we may be reading from a parcel. See PumpSettingsParcel. - mRawData = new byte[MAXIMUM_DATA_LENGTH]; - /* fill in default values */ - } - - public byte[] getRawData() { return mRawData; } - - public boolean parseFrom(byte[] data) { - if (!setRawData(data)) { return false; } - return parseFromRaw(); - } - - // copy as much as we can from a byte array, but don't parse it. - public boolean setRawData(byte[] data) { - if (data == null) { - return false; - } - int len = Math.min(MAXIMUM_DATA_LENGTH,data.length); - System.arraycopy(data,0,mRawData,0,len); - return true; - } - - public boolean parseFromRaw() { - mAutoOffDuration_hours = mRawData[0]; - mAlarmVolume = mRawData[1]; - mAlarmMode = 2; - if (mRawData[1] == 4) { - mAlarmVolume = -1; - mAlarmMode = 1; - } - mAudioBolusEnable = (mRawData[2] == 1); - mAudioBolusSize = 0; - if (mAudioBolusEnable) { - mAudioBolusSize = mRawData[3] / 10.0; - } - mVariableBolusEnable = (mRawData[4] == 1); - // MM23 is different - int maxBolusByte = mRawData[5]; - if (maxBolusByte < 0) { maxBolusByte += 256; } - mMaxBolus = (maxBolusByte) / 10.0; - // MM512 and up - // TODO: check mMaxBasal calculation - // did I get the bytes in the right order? - int maxBasalHighByte = mRawData[6]; - if (maxBasalHighByte < 0) { - maxBasalHighByte += 256; - } - int maxBasalLowByte = mRawData[7]; - if (maxBasalLowByte < 0) { - maxBasalLowByte += 256; - } - mMaxBasal = ((maxBasalHighByte * 256) + maxBasalLowByte)/40.0; - mTimeFormat = mRawData[8]; - // mInsulinConcentration: 0 is 100%, 1 is 50% - mInsulinConcentration = 100; - if (mRawData[9] == 1) { - mInsulinConcentration = 50; - } - mPatternsEnabled = (mRawData[10] == 1); - mSelectedPattern = BasalProfileTypeEnum.STD; - if (mRawData[11] == 0x01) { - mSelectedPattern = BasalProfileTypeEnum.A; - } else if (mRawData[11] == 0x02) { - mSelectedPattern = BasalProfileTypeEnum.B; - } - mRFEnable = (mRawData[12] == 1); - mBlockEnable = (mRawData[13] == 1); - mTempBasalType = mRawData[14]; // todo: put into proper class of its own - mTempBasalRate = mRawData[15]; - - mParadigmEnable = mRawData[16]; - mInsulinActionType = mRawData[17]; - mLowReservoirWarnType = mRawData[18]; - mLowReservoirWarnPoint = mRawData[19]; - mKeypadLockStatus = mRawData[20]; - return true; - } - public String explain() { - String rval = ""; - // write out a string describing the current contents - rval += String.format("Auto-Off Duration (hours): %d\n",mAutoOffDuration_hours); - rval += String.format("Alarm (Volume: %d, Mode: %d)\n",mAlarmVolume,mAlarmMode); - rval += String.format("Audio BolusNormalPumpEvent (enabled=%s, size=%g)\n",mAudioBolusEnable,mAudioBolusSize); - rval += String.format("Variable BolusNormalPumpEvent Enable: %s\n", mVariableBolusEnable); - rval += String.format("Max BolusNormalPumpEvent: %g\n",mMaxBolus); - rval += String.format("Max Basal: %g\n",mMaxBasal); - rval += String.format("Time Format 0x%02X\n", mTimeFormat); - rval += String.format("Insulin Concentration %d%%\n",mInsulinConcentration); - rval += String.format("Patterns Enabled: %s\n",mPatternsEnabled); - rval += String.format("Selected Pattern: %d\n",mSelectedPattern); - rval += String.format("RF Enabled: %s\n",mRFEnable); - rval += String.format("Block Enabled: %s\n",mBlockEnable); - rval += String.format("Temp Basal Type: %s\n",(mTempBasalType == 1)?"Percent":"Units/Hr"); - if (mTempBasalType == 1) { - rval += String.format("Temp Basal Rate: %d%%\n",mTempBasalRate); - } else { - rval += String.format("Temp Basal Rate: %d U/h\n",mTempBasalRate); - } - rval += String.format("Paradigm Enabled: %s\n", mParadigmEnable); - rval += String.format("Insulin Action Type: 0x%02X\n",mInsulinActionType); - rval += String.format("Low Reservoir Warn Type: 0x%02X\n",mLowReservoirWarnType); - rval += String.format("Low Reservoir Warn Point: 0x%02X\n",mLowReservoirWarnPoint); - rval += String.format("Keypad Lock Status: 0x%02X\n",mKeypadLockStatus); - return rval; - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/TempBasalPair.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/TempBasalPair.java deleted file mode 100644 index 553a1f3309..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/TempBasalPair.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData; - -/** - * Created by geoff on 5/29/15. - * - * Just need a class to keep the pair together, for parcel transport. - */ -@Deprecated -public class TempBasalPair { - private double mInsulinRate = 0.0; - private int mDurationMinutes = 0; - private boolean mIsPercent = false; - - public double getInsulinRate() { - return mInsulinRate; - } - - public void setInsulinRate(double insulinRate) { - this.mInsulinRate = insulinRate; - } - - public int getDurationMinutes() { - return mDurationMinutes; - } - - public void setDurationMinutes(int durationMinutes) { - this.mDurationMinutes = durationMinutes; - } - - public boolean isPercent() { - return mIsPercent; - } - - public void setIsPercent(boolean yesIsPercent) { - this.mIsPercent = yesIsPercent; - } - - public TempBasalPair() { } - - public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) { - mInsulinRate = insulinRate; - mIsPercent = isPercent; - mDurationMinutes = durationMinutes; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmClockReminderPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmClockReminderPumpEvent.java deleted file mode 100644 index fde5a4ea46..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmClockReminderPumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/11/16. - */ -public class AlarmClockReminderPumpEvent extends TimeStampedRecord { - public AlarmClockReminderPumpEvent() {}; - - @Override - public String getShortTypeName() { - return "Alarm Reminder"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmSensorPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmSensorPumpEvent.java deleted file mode 100644 index 2c313b966a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/AlarmSensorPumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class AlarmSensorPumpEvent extends TimeStampedRecord { - public AlarmSensorPumpEvent() {} - - @Override - public int getLength() { return 8; } - - @Override - public String getShortTypeName() { - return "Alarm Sensor"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BGReceivedPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BGReceivedPumpEvent.java deleted file mode 100644 index 1e944c2cc4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BGReceivedPumpEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.util.ByteUtil; - -public class BGReceivedPumpEvent extends TimeStampedRecord { - private int amount = 0; - private byte[] meter = new byte[3]; - - public BGReceivedPumpEvent() { - } - - @Override - public int getLength() { return 10; } - - @Override - public String getShortTypeName() { - return "BG Received"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!super.simpleParse(data,2)) { - return false; - } - amount = (asUINT8(data[1]) << 3) + (asUINT8(data[4])>>5); - meter = ByteUtil.substring(data,7,3); - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - amount = in.getInt("amount"); - meter = in.getByteArray("meter"); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putInt("amount",amount); - in.putByteArray("meter",meter); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BasalProfileStart.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BasalProfileStart.java deleted file mode 100644 index 9322d259c9..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BasalProfileStart.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class BasalProfileStart extends TimeStampedRecord { - private static final String TAG = "BasalProfileStart"; - private int offset = 0; - private double rate = 0.0; - private int profileIndex = 0; - - public BasalProfileStart() { } - - @Override - public int getLength() { return 10; } - - @Override - public String getShortTypeName() { - return "Basal Profile Start"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - - profileIndex = asUINT8(data[1]); - offset = asUINT8(data[7]) * 30 * 1000 * 60; - rate = (double)(asUINT8(data[8])) / 40.0; - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - offset = in.getInt("offset"); - rate = in.getDouble("rate"); - profileIndex = in.getInt("profileIndex"); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putInt("offset",offset); - in.putDouble("rate",rate); - in.putInt("profileIndex",profileIndex); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BatteryPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BatteryPumpEvent.java deleted file mode 100644 index 714f72b059..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BatteryPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class BatteryPumpEvent extends TimeStampedRecord { - public BatteryPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Battery"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusNormalPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusNormalPumpEvent.java deleted file mode 100644 index 32768b3ebf..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusNormalPumpEvent.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; - -public class BolusNormalPumpEvent extends TimeStampedRecord { - private final static String TAG = "BolusNormalPumpEvent"; - - private double programmedAmount = 0.0; - private double deliveredAmount = 0.0; - private int duration = 0; - private double unabsorbedInsulinTotal = 0.0; - private String bolusType = "Unset"; - - public BolusNormalPumpEvent() { - } - - @Override - public int getLength() { return PumpModel.isLargerFormat(model) ? 13 : 9; } - - @Override - public String getShortTypeName() { - return "Normal Bolus"; - } - - private double insulinDecode(int a, int b) { - return ((a << 8) + b) / 40.0; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (getLength() > data.length) { - return false; - } - if (PumpModel.isLargerFormat(model)) { - programmedAmount = insulinDecode(asUINT8(data[1]),asUINT8(data[2])); - deliveredAmount = insulinDecode(asUINT8(data[3]),asUINT8(data[4])); - unabsorbedInsulinTotal = insulinDecode(asUINT8(data[5]),asUINT8(data[6])); - duration = asUINT8(data[7]) * 30; - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, 8)); - } catch (org.joda.time.IllegalFieldValueException e) { - return false; - } - } else { - programmedAmount = asUINT8(data[1]) / 10.0f; - deliveredAmount = asUINT8(data[2]) / 10.0f; - duration = asUINT8(data[3]) * 30; - unabsorbedInsulinTotal = 0; - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data,4)); - } catch (org.joda.time.IllegalFieldValueException e) { - return false; - } - - } - - bolusType = (duration > 0) ? "square" : "normal"; - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - programmedAmount = in.getDouble("programmedAmount",0.0); - deliveredAmount = in.getDouble("deliveredAmount",0.0); - duration = in.getInt("duration",0); - unabsorbedInsulinTotal = in.getDouble("unabsorbedInsulinTotal",0.0); - bolusType = in.getString("bolusType","Unset"); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putDouble("programmedAmount",programmedAmount); - in.putDouble("deliveredAmount",deliveredAmount); - in.putInt("duration",duration); - in.putDouble("unabsorbedInsulinTotal",unabsorbedInsulinTotal); - in.putString("bolusType",bolusType); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusWizardBolusEstimatePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusWizardBolusEstimatePumpEvent.java deleted file mode 100644 index ffd628f204..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/BolusWizardBolusEstimatePumpEvent.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { - private final static String TAG = "BolusWizardBolusEstimatePumpEvent"; - - private int carbohydrates; - private int bloodGlucose; - private double foodEstimate; - private double correctionEstimate; - private double bolusEstimate; - private double unabsorbedInsulinTotal; - private int bgTargetLow; - private int bgTargetHigh; - private int insulinSensitivity; - private double carbRatio; - - public BolusWizardBolusEstimatePumpEvent() { - correctionEstimate = (double)0.0; - bloodGlucose = 0; - carbohydrates = 0; - carbRatio = 0.0; - insulinSensitivity = 0; - bgTargetLow = 0; - bgTargetHigh = 0; - bolusEstimate = 0.0; - foodEstimate = 0.0; - unabsorbedInsulinTotal = 0.0; - } - - @Override - public int getLength() { return PumpModel.isLargerFormat(model) ? 22 : 20;} - - @Override - public String getShortTypeName() { - return "Bolus Wizard Est."; - } - - @Override - public boolean readFromBundle(Bundle in) { - carbohydrates = in.getInt("carbohydrates",0); - bloodGlucose = in.getInt("bloodGlucose",0); - foodEstimate = in.getDouble("foodEstimate",0); - correctionEstimate = in.getDouble("correctionEstimate",0); - bolusEstimate = in.getDouble("bolusEstimate",0); - unabsorbedInsulinTotal = in.getDouble("unabsorbedInsulinTotal",0); - bgTargetLow = in.getInt("bgTargetLow",0); - bgTargetHigh = in.getInt("bgTargetHigh",0); - insulinSensitivity = in.getInt("insulinSensitivity",0); - carbRatio = in.getDouble("carbRatio",0); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putInt("carbohydrates",carbohydrates); - in.putInt("bloodGlucose",bloodGlucose); - in.putDouble("foodEstimate",foodEstimate); - in.putDouble("correctionEstimate",correctionEstimate); - in.putDouble("bolusEstimate",bolusEstimate); - in.putDouble("unabsorbedInsulinTotal",unabsorbedInsulinTotal); - in.putInt("bgTargetLow",bgTargetLow); - in.putInt("bgTargetHigh",bgTargetHigh); - in.putInt("insulinSensitivity",insulinSensitivity); - in.putDouble("carbRatio",carbRatio); - } - - public double getCorrectionEstimate() { return correctionEstimate; } - public long getBG() { return bloodGlucose; } - public int getCarbohydrates() { return carbohydrates; } - public double getICRatio() { return carbRatio; } - public int getInsulinSensitivity() { return insulinSensitivity; } - public int getBgTargetLow() { return bgTargetLow; } - public int getBgTargetHigh() { return bgTargetHigh; } - public double getBolusEstimate() { return bolusEstimate; } - public double getFoodEstimate() { return foodEstimate; } - public double getUnabsorbedInsulinTotal() { return unabsorbedInsulinTotal; } - - private double insulinDecode(int a, int b) { - return ((a << 8) + b) / 40.0; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - if (PumpModel.isLargerFormat(model)) { - carbohydrates = (asUINT8(data[8]) & 0x0c << 6) + asUINT8(data[7]); - bloodGlucose = (asUINT8(data[8]) & 0x03 << 8) + asUINT8(data[1]); - foodEstimate = insulinDecode(asUINT8(data[14]), asUINT8(data[15])); - correctionEstimate = (double)((asUINT8(data[16])& 0b111000) << 5 + asUINT8(data[13]))/40.0; - bolusEstimate = insulinDecode(asUINT8(data[19]), asUINT8(data[20])); - unabsorbedInsulinTotal = insulinDecode(asUINT8(data[17]),asUINT8(data[18])); - bgTargetLow = asUINT8(data[12]); - bgTargetHigh = asUINT8(data[21]); - insulinSensitivity = asUINT8(data[11]); - carbRatio = (double)(((asUINT8(data[9]) & 0x07) << 8) + asUINT8(data[10]))/40.0; - } else { - carbohydrates = asUINT8(data[7]); - bloodGlucose = ((asUINT8(data[8]) & 0x03) << 8) + asUINT8(data[1]); - foodEstimate = (double)(asUINT8(data[13]))/10.0; - correctionEstimate = (double)((asUINT8(data[14])<<8) + asUINT8(data[12])) / 10.0; - bolusEstimate = (double)(asUINT8(data[18]))/10.0; - unabsorbedInsulinTotal = (double)(asUINT8(data[16])) / 10.0; - bgTargetLow = asUINT8(data[11]); - bgTargetHigh = asUINT8(data[19]); - insulinSensitivity = asUINT8(data[10]); - carbRatio = (double)asUINT8(data[9]); - } - - return true; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/CalBgForPhPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/CalBgForPhPumpEvent.java deleted file mode 100644 index 1f18c26c6d..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/CalBgForPhPumpEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class CalBgForPhPumpEvent extends TimeStampedRecord { - private int amount = 0; - - public CalBgForPhPumpEvent() { - } - - @Override - public String getShortTypeName() { - return "Cal Bg For Ph"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - amount = ((asUINT8(data[6]) & 0x80) << 1) + asUINT8(data[1]); - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - amount = in.getInt("amount",0); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putInt("amount",amount); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmClockEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmClockEnablePumpEvent.java deleted file mode 100644 index e7a20ae425..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmClockEnablePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeAlarmClockEnablePumpEvent extends TimeStampedRecord { - public ChangeAlarmClockEnablePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Alarm Clock Enable"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmNotifyModePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmNotifyModePumpEvent.java deleted file mode 100644 index a1ba91e27e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAlarmNotifyModePumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class ChangeAlarmNotifyModePumpEvent extends TimeStampedRecord { - public ChangeAlarmNotifyModePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Alarm Notify Mode"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAudioBolusPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAudioBolusPumpEvent.java deleted file mode 100644 index 271dc3ef15..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeAudioBolusPumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeAudioBolusPumpEvent extends TimeStampedRecord { - public ChangeAudioBolusPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Audio Bolus"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBGReminderEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBGReminderEnablePumpEvent.java deleted file mode 100644 index 35fad6322c..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBGReminderEnablePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeBGReminderEnablePumpEvent extends TimeStampedRecord { - public ChangeBGReminderEnablePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch BG Rmndr Enable"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePatternPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePatternPumpEvent.java deleted file mode 100644 index a145d27d1c..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePatternPumpEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeBasalProfilePatternPumpEvent extends TimeStampedRecord { - public ChangeBasalProfilePatternPumpEvent() {} - - @Override - public int getLength() { - return 152; - } - - @Override - public String getShortTypeName() { - return "Ch Basal Prof Pat"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePumpEvent.java deleted file mode 100644 index c653ac0cfd..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBasalProfilePumpEvent.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class ChangeBasalProfilePumpEvent extends TimeStampedRecord { - public ChangeBasalProfilePumpEvent() { - } - - @Override - public int getLength() { return 152; } - - @Override - public String getShortTypeName() { - return "Ch Basal Profile"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderEnablePumpEvent.java deleted file mode 100644 index 45bc0b2327..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderEnablePumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeBolusReminderEnablePumpEvent extends TimeStampedRecord { - public ChangeBolusReminderEnablePumpEvent() {} - - @Override - public int getLength() { return 9; } - - @Override - public String getShortTypeName() { - return "Ch Bolus Rmndr Enable"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderTimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderTimePumpEvent.java deleted file mode 100644 index 1f9a8d6d57..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusReminderTimePumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeBolusReminderTimePumpEvent extends TimeStampedRecord { - public ChangeBolusReminderTimePumpEvent(){} - - @Override - public String getShortTypeName() { - return "Ch Bolus Rmndr Time"; - } - - @Override - public int getLength() { return 9; } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusScrollStepSizePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusScrollStepSizePumpEvent.java deleted file mode 100644 index 90ac2477cf..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusScrollStepSizePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeBolusScrollStepSizePumpEvent extends TimeStampedRecord { - public ChangeBolusScrollStepSizePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Bolus Scroll SS"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusWizardSetupPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusWizardSetupPumpEvent.java deleted file mode 100644 index e602421c0f..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeBolusWizardSetupPumpEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class ChangeBolusWizardSetupPumpEvent extends TimeStampedRecord { - - public ChangeBolusWizardSetupPumpEvent() { - - } - - @Override - public int getLength() { - return 144; - } - - @Override - public String getShortTypeName() { - return "Ch Bolus Wizard Setup"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCaptureEventEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCaptureEventEnablePumpEvent.java deleted file mode 100644 index 32cf7094df..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCaptureEventEnablePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeCaptureEventEnablePumpEvent extends TimeStampedRecord { - public ChangeCaptureEventEnablePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Capture Event Ena"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCarbUnitsPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCarbUnitsPumpEvent.java deleted file mode 100644 index b4c64c25f6..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeCarbUnitsPumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeCarbUnitsPumpEvent extends TimeStampedRecord { - public ChangeCarbUnitsPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Carb Units"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeChildBlockEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeChildBlockEnablePumpEvent.java deleted file mode 100644 index 21da1c37c1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeChildBlockEnablePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeChildBlockEnablePumpEvent extends TimeStampedRecord { - public ChangeChildBlockEnablePumpEvent(){} - - @Override - public String getShortTypeName() { - return "Ch Child Block Ena"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeMaxBolusPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeMaxBolusPumpEvent.java deleted file mode 100644 index 9c9904f187..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeMaxBolusPumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeMaxBolusPumpEvent extends TimeStampedRecord { - public ChangeMaxBolusPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Max Bolux"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeOtherDeviceIDPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeOtherDeviceIDPumpEvent.java deleted file mode 100644 index 36d3230711..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeOtherDeviceIDPumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class ChangeOtherDeviceIDPumpEvent extends TimeStampedRecord { - - public ChangeOtherDeviceIDPumpEvent() { - } - - @Override - public int getLength() { return 37; } - - @Override - public String getShortTypeName() { - return "Ch Other Dev ID"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeReservoirWarningTimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeReservoirWarningTimePumpEvent.java deleted file mode 100644 index 67632c2e32..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeReservoirWarningTimePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeReservoirWarningTimePumpEvent extends TimeStampedRecord { - public ChangeReservoirWarningTimePumpEvent(){} - - @Override - public String getShortTypeName() { - return "Ch Res Warn Time"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorRateOfChangeAlertSetupPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorRateOfChangeAlertSetupPumpEvent.java deleted file mode 100644 index da6cf942b9..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorRateOfChangeAlertSetupPumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeSensorRateOfChangeAlertSetupPumpEvent extends TimeStampedRecord { - public ChangeSensorRateOfChangeAlertSetupPumpEvent() {} - - @Override - public int getLength() { return 12; } - - @Override - public String getShortTypeName() { - return "Ch Sensor ROC Alert"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorSetup2PumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorSetup2PumpEvent.java deleted file mode 100644 index 817f15be54..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeSensorSetup2PumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeSensorSetup2PumpEvent extends TimeStampedRecord { - public ChangeSensorSetup2PumpEvent() {} - - @Override - public int getLength() { return 37; } - - @Override - public String getShortTypeName() { - return "Ch Sensor Setup2"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTempBasalTypePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTempBasalTypePumpEvent.java deleted file mode 100644 index 0b932b5df5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTempBasalTypePumpEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeTempBasalTypePumpEvent extends TimeStampedRecord { - private boolean isPercent=false; // either absolute or percent - public ChangeTempBasalTypePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Ch Temp Basal Type"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - if (asUINT8(data[1])==1) { - isPercent = true; - } else { - isPercent = false; - } - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - isPercent = in.getBoolean("isPercent",false); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - in.putBoolean("isPercent",isPercent); - super.writeToBundle(in); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimeFormatPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimeFormatPumpEvent.java deleted file mode 100644 index 199793761b..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimeFormatPumpEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class ChangeTimeFormatPumpEvent extends TimeStampedRecord { - public ChangeTimeFormatPumpEvent() { - } - - @Override - public String getShortTypeName() { - return "Ch Time Format"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimePumpEvent.java deleted file mode 100644 index ca65f566f1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeTimePumpEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class ChangeTimePumpEvent extends TimeStampedRecord { - public ChangeTimePumpEvent() { - - } - - @Override - public int getLength() { return 14; } - - @Override - public String getShortTypeName() { - return "Change Time"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeVariableBolusPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeVariableBolusPumpEvent.java deleted file mode 100644 index d778e87dbb..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeVariableBolusPumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeVariableBolusPumpEvent extends TimeStampedRecord { - public ChangeVariableBolusPumpEvent(){} - - @Override - public String getShortTypeName() { - return "Ch Var. Bolus"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogEnablePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogEnablePumpEvent.java deleted file mode 100644 index 70bc7a2ca2..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogEnablePumpEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeWatchdogEnablePumpEvent extends TimeStampedRecord { - public ChangeWatchdogEnablePumpEvent(){} - - @Override - public String getShortTypeName() { - return "Ch Watchdog Enable"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogMarriageProfilePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogMarriageProfilePumpEvent.java deleted file mode 100644 index f9f0f00b90..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ChangeWatchdogMarriageProfilePumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class ChangeWatchdogMarriageProfilePumpEvent extends TimeStampedRecord { - public ChangeWatchdogMarriageProfilePumpEvent() {} - - @Override - public int getLength() { return 12; } - - @Override - public String getShortTypeName() { - return "Ch WD Marriage"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ClearAlarmPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ClearAlarmPumpEvent.java deleted file mode 100644 index 3bf663ac44..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ClearAlarmPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class ClearAlarmPumpEvent extends TimeStampedRecord { - public ClearAlarmPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Clear Alarm"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteAlarmClockTimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteAlarmClockTimePumpEvent.java deleted file mode 100644 index 0f726986b4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteAlarmClockTimePumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class DeleteAlarmClockTimePumpEvent extends TimeStampedRecord { - public DeleteAlarmClockTimePumpEvent() {} - - @Override - public int getLength() { return 14; } - - @Override - public String getShortTypeName() { - return "Del Alarm Clock Time"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteBolusReminderTimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteBolusReminderTimePumpEvent.java deleted file mode 100644 index 787923f870..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteBolusReminderTimePumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class DeleteBolusReminderTimePumpEvent extends TimeStampedRecord { - public DeleteBolusReminderTimePumpEvent() {} - - @Override - public int getLength() { return 9; } - - @Override - public String getShortTypeName() { - return "Del Bolus Rmndr Time"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteOtherDeviceIDPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteOtherDeviceIDPumpEvent.java deleted file mode 100644 index 98a069c139..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/DeleteOtherDeviceIDPumpEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class DeleteOtherDeviceIDPumpEvent extends TimeStampedRecord { - public DeleteOtherDeviceIDPumpEvent(){} - - @Override - public int getLength() { return 12; } - - @Override - public String getShortTypeName() { - return "Del Other Dev ID"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/EnableDisableRemotePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/EnableDisableRemotePumpEvent.java deleted file mode 100644 index 65ef42a33e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/EnableDisableRemotePumpEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class EnableDisableRemotePumpEvent extends TimeStampedRecord { - public EnableDisableRemotePumpEvent() { - } - - @Override - public int getLength() { return 21; } - - @Override - public String getShortTypeName() { - return "Toggle Remote"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/InsulinMarkerEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/InsulinMarkerEvent.java deleted file mode 100644 index 41af3b4b4e..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/InsulinMarkerEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -/** - * Created by geoff on 7/16/16. - */ -public class InsulinMarkerEvent extends TimeStampedRecord { - public InsulinMarkerEvent() {} - - @Override - public int getLength() { - return 8; - } - - /* - Darrell Wright: - it is a manual entry of a bolus that the pump didn't deliver, so opcode, timestamp and at least a number to represent the units of insulin - */ - - @Override - public String getShortTypeName() { - return "UnknownInsulin"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryExerciseMarkerPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryExerciseMarkerPumpEvent.java deleted file mode 100644 index 1e2994fbe6..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryExerciseMarkerPumpEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -/** - * Created by geoff on 6/5/16. - */ -public class JournalEntryExerciseMarkerPumpEvent extends TimeStampedRecord { - public JournalEntryExerciseMarkerPumpEvent(){} - - @Override - public int getLength() { return 8; } - - @Override - public String getShortTypeName() { - return "Exercise Marker"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowBatteryPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowBatteryPumpEvent.java deleted file mode 100644 index 85355d203a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowBatteryPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class JournalEntryPumpLowBatteryPumpEvent extends TimeStampedRecord { - public JournalEntryPumpLowBatteryPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Low Battery"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowReservoirPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowReservoirPumpEvent.java deleted file mode 100644 index bc7c5f28c4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/JournalEntryPumpLowReservoirPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class JournalEntryPumpLowReservoirPumpEvent extends TimeStampedRecord { - public JournalEntryPumpLowReservoirPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Low Reservoir"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Model522ResultTotalsPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Model522ResultTotalsPumpEvent.java deleted file mode 100644 index c0cf926a22..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Model522ResultTotalsPumpEvent.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class Model522ResultTotalsPumpEvent extends TimeStampedRecord { - public Model522ResultTotalsPumpEvent() {} - - public int getDatestampOffset() { return 1; } - - @Override - public int getLength() { return 44; } - - @Override - public String getShortTypeName() { - return "M522 Result Totals"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/NewTimeSet.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/NewTimeSet.java deleted file mode 100644 index 8a5832973d..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/NewTimeSet.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -// This event existed as 0x18 in Roundtrip and early Decocare, -// but I don't see a corresponding event in RileyLink_ios. -public class NewTimeSet extends TimeStampedRecord { - public NewTimeSet() { - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - return false; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PrimePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PrimePumpEvent.java deleted file mode 100644 index b0c26a10a7..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PrimePumpEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class PrimePumpEvent extends TimeStampedRecord { - private double amount=0.0; - private double programmedAmount=0.0; - private String primeType = "unknown"; - - public PrimePumpEvent() { - } - - @Override - public int getLength() { return 10; } - - @Override - public String getShortTypeName() { - return "Prime Pump"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,5)) { - return false; - } - amount = (double)(asUINT8(data[4])<<2) / 40.0; - programmedAmount = (double)(asUINT8(data[2])<<2) / 40.0; - primeType = programmedAmount == 0 ? "manual" : "fixed"; - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - amount = in.getDouble("amount",0.0); - programmedAmount = in.getDouble("programmedAmount",0); - primeType = in.getString("primeType","unknown"); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - in.putDouble("amount",amount); - in.putDouble("programmedAmount",programmedAmount); - in.putString("primeType",primeType); - super.writeToBundle(in); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PumpAlarmPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PumpAlarmPumpEvent.java deleted file mode 100644 index 7081dec177..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/PumpAlarmPumpEvent.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class PumpAlarmPumpEvent extends TimeStampedRecord { - private int rawtype = 0; - public PumpAlarmPumpEvent() { - } - - @Override - public int getLength() { return 9; } - - @Override - public String getShortTypeName() { - return "Pump Alarm"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,4)) { - return false; - } - rawtype = asUINT8(data[1]); - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - rawtype = in.getInt("rawtype",0); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - in.putInt("rawtype",rawtype); - super.writeToBundle(in); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Record.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Record.java deleted file mode 100644 index 6992ddfae8..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Record.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; - -abstract public class Record { - private static final String TAG = "Record"; - protected PumpModel model; - protected byte recordOp; - //protected int length; - protected int foundAtOffset; - protected byte[] rawbytes = new byte[0]; - //protected String recordTypeName = this.getClass().getSimpleName(); - - public String getRecordTypeName() { return this.getClass().getSimpleName(); } - public String getShortTypeName() { - return this.getClass().getSimpleName(); - } - public void setPumpModel(PumpModel model) { this.model = model; } - public int getFoundAtOffset() { return foundAtOffset; } - - public Record() { - - } - - public boolean parseWithOffset(byte[] data, PumpModel model, int foundAtOffset) { - // keep track of where the record was found for later analysis - this.foundAtOffset = foundAtOffset; - if (data == null) { - return false; - } - if (data.length < 1) { - return false; - } - recordOp = data[0]; - boolean didParse = parseFrom(data,model); - if (didParse) { - captureRawBytes(data); - } - return didParse; - } - - public void captureRawBytes(byte[] data) { - this.rawbytes = new byte[getLength()]; - System.arraycopy(data, 0, this.rawbytes,0,getLength()-1); - } - - public boolean parseFrom(byte[] data, PumpModel model) { - return true; - } - - public PumpTimeStamp getTimestamp() { - return new PumpTimeStamp(); - } - - public int getLength() { - return 1; - } - - public byte getRecordOp() { - return recordOp; - } - - protected static int asUINT8(byte b) { - return (b < 0) ? b + 256 : b; - } - - public Bundle dictionaryRepresentation() { - Bundle rval = new Bundle(); - writeToBundle(rval); - return rval; - } - - public boolean readFromBundle(Bundle in) { - // length is determined at instantiation - // record type name is "static" - // opcode has already been read. - return true; - } - - public void writeToBundle(Bundle in) { - in.putInt("length",getLength()); - in.putInt("foundAtOffset",foundAtOffset); - in.putInt("_opcode",recordOp); - in.putString("_type", getRecordTypeName()); - in.putString("_stype", getShortTypeName()); - in.putByteArray("rawbytes",rawbytes); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RecordTypeEnum.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RecordTypeEnum.java deleted file mode 100644 index 12a031eda4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RecordTypeEnum.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -/** - * Created by geoff on 5/28/15. - */ -public enum RecordTypeEnum { - RECORD_TYPE_NULL((byte)0x00, null), - RECORD_TYPE_BOLUSNORMAL((byte)0x01,BolusNormalPumpEvent.class), - RECORD_TYPE_PRIME((byte)0x03,PrimePumpEvent.class), - RECORD_TYPE_ALARMPUMP((byte)0x06,PumpAlarmPumpEvent.class), - RECORD_TYPE_RESULTDAILYTOTAL((byte)0x07,ResultDailyTotalPumpEvent.class), - RECORD_TYPE_CHANGEBASALPROFILEPATTERN((byte)0x08,ChangeBasalProfilePatternPumpEvent.class), - RECORD_TYPE_CHANGEBASALPROFILE((byte)0x09,ChangeBasalProfilePumpEvent.class), - RECORD_TYPE_CALBGFORPH((byte)0x0A,CalBgForPhPumpEvent.class), - RECORD_TYPE_ALARMSENSOR((byte)0x0B,AlarmSensorPumpEvent.class), - RECORD_TYPE_CLEARALARM((byte)0x0C,ClearAlarmPumpEvent.class), - //RECORD_TYPE_SELECTBASALPROFILE((byte)0x14,SelectBasalProfile.class), - RECORD_TYPE_TEMPBASALDURATION((byte)0x16,TempBasalDurationPumpEvent.class), - RECORD_TYPE_CHANGETIME((byte)0x17,ChangeTimePumpEvent.class), - RECORD_TYPE_NEWTIMESET((byte)0x18,NewTimeSet.class), - RECORD_TYPE_JournalEntryPumpLowBattery((byte)0x19,JournalEntryPumpLowBatteryPumpEvent.class), - RECORD_TYPE_BATTERY((byte)0x1A,BatteryPumpEvent.class), - RECORD_TYPE_PUMPSUSPENDED((byte)0x1E,SuspendPumpEvent.class), - RECORD_TYPE_PUMPRESUMED((byte)0x1F,ResumePumpEvent.class), - RECORD_TYPE_REWIND((byte)0x21,RewindPumpEvent.class), - RECORD_TYPE_CHANGECHILDBLOCKENABLE((byte)0x23,ChangeChildBlockEnablePumpEvent.class), - RECORD_TYPE_CHANGEMAXBOLUS((byte)0x24,ChangeMaxBolusPumpEvent.class), - RECORD_TYPE_ENABLEDISABLEREMOTE((byte)0x26,EnableDisableRemotePumpEvent.class), - RECORD_TYPE_TEMPBASALRATE((byte)0x33,TempBasalRatePumpEvent.class), - RECORD_TYPE_LOWRESERVOIR((byte)0x34,JournalEntryPumpLowReservoirPumpEvent.class), - RECORD_TYPE_AlarmClockReminder((byte)0x35,AlarmClockReminderPumpEvent.class), - RECORD_TYPE_BGRECEIVED((byte)0x3F,BGReceivedPumpEvent.class), - RECORD_TYPE_JournalEntryExerciseMarker((byte)0x41,JournalEntryExerciseMarkerPumpEvent.class), - RECORD_TYPE_Unknown7Byte_1((byte)0x42,Unknown7ByteEvent1.class), - RECORD_TYPE_InsulinMarker((byte)0x43,InsulinMarkerEvent.class), - RECORD_TYPE_CHANGESENSORSETUP2((byte)0x50,ChangeSensorSetup2PumpEvent.class), - RECORD_TYPE_ChangeSensorRateOfChangeAlertSetup((byte)0x56,ChangeSensorRateOfChangeAlertSetupPumpEvent.class), - RECORD_TYPE_ChangeBolusScrollStepSize((byte)0x57,ChangeBolusScrollStepSizePumpEvent.class), - RECORD_TYPE_ChangeBolusWizardSetup((byte)0x5A,ChangeBolusWizardSetupPumpEvent.class), - RECORD_TYPE_BolusWizardBolusEstimate((byte)0x5B,BolusWizardBolusEstimatePumpEvent.class), - RECORD_TYPE_UNABSORBEDINSULIN((byte)0x5C,UnabsorbedInsulin.class), - RECORD_TYPE_CHANGEVARIABLEBOLUS((byte)0x5e,ChangeVariableBolusPumpEvent.class), - RECORD_TYPE_CHANGEAUDIOBOLUS((byte)0x5f,ChangeAudioBolusPumpEvent.class), - RECORD_TYPE_ChangeBGReminderEnable((byte)0x60,ChangeBGReminderEnablePumpEvent.class), - RECORD_TYPE_ChangeAlarmClockEnable((byte)0x61,ChangeAlarmClockEnablePumpEvent.class), - RECORD_TYPE_ChangeTempBasalType((byte)0x62,ChangeTempBasalTypePumpEvent.class), - RECORD_TYPE_ChangeAlarmNotifyMode((byte)0x63,ChangeAlarmNotifyModePumpEvent.class), - RECORD_TYPE_ChangeTimeFormat((byte)0x64,ChangeTimeFormatPumpEvent.class), - RECORD_TYPE_ChangeReservoirWarningTime((byte)0x65,ChangeReservoirWarningTimePumpEvent.class), - RECORD_TYPE_ChangeBolusReminderEnable((byte)0x66,ChangeBolusReminderEnablePumpEvent.class), - RECORD_TYPE_ChangeBolusReminderTime((byte)0x67,ChangeBolusReminderTimePumpEvent.class), - RECORD_TYPE_DeleteBolusReminderTime((byte)0x68,DeleteBolusReminderTimePumpEvent.class), - RECORD_TYPE_DeleteAlarmClockTime((byte)0x6a,DeleteAlarmClockTimePumpEvent.class), - RECORD_TYPE_MODEL522RESULTTOTALS((byte)0x6D,Model522ResultTotalsPumpEvent.class), - RECORD_TYPE_SARA6E((byte)0x6E,Sara6EPumpEvent.class), - RECORD_TYPE_ChangeCarbUnits((byte)0x6f,ChangeCarbUnitsPumpEvent.class), - RECORD_TYPE_BASALPROFILESTART((byte)0x7B,BasalProfileStart.class), - RECORD_TYPE_ChangeWatchdogEnable((byte)0x7c,ChangeWatchdogEnablePumpEvent.class), - RECORD_TYPE_CHANGEOTHERDEVICEID((byte)0x7d,ChangeOtherDeviceIDPumpEvent.class), - RECORD_TYPE_ChangeWatchdogMarriageProfile((byte)0x81,ChangeWatchdogMarriageProfilePumpEvent.class), - RECORD_TYPE_DeleteOtherDeviceID((byte)0x82,DeleteOtherDeviceIDPumpEvent.class), - RECORD_TYPE_ChangeCaptureEventEnable((byte)0x83,ChangeCaptureEventEnablePumpEvent.class); - - - private byte opcode; - private Class mRecordClass; - - public byte opcode() { - return opcode; - } - public Class recordClass() { - return mRecordClass; - } - RecordTypeEnum(byte b,Class c) { - opcode = b; - mRecordClass = c; - } - public static RecordTypeEnum fromByte(byte b) { - for(RecordTypeEnum en : RecordTypeEnum.values()) { - if (en.opcode() == b) { - return en; - } - } - return RECORD_TYPE_NULL; - } - - private static final String TAG = "RecordTypeEnum"; - public T getRecordClassInstance(PumpModel model) { - Constructor ctor; - T record = null; - try { - Class c = recordClass(); - if (c!=null) { - ctor = recordClass().getConstructor(); - if (ctor != null) { - record = ctor.newInstance(); - record.setPumpModel(model); - } - } - } catch (NoSuchMethodException e) { - // NOTE: these were all OR'd together, but android requires us to separate them. - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return record; - } - - public static T getRecordClassInstance(Bundle bundle, PumpModel model) { - byte opcode = bundle.getByte("_opcode"); - RecordTypeEnum e = RecordTypeEnum.fromByte(opcode); - return e.getRecordClassInstance(model); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResultDailyTotalPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResultDailyTotalPumpEvent.java deleted file mode 100644 index 09c06f5f8f..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResultDailyTotalPumpEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; - -public class ResultDailyTotalPumpEvent extends TimeStampedRecord { - private static final String TAG = "ResultDailyTotalPumpEvent"; - public ResultDailyTotalPumpEvent() { - } - - @Override - public int getDatestampOffset() { return 5; } - - @Override - public int getLength() { return PumpModel.isLargerFormat(model) ? 10 : 7; } - - @Override - protected boolean collectTimeStamp(byte[] data, int offset) { - try { - // This might be a 5 byte date on largerFormat - timestamp = new PumpTimeStamp(TimeFormat.parse2ByteDate(data, offset)); - } catch (org.joda.time.IllegalFieldValueException e) { - return false; - } - return true; - } - - @Override - public String getShortTypeName() { - return "Result Daily Total"; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResumePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResumePumpEvent.java deleted file mode 100644 index df514fdf4a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/ResumePumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class ResumePumpEvent extends TimeStampedRecord { - public ResumePumpEvent() {} - - @Override - public String getShortTypeName() { - return "Resume"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RewindPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RewindPumpEvent.java deleted file mode 100644 index 2ffacbafd5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/RewindPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class RewindPumpEvent extends TimeStampedRecord { - public RewindPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Rewind"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Sara6EPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Sara6EPumpEvent.java deleted file mode 100644 index 712b13437a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/Sara6EPumpEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; - -public class Sara6EPumpEvent extends TimeStampedRecord { - public Sara6EPumpEvent() { - } - - @Override - public int getLength() { - return 52; - } - - @Override - public String getShortTypeName() { - return "Sara6E"; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - // We don't understand this event... - // Minimum 16 characters? date components? - if (16 > data.length) { - return false; - } - try { - timestamp = new PumpTimeStamp(TimeFormat.parse2ByteDate(data,1)); - } catch (org.joda.time.IllegalFieldValueException e) { - return false; - } - return true; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/SuspendPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/SuspendPumpEvent.java deleted file mode 100644 index 355a1c2381..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/SuspendPumpEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -public class SuspendPumpEvent extends TimeStampedRecord { - public SuspendPumpEvent() {} - - @Override - public String getShortTypeName() { - return "Suspend"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalDurationPumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalDurationPumpEvent.java deleted file mode 100644 index 5356cd7815..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalDurationPumpEvent.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class TempBasalDurationPumpEvent extends TimeStampedRecord { - private int durationMinutes = 0; - public TempBasalDurationPumpEvent() { } - - @Override - public String getShortTypeName() { - return "Temp Basal Duration"; - } - - public int getDurationMinutes() { - return durationMinutes; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - durationMinutes = asUINT8(data[1]) * 30; - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - durationMinutes = in.getInt("durationMinutes",0); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putInt("durationMinutes",durationMinutes); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalRatePumpEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalRatePumpEvent.java deleted file mode 100644 index d29a849588..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TempBasalRatePumpEvent.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; - -public class TempBasalRatePumpEvent extends TimeStampedRecord { - private double basalRate = 0.0; // rate in Units/hr - private boolean mIsPercent = false; // The value is either an absolute number or a percentage - - public TempBasalRatePumpEvent() { } - - @Override - public int getLength() { return 8; } - - @Override - public String getShortTypeName() { - return "Temp Basal Rate"; - } - - public double getBasalRate() { return basalRate; } - public boolean isPercent() { return mIsPercent; } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (!simpleParse(data,2)) { - return false; - } - if ((asUINT8(data[7])>>3)==0) { - mIsPercent = false; - basalRate = (double)(asUINT8(data[1])) / 40.0; - } else { - mIsPercent = true; - basalRate = asUINT8(data[1]); - } - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - basalRate = in.getDouble("basalRate",0); - mIsPercent = in.getBoolean("mIsPercent",false); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - in.putDouble("basalRate",basalRate); - in.putBoolean("mIsPercent",mIsPercent); - super.writeToBundle(in); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TimeStampedRecord.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TimeStampedRecord.java deleted file mode 100644 index ea20e18e93..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/TimeStampedRecord.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpTimeStamp; -import com.gxwtech.roundtrip2.RoundtripService.medtronic.TimeFormat; -import com.gxwtech.roundtrip2.util.ByteUtil; - -/* - * Many events in the history only consist of a single opcode and a datestamp. - * This serves to record that a particular event happened at a particular date. - * Many of the subclasses of this class only override the opcode. - */ -abstract public class TimeStampedRecord extends Record { - private final static String TAG = "TimeStampedRecord"; - private final static boolean DEBUG_TIMESTAMPEDRECORD = false; - - @Override - public int getLength() { return 7; } - - public int getDatestampOffset() { return 2; } - - protected PumpTimeStamp timestamp; - - public TimeStampedRecord() { - timestamp = new PumpTimeStamp(); - } - - @Override - public PumpTimeStamp getTimestamp() { - return timestamp; - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - return simpleParse(data,getDatestampOffset()); - } - - // This is useful if there is no data inside, or we don't care about the data. - public boolean simpleParse(byte[] data, int fiveByteDateOffset) { - if (getLength() > data.length) { - return false; - } - if (!collectTimeStamp(data,fiveByteDateOffset)) { - return false; - } - rawbytes = ByteUtil.substring(data,0,getLength()); - return true; - } - - protected boolean collectTimeStamp(byte[] data, int offset) { - try { - timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, offset)); - } catch (org.joda.time.IllegalFieldValueException e) { - return false; - } - return true; - } - - @Override - public boolean readFromBundle(Bundle in) { - String timestampString = in.getString("timestamp"); - timestamp = new PumpTimeStamp(timestampString); - return super.readFromBundle(in); - } - - @Override - public void writeToBundle(Bundle in) { - super.writeToBundle(in); - in.putString("timestamp",timestamp.toString()); - - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/UnabsorbedInsulin.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/UnabsorbedInsulin.java deleted file mode 100644 index 0d90b78449..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpData/records/UnabsorbedInsulin.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.records; - - -import android.os.Bundle; -import android.util.Log; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpModel; -import com.gxwtech.roundtrip2.util.ByteUtil; - -import java.util.ArrayList; - -public class UnabsorbedInsulin extends Record { - private static final String TAG = "UnabsorbedInsulin"; - private int length = 2; - - @Override - public int getLength() { return length; /* this is a variable sized record */} - - @Override - public String getShortTypeName() { - return "Unabsorbed Insulin"; - } - - class UnabsorbedInsulinRecord { - public double amount = 0.0; - public int age = 0; - public UnabsorbedInsulinRecord(double amount, int age) { - this.amount = amount; - this.age = age; - } - } - - ArrayList records = new ArrayList<>(); - - public UnabsorbedInsulin() { - } - - @Override - public boolean parseFrom(byte[] data, PumpModel model) { - if (data.length < 2) { - return false; - } - length = asUINT8(data[1]); - if (length < 2) { - length = 2; - } - if (length > data.length) { - return false; - } - - int numRecords = (asUINT8(data[1]) - 2) / 3; - for (int i=0; i 0) { - this.packetType = new PacketType(rxData[0]); - } - if (rxData.length > 3) { - this.address = ByteUtil.substring(rxData, 1, 3); - } - if (rxData.length > 4) { - this.messageType = new MessageType(rxData[4]); - } - if (rxData.length > 5) { - this.messageBody = MessageType.constructMessageBody(messageType, ByteUtil.substring(rxData, 5, rxData.length - 5)); - } - } - - public byte[] getTxData() { - byte[] rval = ByteUtil.concat(new byte[] {(byte)packetType.value},address); - rval = ByteUtil.concat(rval,(byte)messageType.mtype); - rval = ByteUtil.concat(rval,messageBody.getTxData()); - return rval; - } - - public byte[] getContents() { - return ByteUtil.concat(new byte[] {messageType.mtype}, messageBody.getTxData()); - } - - public boolean isValid() { - if (packetType == null) return false; - if (address == null) return false; - if (messageType == null) return false; - if (messageBody == null) return false; - return true; - } - - public MessageBody getMessageBody() { - return messageBody; - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpModel.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpModel.java deleted file mode 100644 index cbdcc8f7c5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpModel.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic; -// cribbed from: -//package com.nightscout.core.drivers.Medtronic; - -/** - * Created by geoff on 5/13/15. - */ - -public enum PumpModel { - UNSET, - MM508, - MM515, - MM522, - MM523; - public static boolean isLargerFormat(PumpModel model) { - if (model == MM523) { - return true; - } - return false; - } - public static String toString(PumpModel model) { - switch(model) { - case UNSET: - return "UNSET"; - case MM508: - return "508"; - case MM515: - return "515"; - case MM522: - return "522"; - case MM523: - return "523"; - default: - return "(error)"; - } - } - public static PumpModel fromString(String s) { - if ("UNSET".equals(s)) { - return UNSET; - } - if (("508".equals(s)) || ("MM508".equals(s))) { - return MM508; - } - if (("515".equals(s)) || ("MM515".equals(s))) { - return MM515; - } - if (("522".equals(s)) || ("MM522".equals(s))) { - return MM522; - } - if (("523".equals(s)) || ("MM523".equals(s))) { - return MM523; - } - return UNSET; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpTimeStamp.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpTimeStamp.java deleted file mode 100644 index f02fd2b816..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/PumpTimeStamp.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic; - -import org.joda.time.LocalDate; -import org.joda.time.LocalDateTime; - -/** - * Created by geoff on 6/4/16. - * Exists to easily merge 2 byte timestamps and 5 byte timestamps. - */ -public class PumpTimeStamp { - private LocalDateTime localDateTime; - public PumpTimeStamp() { - localDateTime = new LocalDateTime(1973,1,1,1,1); - } - public PumpTimeStamp(String stringRepresentation) { localDateTime.parse(stringRepresentation); } - public PumpTimeStamp(LocalDate localDate) { - try { - localDateTime = new LocalDateTime(localDate); - } catch (IllegalArgumentException e) { - // This should be caught earlier - localDateTime = new LocalDateTime(1973,1,1,1,1); - } - } - public PumpTimeStamp(LocalDateTime localDateTime) { - this.localDateTime = localDateTime; - } - public LocalDateTime getLocalDateTime() { - return localDateTime; - } - @Override - public String toString() { - return getLocalDateTime().toString(); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TempBasalEvent.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TempBasalEvent.java deleted file mode 100644 index 1a1ae3b7c5..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TempBasalEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic; - - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.TempBasalPair; - -import org.joda.time.LocalDateTime; - -/** - * Created by geoff on 6/8/15. - * - * In the pump's history, temp basals are recorded as 1) a TempBasalRatePumpEvent event, - * with a timestamp and a rate, and 2) as a separate TempBasalDurationPumpEvent event, with a timestamp - * and a duration. This is inconvenient for the rest of the software, so this class puts the two - * together as a timestamp, duration, and rate in one package. - * - */ -@Deprecated -public class TempBasalEvent { - public LocalDateTime mTimestamp; - public TempBasalPair mBasalPair; - public TempBasalEvent() { - mTimestamp = new LocalDateTime(); - mBasalPair = new TempBasalPair(); - } - public TempBasalEvent(LocalDateTime timestamp, TempBasalPair pair) { - mTimestamp = timestamp; - mBasalPair = pair; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TimeFormat.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TimeFormat.java deleted file mode 100644 index 5ce44890d0..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripService/medtronic/TimeFormat.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.gxwtech.roundtrip2.RoundtripService.medtronic; - -import android.util.Log; - -import com.gxwtech.roundtrip2.util.ByteUtil; - -import org.joda.time.LocalDate; -import org.joda.time.LocalDateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -/** - * Created by geoff on 6/4/16. - */ -public class TimeFormat { - private static final boolean DEBUG_TIMEFORMAT = false; - private static final String TAG = "TimeFormat"; - public TimeFormat() { } - public static final String standardFormatString = "YYYY-MM-dd HH:mm:ss"; - public static DateTimeFormatter standardFormatter() { - return DateTimeFormat.forPattern(standardFormatString); - } - - public static LocalDate parse2ByteDate(byte[] data, int offset) throws org.joda.time.IllegalFieldValueException { - int low = ByteUtil.asUINT8(data[0 + offset]) & 0x1F; - int mhigh = (ByteUtil.asUINT8(data[0 + offset]) & 0xE0) >> 4; - int mlow = (ByteUtil.asUINT8(data[1 + offset]) & 0x80) >> 7; - int month = mhigh + mlow; - int dayOfMonth = low + 1; - int year = 2000 + (ByteUtil.asUINT8(data[offset + 1]) & 0x7F); - /* - Log.w(TAG, String.format("Attempting to create DateTime from: %04d-%02d-%02d %02d:%02d:%02d", - year + 2000, month, dayOfMonth, hour, minutes, seconds)); - */ -// try { - LocalDate rval = new LocalDate(year, month, dayOfMonth); - return rval; - /* - } catch (org.joda.time.IllegalFieldValueException e) { - Log.e(TAG,"Illegal DateTime field"); - //e.printStackTrace(); - return new LocalDate(1973,3,3); - } - */ - } - - // for relation to old code, replace offset with headerSize - - - public static LocalDateTime parse5ByteDate(byte[] data, int offset) throws org.joda.time.IllegalFieldValueException { - //offset = headerSize; - if (DEBUG_TIMEFORMAT) { - Log.w(TAG, String.format("bytes to parse: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X", - data[offset], data[offset + 1], data[offset + 2], data[offset + 3], data[offset + 4])); - } - int seconds = data[offset] & 0x3F; - int minutes = data[offset + 1] & 0x3F; - int hour = data[offset + 2] & 0x1F; - int dayOfMonth = data[offset + 3] & 0x1F; - // Yes, the month bits are stored in the high bits above seconds and minutes!! - int month = ((data[offset] >> 4) & 0x0c) + ((data[offset + 1] >> 6) & 0x03); - int year = data[offset + 4] & 0x3F; // Assuming this is correct, need to verify. Otherwise this will be a problem in 2016. - /* - Log.w(TAG,String.format("Attempting to create DateTime from: %04d-%02d-%02d %02d:%02d:%02d", - year+2000,month,dayOfMonth,hour,minutes,seconds)); - */ -// try { - LocalDateTime timeStamp = new LocalDateTime(year + 2000, month, dayOfMonth, hour, minutes, seconds); - return timeStamp; - /* - } catch (org.joda.time.IllegalFieldValueException e) { - Log.e(TAG, "Illegal DateTime field"); - //e.printStackTrace(); - return new LocalDateTime(1973,2,2,2,2); - } - */ - } - - - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripServiceClientConnection.java b/app/src/main/java/com/gxwtech/roundtrip2/RoundtripServiceClientConnection.java deleted file mode 100644 index 08cd395160..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/RoundtripServiceClientConnection.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -import com.gxwtech.roundtrip2.ServiceData.ServiceCommand; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - -import org.joda.time.DateTime; -import org.joda.time.Instant; - -/** - * Created by geoff on 6/11/16. - */ -public class RoundtripServiceClientConnection { - private static final String TAG = "RTServiceClient"; - private Context context; - private Messenger mService = null; - private boolean mBound = false; - - public RoundtripServiceClientConnection(Context context) { - this.context = context; - } - - class IncomingHandler extends Handler { - @Override - public void handleMessage(Message msg) { - Bundle bundle = msg.getData(); - Intent intent; - switch (msg.what) { - case RT2Const.IPC.MSG_clientRegistered: - // Service has registered us. Communication lines are open. - mBound = true; - intent = new Intent(RT2Const.local.INTENT_serviceConnected); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); - break; - case RT2Const.IPC.MSG_IPC: - // broadcast contents of message as an intent - ServiceTransport transport = new ServiceTransport(msg.getData()); - Log.d(TAG,"Client received IPC message, bouncing to local: " + transport.describeContentsShort()); - intent = new Intent(transport.getTransportType()); - intent.putExtra(RT2Const.IPC.bundleKey,transport.getMap()); - LocalBroadcastManager.getInstance(context).sendBroadcast(intent); - break; - default: - Log.e(TAG,"handleMessage: unknown 'what' in message: "+msg.what); - super.handleMessage(msg); - } - } - } - - final Messenger mMessenger = new Messenger(new IncomingHandler()); - - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - mService = new Messenger(service); - try { - Message msg = Message.obtain(null,RT2Const.IPC.MSG_registerClient); - msg.replyTo = mMessenger; - mService.send(msg); - } catch (RemoteException e) { - // In this case the service has crashed before we could even - // do anything with it; we can count on soon being - // disconnected (and then reconnected if it can be restarted) - // so there is no need to do anything here. - } - Log.d(TAG,"Sent registration message to service"); - } - - @Override - public void onServiceDisconnected(ComponentName className) { - mService = null; - Log.d(TAG,"Disconnected from service."); - } - }; - - public ServiceConnection getServiceConnection() { - return mConnection; - } - - public void unbind() { - if (mBound) { - if (mService!=null) { - try { - Message msg = Message.obtain(null,RT2Const.IPC.MSG_unregisterClient); - msg.replyTo = mMessenger; - mService.send(msg); - } catch (RemoteException e) { - // Nothing to do if the connection has already crashed. - } - } - mBound = false; - } - } - - public boolean sendServiceCommand(ServiceCommand command) { - if (!mBound) { - Log.e(TAG,"sendServiceCommand: cannot send command -- not yet bound to service"); - return false; - } - - ServiceTransport transport = new ServiceTransport(); - Log.d(TAG,"client sending message: " + transport.describeContentsShort()); - - // can't set sender hashcode -- Service will do that. - transport.setServiceCommand(command); - transport.setTransportType(RT2Const.IPC.MSG_ServiceCommand); - - Message msg = Message.obtain(null, RT2Const.IPC.MSG_IPC, 0, 0); - - msg.setData(transport.getMap()); - msg.replyTo = mMessenger; - try { - mService.send(msg); - } catch (RemoteException e) { - Log.e(TAG,"sendServiceCommand: failed to send message"); - e.printStackTrace(); - return false; - } - return true; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceClientConnection.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceClientConnection.java deleted file mode 100644 index d7281b1ac3..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceClientConnection.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.util.Log; - - -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.RoundtripService; -import com.gxwtech.roundtrip2.RoundtripServiceClientConnection; -import com.gxwtech.roundtrip2.ServiceData.ServiceClientActions; -import com.gxwtech.roundtrip2.ServiceData.ServiceCommand; - -import info.nightscout.androidaps.MainApp; - -/** - * Created by Tim on 27/06/2016. - * Object that interfaces with the RT2 Service and Client Actions - */ -public class ServiceClientConnection { - - private static String TAG = "ServiceClientConnection"; - private RoundtripServiceClientConnection roundtripServiceClientConnection; - private Context context = MainApp.instance(); - - public ServiceClientConnection() { - roundtripServiceClientConnection = new RoundtripServiceClientConnection(context); - - //Connect to the RT service - doBindService(); - } - - /* - * - * Functions to work with the RT2 Service - * - */ - private void doBindService() { -// context.bindService(new Intent(context,RoundtripService.class), -// roundtripServiceClientConnection.getServiceConnection(), -// Context.BIND_AUTO_CREATE); - Log.d(TAG,"doBindService: binding. N/A"); - } - private void doUnbindService() { -// ServiceConnection conn = roundtripServiceClientConnection.getServiceConnection(); -// roundtripServiceClientConnection.unbind(); -// context.unbindService(conn); - Log.d(TAG,"doUnbindService: unbinding. N/A"); - } - - // send one-liner message to RoundtripService - //private void sendIPCMessage(String ipcMsgType) { - // Create a bundle with the data - // Bundle bundle = new Bundle(); - // bundle.putString(RT2Const.IPC.messageKey, ipcMsgType); - // if (sendMessage(bundle)) { - // Log.d(TAG,"sendIPCMessage: sent "+ipcMsgType); - // } else { - // Log.e(TAG,"sendIPCMessage: send failed"); - // } - //} - - //private boolean sendMessage(Bundle bundle) { - //return roundtripServiceClientConnection.sendMessage(bundle); - //} - - /* - * - * functions the client can call - * - */ - //public void sendBLEaccessGranted() { sendIPCMessage(RT2Const.IPC.MSG_BLE_accessGranted); } - - //public void sendBLEaccessDenied() { sendIPCMessage(RT2Const.IPC.MSG_BLE_accessDenied); } - - public void setThisRileylink(String address) { - //Bundle bundle = new Bundle(); - //bundle.putString(RT2Const.IPC.messageKey, RT2Const.IPC.MSG_BLE_useThisDevice); - //bundle.putString(RT2Const.IPC.MSG_BLE_useThisDevice_addressKey,address); - //sendMessage(bundle); - ServiceCommand command = ServiceClientActions.makeUseThisRileylinkCommand(address); - roundtripServiceClientConnection.sendServiceCommand(command); - Log.d(TAG,"sendIPCMessage: (use this address) "+address); - } - - public void sendPUMP_useThisDevice(String pumpIDString) { - //Bundle bundle = new Bundle(); - //bundle.putString(RT2Const.IPC.messageKey, RT2Const.IPC.MSG_PUMP_useThisAddress); - //bundle.putString(RT2Const.IPC.MSG_PUMP_useThisAddress_pumpIDKey,pumpIDString); - //sendMessage(bundle); - ServiceCommand command = ServiceClientActions.makeSetPumpIDCommand(pumpIDString); - roundtripServiceClientConnection.sendServiceCommand(command); - Log.d(TAG,"sendPUMP_useThisDevice: " + pumpIDString); - } - - public void doTunePump() { - ServiceCommand command = ServiceClientActions.makeTunePumpCommand(); - roundtripServiceClientConnection.sendServiceCommand(command); - } - - public void getHistory() { - //sendIPCMessage(RT2Const.IPC.MSG_PUMP_fetchHistory); - } - - public void getSavedHistory(){ - //sendIPCMessage(RT2Const.IPC.MSG_PUMP_fetchSavedHistory); - } - - public void setTempBasal(double amountUnitsPerHour, int durationMinutes, int uid) { - ServiceCommand command = ServiceClientActions.makeSetTempBasalCommand(amountUnitsPerHour,durationMinutes); - roundtripServiceClientConnection.sendServiceCommand(command); - } - - public void readPumpClock() { - ServiceCommand command = ServiceClientActions.makeReadPumpClockCommand(); - roundtripServiceClientConnection.sendServiceCommand(command); - } - - public void readISFProfile() { - ServiceCommand getISFProfileCommand = ServiceClientActions.makeReadISFProfileCommand(); - roundtripServiceClientConnection.sendServiceCommand(getISFProfileCommand); - } - - public void updateAllStatus() { - ServiceCommand command = ServiceClientActions.makeUpdateAllStatusCommand(); - roundtripServiceClientConnection.sendServiceCommand(command); - } - - public void doFetchPumpHistory() { - ServiceCommand retrievePageCommand = ServiceClientActions.makeFetchPumpHistoryCommand(); - roundtripServiceClientConnection.sendServiceCommand(retrievePageCommand); - } - - public void doFetchSavedHistory() { - // Does not (at the moment) fetch saved history :( - ServiceCommand cmd = ServiceClientActions.makeFetchPumpHistoryCommand(); - roundtripServiceClientConnection.sendServiceCommand(cmd); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BasalProfile.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BasalProfile.java deleted file mode 100644 index c34a413cda..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BasalProfile.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; -import org.joda.time.LocalTime; - -/** - * Created by geoff on 6/25/16. - */ -public class BasalProfile extends TimeValueProfile { - String profileType = "unknown"; - public BasalProfile() { - } - - public double getRateForTime(LocalTime atTime) { - Double rval = -999999999.0; // clearly invalid - Object o = getObjectForTime(atTime); - if (o != null) { - try { - rval = (Double)o; - } catch (ClassCastException e) { - } - } - return rval; - } - - public boolean initFromServiceResult(ServiceResult serviceResult) { - boolean initValid = initFromServiceResult(serviceResult,"BasalProfile"); - // now get our specific values from the BasalProfile - Bundle resultMap = serviceResult.getMap(); - if (resultMap != null) { - Bundle profile = resultMap.getBundle("BasalProfile"); - if (profile == null) { - return false; - } - String which = profile.getString("ProfileType"); - if (which != null) { - this.profileType = which; - } else { - mIsValid = false; - } - } else { - mIsValid = false; - } - mIsValid = initValid; - return mIsValid; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BolusWizardCarbProfile.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BolusWizardCarbProfile.java deleted file mode 100644 index 443cb9b4a4..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/BolusWizardCarbProfile.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import org.joda.time.LocalTime; - -/** - * Created by geoff on 6/25/16. - */ -public class BolusWizardCarbProfile extends TimeValueProfile { - public BolusWizardCarbProfile() { - } - - public double getCarbRatioForTime(LocalTime atTime) { - Double rval = -999999999.0; // clearly invalid - Object o = getObjectForTime(atTime); - if (o != null) { - try { - rval = (Double) o; - } catch (ClassCastException e) { - } - } - return rval; - } - - public boolean initFromServiceResult(ServiceResult serviceResult) { - return initFromServiceResult(serviceResult, "BolusWizardCarbProfile"); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/FetchPumpHistoryResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/FetchPumpHistoryResult.java deleted file mode 100644 index d2c13b2e86..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/FetchPumpHistoryResult.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; - -import com.gxwtech.roundtrip2.RoundtripService.medtronic.PumpData.Page; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by geoff on 7/16/16. - */ -public class FetchPumpHistoryResult extends ServiceResult { - public FetchPumpHistoryResult() {} - - public ArrayList getPageArray() { - ArrayList pagebundles = map.getParcelableArrayList("pageArrayList"); - ArrayList pages = new ArrayList<>(); - for (Bundle b : pagebundles) { - Page p = new Page(); - p.unpack(b); - pages.add(p); - } - return pages; - } - - public void setPageArray(List pageList) { - ArrayList pageBundles = new ArrayList<>(); - for (Page p : pageList) { - pageBundles.add(p.pack()); - } - map.putParcelableArrayList("pageArrayList",pageBundles); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ISFProfile.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ISFProfile.java deleted file mode 100644 index 9e6264ca8a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ISFProfile.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import org.joda.time.LocalTime; - -/** - * Created by geoff on 6/25/16. - */ -public class ISFProfile extends TimeValueProfile { - public ISFProfile() { - - } - - public double getISFForTime(LocalTime atTime) { - Double rval = -99999999.0; // clearly invalid - Object o = getObjectForTime(atTime); - if (o != null) { - try { - rval = (Double)o; - } catch (ClassCastException e) { - } - } - return rval; - } - - public boolean initFromServiceResult(ServiceResult serviceResult) { - return initFromServiceResult(serviceResult,"ISFProfile"); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpModelResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpModelResult.java deleted file mode 100644 index 1da971b71f..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpModelResult.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -/** - * Created by geoff on 7/11/16. - */ -public class PumpModelResult extends ServiceResult { - private static final String TAG = "PumpModelResult"; - public PumpModelResult() { } - - @Override - public void init() { - map.putString("ServiceMessageType","PumpModelResult"); - } - - public void setPumpModel(String model) { - map.putString("model", model); - } - - public String getPumpModel() { - return map.getString("model"); - } - - public void initFromServiceResult(ServiceResult serviceResult) { - setMap(serviceResult.getMap()); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpStatusResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpStatusResult.java deleted file mode 100644 index 3a9821e0fb..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/PumpStatusResult.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import com.gxwtech.roundtrip2.RoundtripService.RileyLink.PumpManagerStatus; - -/** - * Created by geoff on 7/16/16. - */ -public class PumpStatusResult extends ServiceResult { - private static final String TAG = "PumpStatusResult"; - public PumpStatusResult() { } - - @Override - public void init() { - map.putString("ServiceMessageType","PumpStatusResult"); - } - - /** - * pumpStatus.remainBattery = statusEvent.remainBattery; - pumpStatus.remainUnits = statusEvent.remainUnits; - pumpStatus.currentBasal = statusEvent.currentBasal; - pumpStatus.last_bolus_amount = statusEvent.last_bolus_amount; - pumpStatus.last_bolus_time = statusEvent.last_bolus_time; - pumpStatus.tempBasalInProgress = statusEvent.tempBasalInProgress; - pumpStatus.tempBasalRatio = statusEvent.tempBasalRatio; - pumpStatus.tempBasalRemainMin = statusEvent.tempBasalRemainMin; - pumpStatus.tempBasalStart = statusEvent.tempBasalStart; - pumpStatus.time = statusEvent.time;//Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime(); - statusEvent.timeLastSync = statusEvent.time; - */ - - /* - double remainBattery; - double remainUnits; - double currentBasal; - double lastBolusAmount; - String lastBolusTime; - int tempBasalInProgress; - double tempBasalRatio; - double tempBasalRemainMin; - String tempBasalStart; - String time; - String timeLastSync; - */ - - public double getRemainBattery() { - return map.getDouble("remainBattery"); - } - - public void setRemainBattery(double remainBattery) { - map.putDouble("remainBattery",remainBattery); - } - - public double getRemainUnits() { - return map.getDouble("remainUnits"); - } - - public void setRemainUnits(double remainUnits) { - map.putDouble("remainUnits",remainUnits); - } - - public double getCurrentBasal() { - return map.getDouble("currentBasal"); - } - - public void setCurrentBasal(double currentBasal) { - map.putDouble("currentBasal",currentBasal); - } - - public double getLastBolusAmount() { - return map.getDouble("lastBolusAmount"); - } - - public void setLastBolusAmount(double lastBolusAmount) { - map.putDouble("lastBolusAmount",lastBolusAmount); - } - - public String getLastBolusTime() { - return map.getString("lastBolusTime",""); - } - - public void setLastBolusTime(String lastBolusTime) { - map.putString("lastBolusTime",lastBolusTime); - } - - public int getTempBasalInProgress() { - return map.getInt("tempBasalInProgress"); - } - - public void setTempBasalInProgress(int tempBasalInProgress) { - map.putInt("tempBasalInProgress",tempBasalInProgress); - } - - public double getTempBasalRatio() { - return map.getDouble("tempBasalRatio"); - } - - public void setTempBasalRatio(double tempBasalRatio) { - map.putDouble("tempBasalRatio",tempBasalRatio); - } - - public double getTempBasalRemainMin() { - return map.getDouble("tempBasalRemainMin"); - } - - public void setTempBasalRemainMin(double tempBasalRemainMin) { - map.putDouble("tempBasalRemainMin",tempBasalRemainMin); - } - - public String getTempBasalStart() { - return map.getString("tempBasalStart",""); - } - - public void setTempBasalStart(String tempBasalStart) { - map.putString("tempBasalStart",tempBasalStart); - } - - public String getTime() { - return map.getString("time",""); - } - - public void setTime(String time) { - map.putString("time",time); - } - - public String getTimeLastSync() { - return map.getString("timeLastSync",""); - } - - public void setTimeLastSync(String timeLastSync) { - map.putString("timeLastSync",timeLastSync); - } - - public void initFromServiceResult(ServiceResult serviceResult) { - setMap(serviceResult.getMap()); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ReadPumpClockResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ReadPumpClockResult.java deleted file mode 100644 index 2ce81d15de..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ReadPumpClockResult.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; -import android.util.Log; - -import org.joda.time.LocalDateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -/** - * Created by geoff on 6/25/16. - */ -public class ReadPumpClockResult extends ServiceResult { - private static final String TAG="ReadPumpClockResult"; - public ReadPumpClockResult() {} - - @Override - public void init() { - map.putString("ServiceMessageType","ReadPumpClockResult"); - } - - public void setTime(LocalDateTime pumpTime) { - Bundle map = getMap(); - DateTimeFormatter fmt = DateTimeFormat.forStyle("FF"); - map.putString("PumpTime",fmt.print(pumpTime)); - setMap(map); - } - - public LocalDateTime getTime() { - LocalDateTime rval = new LocalDateTime(1900,1,1,1,1); - Bundle map = getMap(); - if (map != null) { - String timeString = map.getString("PumpTime"); - if (timeString != null) { - DateTimeFormatter fmt = DateTimeFormat.forStyle("FF"); - try { - rval = fmt.parseLocalDateTime(timeString); - } catch (IllegalArgumentException e) { - Log.e(TAG,"getTime: failed to parse time from '"+timeString+"'"); - } - } - } - return rval; - } - - public String getTimeString() { - Bundle map = getMap(); - if (map != null) { - String rval = map.getString("PumpTime"); - if (rval != null) { - return rval; - } - } - return ""; - } - - // This can be overridden by subclasses -- essentially it allows - // casting from the base class to the subclass. - public void initFromServiceResult(ServiceResult serviceResult) { - setMap(serviceResult.getMap()); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/RetrieveHistoryPageResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/RetrieveHistoryPageResult.java deleted file mode 100644 index 83616501fd..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/RetrieveHistoryPageResult.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; - -/** - * Created by geoff on 7/2/16. - */ -public class RetrieveHistoryPageResult extends ServiceResult { - public RetrieveHistoryPageResult() {} - public void setPageNumber(int pageNumber) { - map.putInt("pageNumber",pageNumber); - } - public int getPageNumber() { - return map.getInt("pageNumber", -1); - } - public void setPageBundle(Bundle pageBundle) { - map.putBundle("pageBundle",pageBundle); - } - public Bundle getPageBundle() { - return map.getBundle("pageBundle"); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceClientActions.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceClientActions.java deleted file mode 100644 index ebdaeb0070..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceClientActions.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; - -import org.joda.time.LocalDateTime; - -import java.util.UUID; - -/** - * Created by geoff on 6/25/16. - */ -public class ServiceClientActions { - public ServiceClientActions() {} - - /* - * Set Temp Basal - * - * inputs: - * amountUnitsPerHour - temp basal amount, in Units per hour - * durationMinutes - temp basal duration, in minutes - * - * result: standard ok/error result - */ - - public static String makeRandomID() { - UUID uuid = UUID.randomUUID(); - return uuid.toString(); - } - - public static ServiceCommand makeSetTempBasalCommand(double amountUnitsPerHour, int durationMinutes) { - ServiceCommand command = new ServiceCommand("SetTempBasal",makeRandomID()); - Bundle b = command.getMap(); - b.putDouble("amountUnitsPerHour",amountUnitsPerHour); - b.putInt("durationMinutes",durationMinutes); - command.setMap(b); - return command; - } - - /* - * Read Basal Profile - * - * inputs: - * which - "STD", "A", or "B" - * - * result: an ok/error result with a basal profile Bundle. - * Get the profile using BasalProfile.initFromServiceResult() - */ - - // 'which' is "STD", "A", or "B" - public static ServiceCommand makeReadBasalProfileCommand(String which) { - ServiceCommand command = new ServiceCommand("ReadBasalProfile",makeRandomID()); - Bundle b = command.getMap(); - b.putString("which",which); - command.setMap(b); - return command; - } - - public static ServiceCommand makeReadPumpClockCommand() { - return new ServiceCommand("ReadPumpClock",makeRandomID()); - } - - public static ServiceCommand makeSendBolusCommand(double amountUnits) { - ServiceCommand command = new ServiceCommand("SendBolus",makeRandomID()); - Bundle b = command.getMap(); - b.putDouble("amountInUnits",amountUnits); - command.setMap(b); - return command; - } - - public static ServiceCommand makeSetPumpClockCommand(LocalDateTime localDateTime) { - ServiceCommand command = new ServiceCommand("SetPumpClock",makeRandomID()); - Bundle b = command.getMap(); - b.putString("localDateTime",localDateTime.toString()); - command.setMap(b); - return command; - } - - public static ServiceCommand makeReadISFProfileCommand() { - return new ServiceCommand("ReadISFProfile",makeRandomID()); - } - - public static ServiceCommand makeReadBolusWizardCarbProfileCommand() { - return new ServiceCommand("ReadBolusWizardCarbProfile",makeRandomID()); - } - - public static ServiceCommand makeReadDIASettingCommand() { - return new ServiceCommand("ReadDIASetting",makeRandomID()); - } - - public static ServiceCommand makeReadBatteryLevelCommand() { - return new ServiceCommand("ReadBatteryLevel",makeRandomID()); - } - - public static ServiceCommand makeReadReservoirLevelCommand() { - return new ServiceCommand("ReadReservoirLevel",makeRandomID()); - } - - public static ServiceCommand makeSetPumpIDCommand(String pumpID) { - ServiceCommand cmd = new ServiceCommand("SetPumpID",makeRandomID()); - Bundle b = cmd.getMap(); - b.putString("pumpID",pumpID); - cmd.setMap(b); - return cmd; - } - - public static ServiceCommand makeUseThisRileylinkCommand(String rlAddress) { - ServiceCommand cmd = new ServiceCommand("UseThisRileylink",makeRandomID()); - Bundle b = cmd.getMap(); - b.putString("rlAddress",rlAddress); - cmd.setMap(b); - return cmd; - } - - public static ServiceCommand makeRetrieveHistoryPageCommand(int pageNumber) { - ServiceCommand cmd = new ServiceCommand("RetrieveHistoryPage",makeRandomID()); - Bundle b = cmd.getMap(); - b.putInt("pageNumber",pageNumber); - cmd.setMap(b); - return cmd; - } - - public static ServiceCommand getPumpModel() { - return new ServiceCommand("ReadPumpModel",makeRandomID()); - } - - public static ServiceCommand makeUpdateAllStatusCommand() { - return new ServiceCommand("UpdatePumpStatus",makeRandomID()); - } - - public static ServiceCommand makeTunePumpCommand() { - return new ServiceCommand("WakeAndTune",makeRandomID()); - } - - public static ServiceCommand makeFetchPumpHistoryCommand() { - return new ServiceCommand("FetchPumpHistory",makeRandomID()); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessage.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessage.java deleted file mode 100644 index 8e587d722b..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessage.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; - -/** - * Created by geoff on 7/4/16. - * - * Base class for all messages passed between service and client - */ -public class ServiceMessage { - protected Bundle map = new Bundle(); - public ServiceMessage() { init(); } - public void init() { - map.putString("ServiceMessageClass",this.getClass().getCanonicalName()); - map.putString("ServiceMessageType",this.getClass().getSimpleName()); - } - public Bundle getMap() { return map; } - public void setMap(Bundle map) { this.map = map; } - public String getServiceMessageType() { - return map.getString("ServiceMessageType"); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessageUpdate.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessageUpdate.java deleted file mode 100644 index f85366ecaa..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceMessageUpdate.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -/** - * Created by geoff on 7/4/16. - */ -@Deprecated -public class ServiceMessageUpdate extends ServiceMessage { - public ServiceMessageUpdate() {} - public void init() { - map.putString("ServiceMessageType","ServiceUpdateMessage"); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceResult.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceResult.java deleted file mode 100644 index a5b095e537..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceResult.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; - -import java.util.HashMap; - -/** - * Created by geoff on 6/25/16. - */ -public class ServiceResult extends ServiceMessage { - public ServiceResult() { init(); } - public ServiceResult(Bundle resultBundle) { - if (resultBundle != null) { - setMap(resultBundle); - } else { - init(); - } - } - - @Override - public void init() { - super.init(); - map.putString("ServiceMessageType","ServiceResult"); - setServiceResultType(this.getClass().getSimpleName()); - setResultError(0,"Uninitialized ServiceResult"); - } - - public void setServiceResultType(String serviceResultType) { - map.putString("ServiceResultType",serviceResultType); - } - - public String getServiceResultType() { - return map.getString("ServiceResultType","ServiceResult"); - } - - public void setResultOK() { - map.putString("result","OK"); - } - public void setResultError(int errorCode) { - setResultError(errorCode,getErrorDescription(errorCode)); - } - public void setResultError(int errorCode, String errorDescription) { - map.putString("result","error"); - map.putInt("errorCode",errorCode); - map.putString("errorDescription",errorDescription); - } - - public static final int ERROR_MALFORMED_PUMP_RESPONSE = 1; - public static final int ERROR_NULL_PUMP_RESPONSE = 2; - public static final int ERROR_INVALID_PUMP_RESPONSE = 3; - public static final int ERROR_PUMP_BUSY = 4; - - public static final String getErrorDescription(int errorCode) { - switch(errorCode) { - case ERROR_MALFORMED_PUMP_RESPONSE: return "Malformed Pump Response"; - case ERROR_NULL_PUMP_RESPONSE: return "Null pump response"; - case ERROR_INVALID_PUMP_RESPONSE: return "Invalid pump response"; - case ERROR_PUMP_BUSY: return "A pump command session is already in progress"; - default: return "Unknown error code (" + errorCode + ")"; - } - } - - public boolean resultIsOK() { - return ("OK".equals(map.getString("result",""))); - } - public String getErrorDescription() { - return map.getString("errorDescription",""); - } - - public String getResult() { - return map.getString("result",""); - } - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceTransport.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceTransport.java deleted file mode 100644 index f67cf9a032..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceTransport.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; -import android.os.Parcel; - -import com.gxwtech.roundtrip2.RT2Const; - -/** - * Created by geoff on 7/6/16. - * - * This class exists to hold a ServiceCommand along with transport variables - * such as time sent, time received, sender. - * May also contain result, if the command is completed. - */ -public class ServiceTransport extends ServiceMessage { - public ServiceTransport() { - } - - public ServiceTransport(Bundle b) { - if (b != null) { - if ("ServiceTransport".equals(b.getString("ServiceMessageType"))) { - setMap(b); - } else { - throw new IllegalArgumentException(); - } - } - } - - @Override - public void init() { - super.init(); - map.putString("ServiceMessageType","ServiceTransport"); - setTransportType("unknown"); - setSenderHashcode(0); - } - - public void setSenderHashcode(Integer senderHashcode) { - map.putInt("senderHashcode",senderHashcode); - } - - public Integer getSenderHashcode() { - return new Integer(map.getInt("senderHashCode",0)); - } - - public void setServiceCommand(ServiceCommand serviceCommand) { - map.putBundle("ServiceCommand",serviceCommand.getMap()); - } - - public ServiceCommand getServiceCommand() { - return new ServiceCommand(map.getBundle("ServiceCommand")); - } - - public boolean hasServiceCommand() { - return (getMap().containsKey("ServiceCommand")); - } - - // On remote end, this will be converted to the "action" of a local Intent, - // so can be used for separating types of messages to different internal handlers. - public void setTransportType(String transportType) { - map.putString("transportType",transportType); - } - - public String getTransportType() { - return map.getString("transportType","unknown"); - } - - public void setServiceResult(ServiceResult serviceResult) { - map.putBundle("ServiceResult",serviceResult.getMap()); - } - - public ServiceResult getServiceResult() { - return new ServiceResult(map.getBundle("ServiceResult")); - } - - public boolean hasServiceResult() { - return (getMap().containsKey("ServiceResult")); - } - - public void setServiceNotification(ServiceNotification notification) { - map.putBundle("ServiceNotification",notification.getMap()); - } - - public ServiceNotification getServiceNotification() { - return new ServiceNotification(map.getBundle("ServiceNotification")); - } - - public boolean hasServiceNotification() { - return (getMap().containsKey("ServiceNotification")); - } - - public boolean commandDidCompleteOK() { - return getServiceResult().resultIsOK(); - } - - public String getOriginalCommandName() { - return getServiceCommand().getCommandName(); - } - - public String describeContentsShort() { - String rval = ""; - rval += getTransportType(); - if (RT2Const.IPC.MSG_ServiceNotification.equals(getTransportType())) { - rval += "note: " + getServiceNotification().getNotificationType(); - } else if (RT2Const.IPC.MSG_ServiceCommand.equals(getTransportType())) { - rval += ", cmd=" + getOriginalCommandName(); - } else if (RT2Const.IPC.MSG_ServiceResult.equals(getTransportType())) { - rval += ", cmd=" + getOriginalCommandName(); - rval += ", rslt=" + getServiceResult().getResult(); - rval += ", err=" + getServiceResult().getErrorDescription(); - } - return rval; - } - - public ServiceTransport clone() { - Parcel p = Parcel.obtain(); - Parcel p2 = Parcel.obtain(); - getMap().writeToParcel(p,0); - byte[] bytes = p.marshall(); - p2.unmarshall(bytes, 0, bytes.length); - p2.setDataPosition(0); - Bundle b = p2.readBundle(); - ServiceTransport rval = new ServiceTransport(); - rval.setMap(b); - return rval; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/TimeValueProfile.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/TimeValueProfile.java deleted file mode 100644 index 1d14c0e07a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/TimeValueProfile.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceData; - -import android.os.Bundle; -import android.util.Log; - -import org.joda.time.LocalDateTime; -import org.joda.time.LocalTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Created by geoff on 6/25/16. - */ -public class TimeValueProfile { - private static final String TAG = "TimeValueProfile"; - boolean mIsValid = false; - LocalDateTime validAt; - ArrayList times = new ArrayList<>(); - HashMap values = new HashMap<>(); - - public TimeValueProfile() { - // initialize with very wrong timestamp. - validAt = new LocalDateTime(1900,1,1,1,1); - } - - public boolean isValid() { - return mIsValid; - } - - public ArrayList getTimes() { - return times; - } - - // This function will return the "object" at any time of day by finding the correct interval. - public Object getObjectForTime(LocalTime atTime) { - LocalTime prevTime = null; - double rval = -1.0; - for (LocalTime t : times) { - if (atTime.compareTo(t) < 0) { - if (prevTime != null) { - Object o = values.get(prevTime); - if (o != null) { - return o; - } - } - } - prevTime = t; - } - // cover last interval -- last time until next midnight - if (prevTime != null) { - Object o = values.get(prevTime); - if (o!=null) { - return o; - } - } - return rval; - } - - public boolean initFromServiceResult(ServiceResult serviceResult, String timeValueProfileName) { - if (serviceResult == null) { - return false; - } - Bundle resultMap = serviceResult.getMap(); - if (resultMap == null) { - return false; - } - Bundle profile = resultMap.getBundle(timeValueProfileName); - if (profile == null) { - return false; - } - mIsValid = true; - - String validDate = profile.getString("ValidDate"); - if (validDate != null) { - DateTimeFormatter fmt = DateTimeFormat.forPattern("YYYY-MM-ddTHH:mm:ss"); - try { - fmt.parseLocalDateTime(validDate); - } catch (IllegalArgumentException e) { - // invalid format - Log.e(TAG,"initFromServiceResult("+this.getClass().getSimpleName()+"): Failed to parse date from '"+validDate+"'"); - mIsValid = false; - } - } else { - mIsValid = false; - } - - int[] profileTimes = profile.getIntArray("times"); - float[] rates = profile.getFloatArray("rates"); - if ((profileTimes != null) && (rates!=null) && (profileTimes.length > 0) && (rates.length > 0) && (profileTimes.length == rates.length)) { - // first value must be zero (midnight) - if (profileTimes[0] != 0) { - mIsValid = false; - // but still try to load all of them. - } - LocalTime prevTime = null; - boolean timesValid = true; - for (int i=0; i= 0) { - timesValid = false; - } - } - } - if (!timesValid) { - Log.e(TAG,"initFromServiceResult(\"+this.getClass().getSimpleName()+\"): times must be monotonic"); - for (int j=0; j ITEMS = new ArrayList<>(); - - public static Map ITEM_MAP = new HashMap<>(); - - public static void addItem(ServiceMessageViewItem item) { - ITEMS.add(item); - ITEM_MAP.put(item.id, item); - } - - public static ServiceMessageViewItem createItem(int position) { - return new ServiceMessageViewItem(String.valueOf(position), "Item " + position, makeDetails(position)); - } - - public static String makeDetails(int position) { - StringBuilder builder = new StringBuilder(); - builder.append("Details about Item: ").append(position); - for (int i = 0; i < position; i++) { - builder.append("\nMore details information here."); - } - return builder.toString(); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailActivity.txt deleted file mode 100644 index b309b925cf..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailActivity.txt +++ /dev/null @@ -1,83 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceMessageViewActivity; - -import android.content.Intent; -import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v7.widget.Toolbar; -import android.view.View; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.app.ActionBar; -import android.view.MenuItem; - -import com.gxwtech.roundtrip2.R; - -/** - * An activity representing a single ServiceMessageView detail screen. This - * activity is only used narrow width devices. On tablet-size devices, - * item details are presented side-by-side with a list of items - * in a {@link ServiceMessageViewListActivity}. - */ -public class ServiceMessageViewDetailActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_servicemessageview_detail); - Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar); - setSupportActionBar(toolbar); - - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own detail action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - - // Show the Up button in the action bar. - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } - - // savedInstanceState is non-null when there is fragment state - // saved from previous configurations of this activity - // (e.g. when rotating the screen from portrait to landscape). - // In this case, the fragment will automatically be re-added - // to its container so we don't need to manually add it. - // For more information, see the Fragments API guide at: - // - // http://developer.android.com/guide/components/fragments.html - // - if (savedInstanceState == null) { - // Create the detail fragment and add it to the activity - // using a fragment transaction. - Bundle arguments = new Bundle(); - arguments.putString(ServiceMessageViewDetailFragment.ARG_ITEM_ID, - getIntent().getStringExtra(ServiceMessageViewDetailFragment.ARG_ITEM_ID)); - ServiceMessageViewDetailFragment fragment = new ServiceMessageViewDetailFragment(); - fragment.setArguments(arguments); - getSupportFragmentManager().beginTransaction() - .add(R.id.servicemessageview_detail_container, fragment) - .commit(); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - // This ID represents the Home or Up button. In the case of this - // activity, the Up button is shown. For - // more details, see the Navigation pattern on Android Design: - // - // http://developer.android.com/design/patterns/navigation.html#up-vs-back - // - navigateUpTo(new Intent(this, ServiceMessageViewListActivity.class)); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailFragment.txt b/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailFragment.txt deleted file mode 100644 index 27137bc27a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewDetailFragment.txt +++ /dev/null @@ -1,69 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceMessageViewActivity; - -import android.app.Activity; -import android.support.design.widget.CollapsingToolbarLayout; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.gxwtech.roundtrip2.R; - -/** - * A fragment representing a single ServiceMessageView detail screen. - * This fragment is either contained in a {@link ServiceMessageViewListActivity} - * in two-pane mode (on tablets) or a {@link ServiceMessageViewDetailActivity} - * on handsets. - */ -public class ServiceMessageViewDetailFragment extends Fragment { - /** - * The fragment argument representing the item ID that this fragment - * represents. - */ - public static final String ARG_ITEM_ID = "item_id"; - - /** - * The dummy content this fragment is presenting. - */ - private ServiceMessageViewItem mItem; - - /** - * Mandatory empty constructor for the fragment manager to instantiate the - * fragment (e.g. upon screen orientation changes). - */ - public ServiceMessageViewDetailFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (getArguments().containsKey(ARG_ITEM_ID)) { - // Load the dummy content specified by the fragment - // arguments. In a real-world scenario, use a Loader - // to load content from a content provider. - mItem = ServiceMessageView.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID)); - - Activity activity = this.getActivity(); - CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout); - if (appBarLayout != null) { - appBarLayout.setTitle(mItem.content); - } - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.servicemessageview_detail, container, false); - - // Show the dummy content as text in a TextView. - if (mItem != null) { - ((TextView) rootView.findViewById(R.id.servicemessageview_detail)).setText(mItem.details); - } - - return rootView; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewItem.java b/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewItem.java deleted file mode 100644 index 003e7fd7f8..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewItem.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceMessageViewActivity; - -import com.gxwtech.roundtrip2.ServiceData.ServiceMessage; - -/** - * Created by geoff on 7/4/16. - */ - -public class ServiceMessageViewItem { - public final String id; - public final String content; - public final String details; - - public ServiceMessageViewItem(String id, String content, String details) { - this.id = id; - this.content = content; - this.details = details; - } - - @Override - public String toString() { - return content; - } -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewListActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewListActivity.txt deleted file mode 100644 index 4ada6dbe2a..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceMessageViewActivity/ServiceMessageViewListActivity.txt +++ /dev/null @@ -1,203 +0,0 @@ -package com.gxwtech.roundtrip2.ServiceMessageViewActivity; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - - -import com.gxwtech.roundtrip2.R; -import com.gxwtech.roundtrip2.RT2Const; - -import java.util.List; - -/** - * An activity representing a list of ServiceMessageViews. This activity - * has different presentations for handset and tablet-size devices. On - * handsets, the activity presents a list of items, which when touched, - * lead to a {@link ServiceMessageViewDetailActivity} representing - * item details. On tablets, the activity presents the list of items and - * item details side-by-side using two vertical panes. - */ -public class ServiceMessageViewListActivity extends AppCompatActivity { - private static final String TAG = "SvcMsgViewListActivity"; - /** - * Whether or not the activity is in two-pane mode, i.e. running on a tablet - * device. - */ - private boolean mTwoPane; - private BroadcastReceiver mBroadcastReceiver; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_servicemessageview_list); - - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - toolbar.setTitle(getTitle()); - - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - - View recyclerView = findViewById(R.id.servicemessageview_list); - assert recyclerView != null; - setupRecyclerView((RecyclerView) recyclerView); - - if (findViewById(R.id.servicemessageview_detail_container) != null) { - // The detail container view will be present only in the - // large-screen layouts (res/values-w900dp). - // If this view is present, then the - // activity should be in two-pane mode. - mTwoPane = true; - } - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (RT2Const.IPC.MSG_ServiceCommand.equals(action) || - (RT2Const.IPC.MSG_ServiceResult.equals(action))) { - Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); - // build ID from the millisecond timestamp and a descriptive part of the ServiceMessage - String command = bundle.getString("command"); - String serviceResultType = bundle.getString("ServiceResultType"); - String idPart = "(null)"; - if (command != null) { - String commandID = bundle.getString("commandID"); - if (commandID != null) { - idPart = command + commandID; - } else { - idPart = command; - } - } - if (serviceResultType != null) { - idPart = serviceResultType; - } - String messageID = bundle.getString(RT2Const.IPC.instantKey,"(null)") + idPart; - // build content from the descriptive string - String content = idPart; - // build details from the KV pairs from the message - StringBuilder detailsBuilder = new StringBuilder(); - for (String key : bundle.keySet()) { - if ("command".equals(key)) continue; - if ("ServiceResultType".equals(key)) continue; - if ("instant".equals(key)) continue; - detailsBuilder.append(key); - detailsBuilder.append("="); - String stringValue = bundle.getString(key); - if (stringValue != null) { - detailsBuilder.append(stringValue); - } else { - Bundle bundleValue = bundle.getBundle(key); - if (bundleValue != null) { - detailsBuilder.append("(bundle)"); - } else { - detailsBuilder.append("(?)"); - } - } - detailsBuilder.append("\n"); - } - ServiceMessageView.addItem(new ServiceMessageViewItem(messageID,content,detailsBuilder.toString())); - } else { - Log.e(TAG,"onReceive: unhandled action: " + action); - } - } - }; - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(RT2Const.IPC.MSG_ServiceCommand); - intentFilter.addAction(RT2Const.IPC.MSG_ServiceResult); - LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter); - } - - private void setupRecyclerView(@NonNull RecyclerView recyclerView) { - recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(ServiceMessageView.ITEMS)); - } - - public class SimpleItemRecyclerViewAdapter - extends RecyclerView.Adapter { - - private final List mValues; - - public SimpleItemRecyclerViewAdapter(List items) { - mValues = items; - } - - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.servicemessageview_list_content, parent, false); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(final ViewHolder holder, int position) { - holder.mItem = mValues.get(position); - holder.mIdView.setText(mValues.get(position).id); - holder.mContentView.setText(mValues.get(position).content); - - holder.mView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mTwoPane) { - Bundle arguments = new Bundle(); - arguments.putString(ServiceMessageViewDetailFragment.ARG_ITEM_ID, holder.mItem.id); - ServiceMessageViewDetailFragment fragment = new ServiceMessageViewDetailFragment(); - fragment.setArguments(arguments); - getSupportFragmentManager().beginTransaction() - .replace(R.id.servicemessageview_detail_container, fragment) - .commit(); - } else { - Context context = v.getContext(); - Intent intent = new Intent(context, ServiceMessageViewDetailActivity.class); - intent.putExtra(ServiceMessageViewDetailFragment.ARG_ITEM_ID, holder.mItem.id); - - context.startActivity(intent); - } - } - }); - } - - @Override - public int getItemCount() { - return mValues.size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - public final View mView; - public final TextView mIdView; - public final TextView mContentView; - public ServiceMessageViewItem mItem; - - public ViewHolder(View view) { - super(view); - mView = view; - mIdView = (TextView) view.findViewById(R.id.id); - mContentView = (TextView) view.findViewById(R.id.content); - } - - @Override - public String toString() { - return super.toString() + " '" + mContentView.getText() + "'"; - } - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/SettingsActivity.txt b/app/src/main/java/com/gxwtech/roundtrip2/SettingsActivity.txt deleted file mode 100644 index c4f8fa118c..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/SettingsActivity.txt +++ /dev/null @@ -1,208 +0,0 @@ -package com.gxwtech.roundtrip2; - - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceActivity; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.ActionBar; -import android.preference.PreferenceFragment; -import android.preference.PreferenceManager; -import android.view.MenuItem; - -import java.util.List; - -/** - * A {@link PreferenceActivity} that presents a set of application settings. On - * handset devices, settings are presented as a single list. On tablets, - * settings are split by category, with category headers shown to the left of - * the list of settings. - *

- * See - * Android Design: Settings for design guidelines and the Settings - * API Guide for more information on developing a Settings UI. - */ -public class SettingsActivity extends AppCompatPreferenceActivity { - /** - * A preference value change listener that updates the preference's summary - * to reflect its new value. - */ - private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - String stringValue = value.toString(); - - switch (preference.getKey()){ - case "pref_user_max_bolus": - preference.setSummary(stringValue + "U"); - break; - case "pref_user_max_basal_rate": - preference.setSummary(stringValue + "U/hr"); - break; - case "pref_user_max_basal_duration": - preference.setSummary(stringValue + "mins"); - break; - case RT2Const.serviceLocal.pumpIDKey: - preference.setSummary(stringValue); - break; - default: - // For all other preferences, set the summary to the value's - // simple string representation. - preference.setSummary(stringValue); - } - - return true; - } - }; - - /** - * Helper method to determine if the device has an extra-large screen. For - * example, 10" tablets are extra-large. - */ - private static boolean isXLargeTablet(Context context) { - return (context.getResources().getConfiguration().screenLayout - & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; - } - - /** - * Binds a preference's summary to its value. More specifically, when the - * preference's value is changed, its summary (line of text below the - * preference title) is updated to reflect the value. The summary is also - * immediately updated upon calling this method. The exact display format is - * dependent on the type of preference. - * - * @see #sBindPreferenceSummaryToValueListener - */ - private static void bindPreferenceSummaryToValue(Preference preference) { - // Set the listener to watch for value changes. - preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); - - // Trigger the listener immediately with the preference's - // current value. - sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, - PreferenceManager - .getDefaultSharedPreferences(preference.getContext()) - .getString(preference.getKey(), "")); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setupActionBar(); - } - - /** - * Set up the {@link android.app.ActionBar}, if the API is available. - */ - private void setupActionBar() { - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - // Show the Up button in the action bar. - actionBar.setDisplayHomeAsUpEnabled(true); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean onIsMultiPane() { - return isXLargeTablet(this); - } - - /** - * {@inheritDoc} - */ - @Override - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void onBuildHeaders(List

target) { - loadHeadersFromResource(R.xml.pref_headers, target); - } - - /** - * This method stops fragment injection in malicious applications. - * Make sure to deny any unknown fragments here. - */ - protected boolean isValidFragment(String fragmentName) { - return PreferenceFragment.class.getName().equals(fragmentName) - || PumpPreferenceFragment.class.getName().equals(fragmentName) - || RileyLinkPreferenceFragment.class.getName().equals(fragmentName); - } - - /** - * This fragment shows general preferences only. It is used when the - * activity is showing a two-pane settings UI. - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static class PumpPreferenceFragment extends PreferenceFragment { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.pref_pump); - setHasOptionsMenu(true); - - // Bind the summaries of EditText/List/Dialog/Ringtone preferences - // to their values. When their values change, their summaries are - // updated to reflect the new value, per the Android Design - // guidelines. - bindPreferenceSummaryToValue(findPreference(RT2Const.serviceLocal.pumpIDKey)); - bindPreferenceSummaryToValue(findPreference("pref_user_max_bolus")); - bindPreferenceSummaryToValue(findPreference("pref_user_max_basal_rate")); - bindPreferenceSummaryToValue(findPreference("pref_user_max_basal_duration")); - - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - startActivity(new Intent(getActivity(), SettingsActivity.class)); - return true; - } - return super.onOptionsItemSelected(item); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static class RileyLinkPreferenceFragment extends PreferenceFragment { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.pref_rileylink); - setHasOptionsMenu(true); - - // Bind the summaries of EditText/List/Dialog/Ringtone preferences - // to their values. When their values change, their summaries are - // updated to reflect the new value, per the Android Design - // guidelines. - bindPreferenceSummaryToValue(findPreference(RT2Const.serviceLocal.rileylinkAddressKey)); - Preference rileylink_ble = findPreference(RT2Const.serviceLocal.rileylinkAddressKey); - rileylink_ble.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startActivity(new Intent(MainApp.instance(), RileyLinkScan.class)); - return true; - } - }); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - startActivity(new Intent(getActivity(), SettingsActivity.class)); - return true; - } - return super.onOptionsItemSelected(item); - } - } - - - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/TreatmentHistory.txt b/app/src/main/java/com/gxwtech/roundtrip2/TreatmentHistory.txt deleted file mode 100644 index 84bbdd86db..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/TreatmentHistory.txt +++ /dev/null @@ -1,320 +0,0 @@ -package com.gxwtech.roundtrip2; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.SimpleAdapter; -import android.widget.Spinner; -import android.widget.TextView; - -import com.gxwtech.roundtrip2.CommunicationService.Objects.Bolus; -import com.gxwtech.roundtrip2.CommunicationService.Objects.Integration; -import com.gxwtech.roundtrip2.CommunicationService.Objects.RealmManager; -import com.gxwtech.roundtrip2.CommunicationService.Objects.TempBasal; -import com.gxwtech.roundtrip2.util.tools; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; - -public class TreatmentHistory extends AppCompatActivity { - private static final String TAG = "TreatmentHistory"; - - SectionsPagerAdapter mSectionsPagerAdapter; //will provide fragments for each of the sections - ViewPager mViewPager; - Fragment bolusFragmentObject; - Fragment basalFragmentObject; - BroadcastReceiver refreshTreatments; - BroadcastReceiver refreshBasal; - static Spinner numHours; - static RealmManager realmManager; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_treatment_history); - - realmManager = new RealmManager(); - - //Num hours spinner setup - numHours = (Spinner) findViewById(R.id.integrationHours); - String[] integrationHours = {"4", "8", "12", "24", "48"}; - ArrayAdapter stringArrayAdapterHours= new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, integrationHours); - numHours.setAdapter(stringArrayAdapterHours); - numHours.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - bolusFragment.update(); - basalFragment.update(); - } - @Override - public void onNothingSelected(AdapterView parent) { - } - }); - numHours.setSelection(0); - - // Create the adapter that will return a fragment for each of the 4 primary sections of the app. - mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); - // Set up the ViewPager with the sections adapter. - mViewPager = (ViewPager) this.findViewById(R.id.pager); - mViewPager.setAdapter(mSectionsPagerAdapter); - bolusFragmentObject = new bolusFragment(); - basalFragmentObject = new basalFragment(); - } - - @Override - public void onDestroy(){ - super.onDestroy(); - realmManager.closeRealm(); - } - - @Override - public void onPause() { - super.onPause(); - if (refreshTreatments != null){ - unregisterReceiver(refreshTreatments); - } - if (refreshBasal != null){ - unregisterReceiver(refreshBasal); - } - } - - @Override - protected void onResume(){ - super.onResume(); - - //Refresh the treatments list - refreshTreatments = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - bolusFragment.update(); - } - }; - registerReceiver(refreshTreatments, new IntentFilter("UPDATE_TREATMENTS")); - bolusFragment.update(); - - //Refresh the Basal list - refreshBasal = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - basalFragment.update(); - } - }; - registerReceiver(refreshBasal, new IntentFilter("UPDATE_BASAL")); - basalFragment.update(); - } - - /* Page layout Fragments */ - - public class SectionsPagerAdapter extends FragmentPagerAdapter { - - public SectionsPagerAdapter(FragmentManager fm) { - super(fm); - } - - @Override - public Fragment getItem(int position) { - // getItem is called to instantiate the fragment for the given page. - switch (position){ - case 0: - return bolusFragmentObject; - case 1: - return basalFragmentObject; - default: - return null; - } - } - - @Override - public int getCount() { - // Show 2 total pages. - return 2; - } - - @Override - public CharSequence getPageTitle(int position) { - switch (position) { - case 0: - return "Bolus Requests"; - case 1: - return "Basal Requests"; - } - return null; - } - } - - public static class bolusFragment extends Fragment { - public bolusFragment(){} - private static ListView list; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_treatments_list, container, false); - list = (ListView) rootView.findViewById(R.id.treatmentsFragmentList); - - update(); - return rootView; - } - - public static void update(){ - - if (list != null) { - ArrayList> bolusList = new ArrayList<>(); - int hoursAgo = Integer.getInteger(numHours.getSelectedItem().toString(),4); - SimpleDateFormat sdfDateTime = new SimpleDateFormat("dd MMM HH:mm", MainApp.instance().getResources().getConfiguration().locale); - List boluses = Bolus.getBolusesBetween(new Date(new Date().getTime() - ((60000 * 60 * hoursAgo))), new Date(), realmManager.getRealm()); - - for (Bolus bolus : boluses){ - HashMap bolusItem = new HashMap(); - List integrations = Integration.getIntegrationsFor("bolus", bolus.getId(), realmManager.getRealm()); - - bolusItem.put("id", bolus.getId()); - bolusItem.put("object", "bolus"); - bolusItem.put("value", bolus.getValue().toString()); - bolusItem.put("timestamp", sdfDateTime.format(bolus.getTimestamp().getTime())); - bolusItem.put("type", bolus.getType()); - for (Integration integration : integrations){ - switch (integration.getType()){ - case "aps_app": - bolusItem.put("integrationAPSState", integration.getState()); - break; - case "pump": - bolusItem.put("integrationPumpState", integration.getState()); - break; - } - } - bolusList.add(bolusItem); - } - - mySimpleAdapter adapter = new mySimpleAdapter(MainApp.instance(), bolusList, R.layout.treatments_list_layout, - new String[]{"id", "object", "value", "timestamp", "type", "aps_app", "pump"}, - new int[]{R.id.treatmentID, R.id.treatmentObject, R.id.treatmentAmount, R.id.treatmentTimestamp, R.id.treatmentType, R.id.treatmentAPS, R.id.treatmentResult}); - list.setAdapter(adapter); - } - } - } - - public static class basalFragment extends Fragment { - public basalFragment() { - } - - private static ListView list; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_treatments_list, container, false); - list = (ListView) rootView.findViewById(R.id.treatmentsFragmentList); - - update(); - return rootView; - } - - public static void update() { - if (list != null) { - ArrayList> basalList = new ArrayList<>(); - Integer hoursAgo = Integer.getInteger(numHours.getSelectedItem().toString(),4); - SimpleDateFormat sdfDateTime = new SimpleDateFormat("dd MMM HH:mm", MainApp.instance().getResources().getConfiguration().locale); - List tempBasals = TempBasal.getTempBasalsDated(new Date(new Date().getTime() - ((60000 * 60 * hoursAgo))), new Date(), realmManager.getRealm()); - - for (TempBasal tempBasal : tempBasals){ - HashMap basalItem = new HashMap(); - List integrations = Integration.getIntegrationsFor("temp_basal", tempBasal.getId(), realmManager.getRealm()); - - basalItem.put("id", tempBasal.getId()); - basalItem.put("object", "temp_basal"); - basalItem.put("rate", tempBasal.getRate().toString()); - basalItem.put("starttime", sdfDateTime.format(tempBasal.getStart_time().getTime())); - for (Integration integration : integrations){ - switch (integration.getType()){ - case "aps_app": - basalItem.put("integrationAPSState", integration.getState()); - break; - case "pump": - basalItem.put("integrationPumpState", integration.getState()); - break; - } - } - basalList.add(basalItem); - } - - mySimpleAdapter adapter = new mySimpleAdapter(MainApp.instance(), basalList, R.layout.treatments_list_layout, - new String[]{"id", "object", "rate", "starttime", "aps_app", "pump"}, - new int[]{R.id.treatmentID, R.id.treatmentObject, R.id.treatmentAmount, R.id.treatmentTimestamp, R.id.treatmentAPS, R.id.treatmentResult}); - list.setAdapter(adapter); - } - } - } - - public static class mySimpleAdapter extends SimpleAdapter { - - public mySimpleAdapter(Context context, List> items, int resource, String[] from, int[] to) { - super(context, items, resource, from, to); - } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view = super.getView(position, convertView, parent); - - TextView value, type; - type = (TextView) view.findViewById(R.id.treatmentObject); - value = (TextView) view.findViewById(R.id.treatmentAmount); - switch (type.getText().toString()){ - case "bolus": - value.setBackgroundResource(R.drawable.insulin_treatment_round); - value.setText(tools.formatDisplayInsulin(Double.valueOf(value.getText().toString()), 1)); - value.setTextColor(MainApp.instance().getResources().getColor(R.color.primary_light)); - break; - case "temp_basal": - value.setBackgroundResource(R.drawable.insulin_basal_square); - value.setText(tools.formatDisplayBasal(Double.valueOf(value.getText().toString()),false)); - value.setTextColor(MainApp.instance().getResources().getColor(R.color.primary_light)); - break; - } - - //Shows Pump result - TextView textPump = (TextView) view.findViewById(R.id.treatmentResult); - ImageView imagePump = (ImageView) view.findViewById(R.id.treatmentResultIcon); - switch (textPump.getText().toString()) { - case "to sync": - imagePump.setBackgroundResource(R.drawable.autorenew); - break; - case "sent": - imagePump.setBackgroundResource(R.drawable.arrow_right_bold_circle); - break; - case "received": - imagePump.setBackgroundResource(R.drawable.information); - break; - case "delayed": - imagePump.setBackgroundResource(R.drawable.clock); - break; - case "delivered": - imagePump.setBackgroundResource(R.drawable.checkbox_marked_circle); - break; - case "error": - imagePump.setBackgroundResource(R.drawable.alert_circle); - break; - default: - imagePump.setBackgroundResource(0); - break; - } - - return view; - } - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/ByteUtil.java b/app/src/main/java/com/gxwtech/roundtrip2/util/ByteUtil.java deleted file mode 100644 index 76bbc05beb..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/ByteUtil.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.gxwtech.roundtrip2.util; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by geoff on 4/28/15. - */ -public class ByteUtil { - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - private final static String HEX_DIGITS_STR = "0123456789ABCDEF"; - - public static byte highByte(short s) { - return (byte) (s / 256); - } - - public static byte lowByte(short s) { - return (byte) (s % 256); - } - - public static int asUINT8(byte b) { - return (b < 0) ? b + 256 : b; - } - - /* For Reference: static void System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) */ - - public static byte[] concat(byte[] a, byte[] b) { - int aLen = a.length; - int bLen = b.length; - byte[] c = new byte[aLen + bLen]; - System.arraycopy(a, 0, c, 0, aLen); - System.arraycopy(b, 0, c, aLen, bLen); - return c; - } - - public static byte[] concat(byte[] a, byte b) { - int aLen = a.length; - byte[] c = new byte[aLen + 1]; - System.arraycopy(a, 0, c, 0, aLen); - c[aLen] = b; - return c; - } - - public static byte[] substring(byte[] a, int start, int len) { - byte[] rval = new byte[len]; - System.arraycopy(a, start, rval, 0, len); - return rval; - } - - public static String shortHexString(byte[] ra) { - String rval = ""; - if (ra == null) { - return rval; - } - if (ra.length == 0) { - return rval; - } - for (int i = 0; i < ra.length; i++) { - rval = rval + HEX_DIGITS[(ra[i] & 0xF0) >> 4]; - rval = rval + HEX_DIGITS[(ra[i] & 0x0F)]; - if (i < ra.length - 1) { - rval = rval + " "; - } - } - return rval; - } - - public static String showPrintable(byte[] ra) { - String s = new String(); - for (int i=0; i='0') && (c<='9')) || - ((c>='A') && (c<='Z')) || - ((c>='a') && (c<='z'))) { - s = s+c; - } - else { - s = s+'.'; - } - } - return s; - } - - public static byte[] fromHexString(String src) { - String s = src.toUpperCase(); - byte[] rval = new byte[]{}; - if ((s.length() % 2)!=0) { - // invalid hex string! - return null; - } - for (int i=0; i byteArray){ - byte[] rval = new byte[byteArray.size()]; - for (int i=0; i toByteArray(byte[] data) { - ArrayList rval = new ArrayList<>(data.length); - for (int i=0; i len2) { - return 1; - } - if (len2 > len1) { - return -1; - } - int acc=0; - for (i=0; i data.length) { - len = data.length; - } - for (int i=0; i 0) { - for (int j=0; j> (7 - i) & 1) == 1); - boolean c15 = ((crc >> 15 & 1) == 1); - crc <<= 1; - if (c15 ^ bit) crc ^= polynomial; - } - } - } - } - crc &= 0xffff; - return new byte[]{(byte) ((crc & 0xFF00) >> 8), (byte) (crc & 0xFF)}; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/Check.java b/app/src/main/java/com/gxwtech/roundtrip2/util/Check.java deleted file mode 100644 index bcce649b11..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/Check.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.gxwtech.roundtrip2.util; - -import com.gxwtech.roundtrip2.CommunicationService.Objects.Bolus; -import com.gxwtech.roundtrip2.CommunicationService.Objects.Integration; -import com.gxwtech.roundtrip2.CommunicationService.Objects.TempBasal; -import com.gxwtech.roundtrip2.RT2Const; - -import java.util.Date; - -import io.realm.Realm; - -/** - * Created by Tim on 16/06/2016. - * Class that provides validation and safety checks - */ -public class Check { - final static boolean DEBUG = true; - - public static String isNewTempBasalSafe(TempBasal tempBasal){ - String reply = ""; - - if (isTreatmentTooOld(tempBasal.getStart_time())) reply += "Treatment is older than " + RT2Const.safety.TREATMENT_MAX_AGE + " mins, rejected."; - //is TBR supported? - // TODO: 21/02/2016 perform checks here, return empty string for OK or text detailing the issue - - return reply; - } - - public static String isCancelTempBasalSafe(TempBasal tempBasal, Integration integrationAPS, Realm realm){ - String reply = ""; - - if (isTreatmentTooOld(tempBasal.getStart_time())) reply += "Treatment is older than " + RT2Const.safety.TREATMENT_MAX_AGE + " mins, rejected. "; - if (!isThisBasalLastActioned(integrationAPS, realm)) reply += "Current Running Temp Basal does not match this Cancel request, Temp Basal has not been canceled. "; - //is TBR supported? - // TODO: 21/02/2016 perform checks here, return empty string for OK or text detailing the issue - - return reply; - } - - public static String isBolusSafeToAction(Bolus bolus){ - String reply = ""; - - if (isTreatmentTooOld(bolus.getTimestamp())) reply += "Treatment is older than " + RT2Const.safety.TREATMENT_MAX_AGE + " mins, rejected. "; - // TODO: 16/06/2016 add additional Bolus safety checks here - - return reply; - } - - public static boolean isPumpSupported(String expectedPump){ - //Do we support the pump requested? - if (DEBUG) return true; - - switch (expectedPump){ - case "medtronic_absolute": - case "medtronic_percent": - return true; - default: - return false; - } - } - - public static boolean isRequestTooOld(Long date){ - //Is this request too old to action? - Long ageInMins = (new Date().getTime() - date) /1000/60; - if (ageInMins > RT2Const.safety.INCOMING_REQUEST_MAX_AGE){ - return true; - } else { - return false; - } - } - - public static boolean isTreatmentTooOld(Date date){ - //Is this treatment too old to action? - Long ageInMins = (new Date().getTime() - date.getTime()) /1000/60; - if (ageInMins > RT2Const.safety.TREATMENT_MAX_AGE){ - return true; - } else { - return false; - } - } - - private static boolean isThisBasalLastActioned(Integration integrationAPS, Realm realm){ - //Is this Basal the most recent one set to the pump? - TempBasal lastActive = TempBasal.lastActive(realm); //Basal that is active or last active - if (lastActive == null) return false; //No basal has ever been active - - Integration integration = Integration.getIntegration("aps_app","temp_basal",lastActive.getId(),realm); - if (integration == null) return false; //We are not aware of any Basal set by this App - - if (integrationAPS.getRemote_id().equals(integration.getRemote_id())) { - return true; - } else { - return false; //Basal to cancel does not match the current active basal - } - } - -} - diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/HexDump.java b/app/src/main/java/com/gxwtech/roundtrip2/util/HexDump.java deleted file mode 100644 index ff38fd2118..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/HexDump.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.gxwtech.roundtrip2.util; - -/** - * Clone of Android's HexDump class, for use in debugging. Cosmetic changes - * only. - */ -public class HexDump { - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - public static String dumpHexString(byte[] array) { - return dumpHexString(array, 0, array.length); - } - - public static String dumpHexString(byte[] array, int offset, int length) { - StringBuilder result = new StringBuilder(); - - byte[] line = new byte[16]; - int lineIndex = 0; - - result.append("\n0x"); - result.append(toHexString(offset)); - - for (int i = offset; i < offset + length; i++) { - if (lineIndex == 16) { - result.append(" "); - - for (int j = 0; j < 16; j++) { - if (line[j] > ' ' && line[j] < '~') { - result.append(new String(line, j, 1)); - } else { - result.append("."); - } - } - - result.append("\n0x"); - result.append(toHexString(i)); - lineIndex = 0; - } - - byte b = array[i]; - result.append(" "); - result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); - result.append(HEX_DIGITS[b & 0x0F]); - - line[lineIndex++] = b; - } - - if (lineIndex != 16) { - int count = (16 - lineIndex) * 3; - count++; - for (int i = 0; i < count; i++) { - result.append(" "); - } - - for (int i = 0; i < lineIndex; i++) { - if (line[i] > ' ' && line[i] < '~') { - result.append(new String(line, i, 1)); - } else { - result.append("."); - } - } - } - - return result.toString(); - } - - public static String toHexString(byte b) { - return toHexString(toByteArray(b)); - } - - public static String toHexString(byte[] array) { - return toHexString(array, 0, array.length); - } - - public static String toHexString(byte[] array, int offset, int length) { - char[] buf = new char[length * 2]; - - int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { - byte b = array[i]; - buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; - buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; - } - - return new String(buf); - } - - public static String toHexString(int i) { - return toHexString(toByteArray(i)); - } - - public static String toHexString(short i) { - return toHexString(toByteArray(i)); - } - - public static byte[] toByteArray(byte b) { - byte[] array = new byte[1]; - array[0] = b; - return array; - } - - public static byte[] toByteArray(int i) { - byte[] array = new byte[4]; - - array[3] = (byte) (i & 0xFF); - array[2] = (byte) ((i >> 8) & 0xFF); - array[1] = (byte) ((i >> 16) & 0xFF); - array[0] = (byte) ((i >> 24) & 0xFF); - - return array; - } - - public static byte[] toByteArray(short i) { - byte[] array = new byte[2]; - - array[1] = (byte) (i & 0xFF); - array[0] = (byte) ((i >> 8) & 0xFF); - - return array; - } - - private static int toByte(char c) { - if (c >= '0' && c <= '9') - return (c - '0'); - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - - throw new RuntimeException("Invalid hex char '" + c + "'"); - } - - public static byte[] hexStringToByteArray(String hexString) { - int length = hexString.length(); - byte[] buffer = new byte[length / 2]; - - for (int i = 0; i < length; i += 2) { - buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString - .charAt(i + 1))); - } - - return buffer; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/StringUtil.java b/app/src/main/java/com/gxwtech/roundtrip2/util/StringUtil.java deleted file mode 100644 index 8cbe024484..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/StringUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gxwtech.roundtrip2.util; - -import java.nio.charset.Charset; -import java.util.ArrayList; - -/** - * Created by geoff on 4/28/15. - */ -public class StringUtil { - - public static String fromBytes(byte[] ra) { - return new String(ra, Charset.forName("UTF-8")); - } - - // these should go in some project-wide string utils package - public static String join(ArrayList ra, String joiner) { - int sz = ra.size(); - String rval = ""; - int n; - for (n = 0; n < sz; n++) { - rval = rval + ra.get(n); - if (n < sz - 1) { - rval = rval + joiner; - } - } - return rval; - } - - public static String testJoin() { - ArrayList ra = new ArrayList(); - ra.add("one"); - ra.add("two"); - ra.add("three"); - return join(ra, "+"); - } - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/ThreadUtil.java b/app/src/main/java/com/gxwtech/roundtrip2/util/ThreadUtil.java deleted file mode 100644 index e966739db2..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/ThreadUtil.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gxwtech.roundtrip2.util; - -/** - * Created by geoff on 5/27/16. - */ -public class ThreadUtil { - public static long getThreadId() { - return Thread.currentThread().getId(); - } - public static String getThreadName() { - return Thread.currentThread().getName(); - } - public static String sig() { - Thread t = Thread.currentThread(); - return t.getName() + "[" + t.getId() + "]"; - } -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/tools.java b/app/src/main/java/com/gxwtech/roundtrip2/util/tools.java deleted file mode 100644 index 61adc29dc1..0000000000 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/tools.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.gxwtech.roundtrip2.util; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.text.ClipboardManager; -import android.util.Log; -import android.widget.TextView; -import android.widget.Toast; - - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.Locale; - -/** - * Created by Tim on 15/06/2016. - */ -public class tools { - final static String TAG = "Tools"; - - public static void showLogging(){ - String logCat = "no logs"; - final String processId = Integer.toString(android.os.Process.myPid()); - try { - Process process = Runtime.getRuntime().exec("logcat -d"); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); - StringBuilder log = new StringBuilder(); - String line; - - while ((line = bufferedReader.readLine()) != null) { - if(line.contains(processId)) log.append(line + "\n"); - } - logCat = log.toString(); - - } catch (IOException e) { - logCat = e.getLocalizedMessage(); - } finally { - //showAlertText(logCat, MainApp.instance()); - showAlertText(logCat, null); - } - } - - public static void showAlertText(final String msg, final Context context){ -// try { -// AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.mContext) // TODO: 09/07/2016 @TIM this should not be needed, should be context -// .setMessage(msg) -// .setPositiveButton("Copy to Clipboard", new DialogInterface.OnClickListener() { -// public void onClick(DialogInterface dialog, int which) { -// ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); -// clipboard.setText(msg); -// Toast.makeText(MainApp.instance(), "Copied to clipboard", Toast.LENGTH_SHORT).show(); -// } -// }) -// .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { -// public void onClick(DialogInterface dialog, int which) { -// // do nothing -// } -// }) -// .show(); -// -// if (msg.length() > 100) { -// TextView textView = (TextView) alertDialog.findViewById(android.R.id.message); -// textView.setTextSize(10); -// } -// } catch (Exception e){ -// //Crashlytics.logException(e); -// Log.e(TAG, "showAlertText: " + e.getLocalizedMessage()); -// } - - Log.e(TAG, "showAlertText: " + msg); - } - - public static Double round(Double value, int decPoints){ - if (value == null || value.isInfinite() || value.isNaN()) return 0D; - DecimalFormat df; - DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.ENGLISH); - otherSymbols.setDecimalSeparator('.'); - otherSymbols.setGroupingSeparator(','); - - switch (decPoints){ - case 1: - //if (precisionRounding()){ - // df = new DecimalFormat("##0.00", otherSymbols); - //} else { - df = new DecimalFormat("##0.0", otherSymbols); - //} - break; - case 2: - df = new DecimalFormat("##0.00", otherSymbols); - break; - case 3: - df = new DecimalFormat("##0.000", otherSymbols); - break; - default: - df = new DecimalFormat("##0.0000", otherSymbols); - } - return Double.parseDouble(df.format(value)); - } - - - public static String formatDisplayInsulin(Double value, int decPoints){ - return round(value,decPoints) + "u"; - } - public static String formatDisplayBasal(Double value, Boolean doubleLine){ - if (doubleLine) { - return round(value, 2) + "\n" + "U/h"; - } else { - return round(value, 2) + "U/h"; - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/PumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/PumpStatus.java index a478897297..4bb00415f4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/PumpStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/PumpStatus.java @@ -82,4 +82,34 @@ public abstract class PumpStatus { public void setPumpType(PumpType pumpType) { this.pumpType = pumpType; } + + // FIXME cleanup this is from RT2 + + public long getTimeIndex() { + return (long) Math.ceil(time.getTime() / 60000d); + } + + public void setTimeIndex(long timeIndex) { + this.timeIndex = timeIndex; + } + + public long timeIndex; + + public Date time; + + public double remainUnits = 0; + public int remainBattery = 0; + + public double currentBasal = 0; + + public int tempBasalInProgress = 0; + public int tempBasalRatio = 0; + public int tempBasalRemainMin = 0; + public Date tempBasalStart; + + public Date last_bolus_time; + public double last_bolus_amount = 0; + + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkBLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkBLEScanActivity.java index 1e393f4475..3fe6172205 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkBLEScanActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkBLEScanActivity.java @@ -33,9 +33,6 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.util.LocationHelper; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +40,9 @@ import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.LocationHelper; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst; import info.nightscout.utils.SP; @@ -51,7 +50,7 @@ import info.nightscout.utils.SP; public class RileyLinkBLEScanActivity extends AppCompatActivity { private static final Logger LOG = LoggerFactory.getLogger(RileyLinkBLEScanActivity.class); - private final static String TAG = "RileyLinkScan"; + private BluetoothAdapter mBluetoothAdapter; private BluetoothLeScanner mLEScanner; private LeDeviceListAdapter mLeDeviceListAdapter; @@ -92,12 +91,12 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { SP.putString(MedtronicConst.Prefs.RileyLinkAddress, bleAddress); //Notify that we have a new rileylinkAddressKey - RileyLinkUtil.sendBroadcastMessage(RT2Const.local.INTENT_NEW_rileylinkAddressKey); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_rileylinkAddressKey); - Log.d(TAG, "New rileylinkAddressKey: " + bleAddress); + LOG.debug("New rileylinkAddressKey: " + bleAddress); //Notify that we have a new pumpIDKey - RileyLinkUtil.sendBroadcastMessage(RT2Const.local.INTENT_NEW_pumpIDKey); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_pumpIDKey); finish(); } }); @@ -205,7 +204,7 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { public void run() { mScanning = false; mLEScanner.stopScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Stop"); + LOG.debug("scanLeDevice: Scanning Stop"); //Toast.makeText(mContext, "Scanning finished", Toast.LENGTH_SHORT).show(); snackbar.dismiss(); } @@ -213,14 +212,14 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { mScanning = true; mLEScanner.startScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Start"); + LOG.debug("scanLeDevice: Scanning Start"); //Toast.makeText(this, "Scanning", Toast.LENGTH_SHORT).show(); snackbar.show(); } else { mScanning = false; mLEScanner.stopScan(mScanCallback); - Log.d(TAG, "scanLeDevice: Scanning Stop"); + LOG.debug("scanLeDevice: Scanning Stop"); //Toast.makeText(this, "Scanning finished", Toast.LENGTH_SHORT).show(); snackbar.dismiss(); @@ -238,7 +237,7 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { if (device.getName() != null && device.getName().length() > 0) { mLeDeviceListAdapter.addDevice(device); mLeDeviceListAdapter.notifyDataSetChanged(); - Log.d(TAG, "Found BLE" + device.getName()); + LOG.debug("Found BLE" + device.getName()); } } }); @@ -254,9 +253,9 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity { BluetoothDevice device = result.getDevice(); if (device.getName() != null && device.getName().length() > 0) { mLeDeviceListAdapter.addDevice(device); - Log.d(TAG, "Found BLE" + result.toString()); + LOG.debug("Found BLE" + result.toString()); } else { - Log.e(TAG, "Found BLE, but name appears to be missing. Ignoring. " + device.getAddress()); + LOG.error("Found BLE, but name appears to be missing. Ignoring. " + device.getAddress()); } } mLeDeviceListAdapter.notifyDataSetChanged(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java index 18231d1f81..79fa03509f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java @@ -8,8 +8,8 @@ import android.view.ViewGroup; import android.widget.TextView; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpCommon.defs.RileyLinkTargetDevice; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetDevice; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus; @@ -33,6 +33,7 @@ public class RileyLinkSettingsTab1 extends Fragment implements RefreshableInterf RileyLinkServiceData rileyLinkServiceData; MedtronicPumpStatus medtronicPumpStatus; + boolean first = false; @Override @@ -60,15 +61,19 @@ public class RileyLinkSettingsTab1 extends Fragment implements RefreshableInterf this.lastUsedFrequency = (TextView) getActivity().findViewById(R.id.rls_t1_last_used_frequency); this.lastDeviceContact = (TextView) getActivity().findViewById(R.id.rls_t1_last_device_contact); + if (!first) { - // 7-12 - int[] ids = {R.id.rls_t1_tv02, R.id.rls_t1_tv03, R.id.rls_t1_tv04, R.id.rls_t1_tv05, R.id.rls_t1_tv07, // - R.id.rls_t1_tv08, R.id.rls_t1_tv09, R.id.rls_t1_tv10, R.id.rls_t1_tv11, R.id.rls_t1_tv12}; + // 7-12 + int[] ids = {R.id.rls_t1_tv02, R.id.rls_t1_tv03, R.id.rls_t1_tv04, R.id.rls_t1_tv05, R.id.rls_t1_tv07, // + R.id.rls_t1_tv08, R.id.rls_t1_tv09, R.id.rls_t1_tv10, R.id.rls_t1_tv11, R.id.rls_t1_tv12}; - for (int id : ids) { + for (int id : ids) { - TextView tv = (TextView) getActivity().findViewById(id); - tv.setText(tv.getText() + ":"); + TextView tv = (TextView) getActivity().findViewById(id); + tv.setText(tv.getText() + ":"); + } + + first = true; } refreshData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java index 49240d29a1..b62c8f6e44 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java @@ -10,10 +10,12 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyScanResults; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyTrial; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessageType; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioResponse; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessage; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpMessage; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst; @@ -34,25 +36,37 @@ public abstract class RileyLinkCommunicationManager { private double[] scanFrequencies; - protected int receiverDeviceAwakeForMinutes = 6; // override this in constructor of specific implementation + protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation protected String receiverDeviceID; // String representation of receiver device (ex. Pump (xxxxxx) or Pod (yyyyyy)) protected long lastGoodReceiverCommunicationTime = 0; protected PumpStatus pumpStatus; + protected RileyLinkServiceData rileyLinkServiceData; // internal flag private boolean showPumpMessages = true; + protected RileyLinkTargetFrequency targetFrequency; - public RileyLinkCommunicationManager(Context context, RFSpy rfspy, double[] scanFrequencies) { + + public RileyLinkCommunicationManager(Context context, RFSpy rfspy, RileyLinkTargetFrequency targetFrequency) { this.context = context; this.rfspy = rfspy; - this.scanFrequencies = scanFrequencies; + this.targetFrequency = targetFrequency; + this.scanFrequencies = targetFrequency.getScanFrequencies(); + this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData(); + RileyLinkUtil.setRileyLinkCommunicationManager(this); + + configurePumpSpecificSettings(); } + protected abstract void configurePumpSpecificSettings(); + + protected PumpMessage sendAndListen(RLMessage msg) { - return sendAndListen(msg, 2000); + return sendAndListen(msg, 4000); // 2000 } + // All pump communications go through this function. protected PumpMessage sendAndListen(RLMessage msg, int timeout_ms) { @@ -65,7 +79,10 @@ public abstract class RileyLinkCommunicationManager { if (rval.isValid()) { // Mark this as the last time we heard from the pump. rememberLastGoodPumpCommunicationTime(); + } else { + LOG.warn("Response is invalid. !!!"); } + if (showPumpMessages) { LOG.info("Received:" + ByteUtil.shortHexString(resp.getRadioResponse().getPayload())); } @@ -73,26 +90,80 @@ public abstract class RileyLinkCommunicationManager { } - public void tryoutPacket(byte[] pkt) { - sendAndListen(makeRLMessage(pkt)); + // /** + // * For set commands we use this method (it just sends data and returns ACK or NAK) + // * + // * @param msg + // * @param timeoutMs + // * @return + // */ + // protected PumpMessage send(RLMessage msg, int timeoutMs) { + // + // // FIXME untested + // if (showPumpMessages) { + // LOG.info("Sent:" + ByteUtil.shortHexString(msg.getTxData())); + // } + // + // RFSpyResponse resp = rfspy.transmit(new RadioPacket(msg.getTxData())); + // PumpMessage rval = new PumpMessage(resp.getRadioResponse().getPayload()); + // if (rval.isValid()) { + // // Mark this as the last time we heard from the pump. + // rememberLastGoodPumpCommunicationTime(); + // } else { + // LOG.warn("Response is invalid. !!!"); + // } + // + // if (showPumpMessages) { + // LOG.info("Received:" + ByteUtil.shortHexString(resp.getRadioResponse().getPayload())); + // } + // return rval; + // } + + + public void wakeUp(boolean force) { + wakeUp(receiverDeviceAwakeForMinutes, force); + + } + + long nextWakeUpRequired = 0L; + + + // FIXME change wakeup // TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy - public void wakeup(int duration_minutes) { + public void wakeUp(int duration_minutes, boolean force) { // If it has been longer than n minutes, do wakeup. Otherwise assume pump is still awake. // **** FIXME: this wakeup doesn't seem to work well... must revisit - receiverDeviceAwakeForMinutes = duration_minutes; + //receiverDeviceAwakeForMinutes = duration_minutes; - long lastGoodPlus = getLastGoodReceiverCommunicationTime() + (receiverDeviceAwakeForMinutes * 60 * 1000); + if (force) + nextWakeUpRequired = 0L; - if (System.currentTimeMillis() > lastGoodPlus) { + if (System.currentTimeMillis() > nextWakeUpRequired) { LOG.info("Waking pump..."); - RLMessage msg = makeRLMessage(RLMessageType.PowerOn, new byte[]{(byte) duration_minutes}); - RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), (byte) 0, (byte) 200, (byte) 0, (byte) 0, 15000, (byte) 0); + + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple + RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200, (byte) 0, (byte) 0, 25000, (byte) 0); LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw())); + + nextWakeUpRequired = System.currentTimeMillis() + (receiverDeviceAwakeForMinutes * 60 * 1000); } else { - LOG.debug("Last pump communication was recent, not waking pump."); + LOG.trace("Last pump communication was recent, not waking pump."); } + + + // long lastGoodPlus = getLastGoodReceiverCommunicationTime() + (receiverDeviceAwakeForMinutes * 60 * 1000); + // + // if (System.currentTimeMillis() > lastGoodPlus || force) { + // LOG.info("Waking pump..."); + // + // byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.PowerOn); + // RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200, (byte) 0, (byte) 0, 15000, (byte) 0); + // LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw())); + // } else { + // LOG.trace("Last pump communication was recent, not waking pump."); + // } } @@ -100,25 +171,49 @@ public abstract class RileyLinkCommunicationManager { rfspy.setBaseFrequency(freqMHz); } + public double tuneForPump() { return scanForPump(scanFrequencies); } + + /** + * If user changes pump and one pump is running in US freq, and other in WW, then previously set frequency would be invalid, + * so we would need to retune. This checks that saved frequency is corrent range. + * + * @param frequency + * @return + */ + public boolean isValidFrequency(double frequency) { + return (this.scanFrequencies[0] <= frequency && this.scanFrequencies[scanFrequencies.length - 1] >= frequency); + } + + + /** + * Do device connection, with wakeup + * + * @return + */ + public abstract boolean tryToConnectToDevice(); + + + // FIXME sorting, and time display public double scanForPump(double[] frequencies) { LOG.info("Scanning for receiver ({})", receiverDeviceID); - wakeup(receiverDeviceAwakeForMinutes); + wakeUp(receiverDeviceAwakeForMinutes, false); FrequencyScanResults results = new FrequencyScanResults(); - for (int i = 0; i < frequencies.length; i++) { + for(int i = 0; i < frequencies.length; i++) { int tries = 3; FrequencyTrial trial = new FrequencyTrial(); trial.frequencyMHz = frequencies[i]; rfspy.setBaseFrequency(frequencies[i]); int sumRSSI = 0; - for (int j = 0; j < tries; j++) { - RLMessage msg = makeRLMessage(RLMessageType.ReadSimpleData); - RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); + for(int j = 0; j < tries; j++) { + + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); + RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); if (resp.wasTimeout()) { LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]); } else if (resp.looksLikeRadioPacket()) { @@ -140,7 +235,7 @@ public abstract class RileyLinkCommunicationManager { } results.sort(); // sorts in ascending order LOG.debug("Sorted scan results:"); - for (int k = 0; k < results.trials.size(); k++) { + for(int k = 0; k < results.trials.size(); k++) { FrequencyTrial one = results.trials.get(k); LOG.debug("Scan Result[{}]: Freq={}, avg RSSI = {}", k, one.frequencyMHz, one.averageRSSI); } @@ -155,19 +250,26 @@ public abstract class RileyLinkCommunicationManager { } } - public RLMessage makeRLMessage(RLMessageType type) { - return makeRLMessage(type, null); - } - public abstract RLMessage makeRLMessage(RLMessageType type, byte[] data); + // public RLMessage makeRLMessage(RLMessageType type) { + // return makeRLMessage(type, null); + // } - public abstract RLMessage makeRLMessage(byte[] data); + + //public abstract RLMessage makeRLMessage(RLMessageType type, byte[] data); + + + //public abstract RLMessage makeRLMessage(byte[] data); + + + public abstract byte[] createPumpMessageContent(RLMessageType type); private int tune_tryFrequency(double freqMHz) { rfspy.setBaseFrequency(freqMHz); - RLMessage msg = makeRLMessage(RLMessageType.ReadSimpleData); - RadioPacket pkt = new RadioPacket(msg.getTxData()); + //RLMessage msg = makeRLMessage(RLMessageType.ReadSimpleData); + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); + RadioPacket pkt = new RadioPacket(pumpMsgContent); RFSpyResponse resp = rfspy.transmitThenReceive(pkt, (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); if (resp.wasTimeout()) { LOG.warn("tune_tryFrequency: no pump response at frequency {}", freqMHz); @@ -183,10 +285,11 @@ public abstract class RileyLinkCommunicationManager { return 0; } + public double quickTuneForPump(double startFrequencyMHz) { double betterFrequency = startFrequencyMHz; double stepsize = 0.05; - for (int tries = 0; tries < 4; tries++) { + for(int tries = 0; tries < 4; tries++) { double evenBetterFrequency = quickTunePumpStep(betterFrequency, stepsize); if (evenBetterFrequency == 0.0) { // could not see the pump at all. @@ -214,14 +317,16 @@ public abstract class RileyLinkCommunicationManager { return betterFrequency; } + private double quickTunePumpStep(double startFrequencyMHz, double stepSizeMHz) { LOG.info("Doing quick radio tune for receiver ({})", receiverDeviceID); - wakeup(receiverDeviceAwakeForMinutes); + wakeUp(false); int startRssi = tune_tryFrequency(startFrequencyMHz); double lowerFrequency = startFrequencyMHz - stepSizeMHz; int lowerRssi = tune_tryFrequency(lowerFrequency); double higherFrequency = startFrequencyMHz + stepSizeMHz; int higherRssi = tune_tryFrequency(higherFrequency); + if ((higherRssi == 0.0) && (lowerRssi == 0.0) && (startRssi == 0.0)) { // we can't see the pump at all... return 0.0; @@ -244,6 +349,7 @@ public abstract class RileyLinkCommunicationManager { pumpStatus.setLastDataTimeToNow(); } + private long getLastGoodReceiverCommunicationTime() { // If we have a value of zero, we need to load from prefs. if (lastGoodReceiverCommunicationTime == 0L) { @@ -251,7 +357,7 @@ public abstract class RileyLinkCommunicationManager { // Might still be zero, but that's fine. } double minutesAgo = (System.currentTimeMillis() - lastGoodReceiverCommunicationTime) / (1000.0 * 60.0); - LOG.debug("Last good pump communication was " + minutesAgo + " minutes ago."); + LOG.trace("Last good pump communication was " + minutesAgo + " minutes ago."); return lastGoodReceiverCommunicationTime; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java index 239a79adf7..7bdf83c8e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java @@ -12,10 +12,24 @@ public class RileyLinkConst { public static final String RileyLinkReady = Prefix + "RileyLink_Ready"; public static final String RileyLinkGattFailed = Prefix + "RileyLink_Gatt_Failed"; + public static final String RileyLinkError = Prefix + "RileyLink_Ready"; public static final String BluetoothConnected = Prefix + "Bluetooth_Connected"; public static final String BluetoothDisconnected = Prefix + "Bluetooth_Disconnected"; + public static final String RileyLinkDisconnected = Prefix + "RileyLink_Disconnected"; + public static final String INTENT_NEW_rileylinkAddressKey = Prefix + "INTENT_NEW_rileylinkAddressKey"; + public static final String INTENT_NEW_pumpIDKey = Prefix + "INTENT_NEW_pumpIDKey"; + } + + public class IPC { + // needs to br renamed (and maybe removed) + public static final String MSG_PUMP_quickTune = Prefix + "MSG_PUMP_quickTune"; + public static final String MSG_PUMP_tunePump = Prefix + "MSG_PUMP_tunePump"; + public static final String MSG_PUMP_fetchHistory = Prefix + "MSG_PUMP_fetchHistory"; + public static final String MSG_PUMP_fetchSavedHistory = Prefix + "MSG_PUMP_fetchSavedHistory"; + + public static final String MSG_ServiceCommand = Prefix + "MSG_ServiceCommand"; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java index 83384e6587..ae45976aa0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java @@ -4,29 +4,48 @@ import android.content.Context; import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkService; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceNotification; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus; + /** * Created by andy on 17/05/2018. */ public class RileyLinkUtil { + private static final Logger LOG = LoggerFactory.getLogger(RileyLinkUtil.class); + private static Context context; private static RileyLinkBLE rileyLinkBLE; private static RileyLinkServiceData rileyLinkServiceData; private static List historyRileyLink = new ArrayList<>(); private static PumpType pumpType; private static MedtronicPumpStatus medtronicPumpStatus; - + private static RileyLinkService rileyLinkService; + private static RileyLinkCommunicationManager rileyLinkCommunicationManager; + //private static RileyLinkIPCConnection rileyLinkIPCConnection; + private static MedtronicDeviceType medtronicPumpModel; + private static RileyLinkTargetFrequency rileyLinkTargetFrequency; + private static MedtronicPumpStatus pumpStatus; // BAD dependencies in Classes: RileyLinkService // Broadcasts: RileyLinkBLE, RileyLinkService, @@ -43,6 +62,31 @@ public class RileyLinkUtil { } + public static void setServiceState(RileyLinkServiceState newState) { + setServiceState(newState, null); + } + + + public static RileyLinkServiceState getServiceState() { + return rileyLinkServiceData.serviceState; + } + + + public static RileyLinkError getError() { + return rileyLinkServiceData.errorCode; + } + + + public static void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) { + rileyLinkServiceData.serviceState = newState; + rileyLinkServiceData.errorCode = errorCode; + + LOG.warn("RileyLink State Changed: {} {}", newState, errorCode == null ? "" : " - Error State: " + errorCode.name()); + + historyRileyLink.add(new RLHistoryItem(rileyLinkServiceData.serviceState, rileyLinkServiceData.errorCode)); + } + + public static void setRileyLinkBLE(RileyLinkBLE rileyLinkBLEIn) { rileyLinkBLE = rileyLinkBLEIn; } @@ -52,38 +96,142 @@ public class RileyLinkUtil { return rileyLinkBLE; } + public static RileyLinkServiceData getRileyLinkServiceData() { return rileyLinkServiceData; } + public static void setRileyLinkServiceData(RileyLinkServiceData rileyLinkServiceData) { RileyLinkUtil.rileyLinkServiceData = rileyLinkServiceData; } - public static void setCurrentTask(ServiceTask task) { - // FIXME - } - - public static void finishCurrentTask(ServiceTask task) { - // FIXME - } - - public static void addHistoryEntry(RLHistoryItem rlHistoryItem) { - historyRileyLink.add(rlHistoryItem); - } public static void setPumpType(PumpType pumpType) { RileyLinkUtil.pumpType = pumpType; } + public static void setPumpStatus(MedtronicPumpStatus medtronicPumpStatus) { RileyLinkUtil.medtronicPumpStatus = medtronicPumpStatus; } + // public static void addHistoryEntry(RLHistoryItem rlHistoryItem) { + // historyRileyLink.add(rlHistoryItem); + // } - public static MedtronicPumpStatus getPumpStatus() { + + public static MedtronicPumpStatus getMedtronicPumpStatus() { return medtronicPumpStatus; } + + + public static boolean hasPumpBeenTunned() { + return rileyLinkServiceData.tuneUpDone; + } + + + public static void tuneUpPump() { + rileyLinkService.doTunePump(); // FIXME thread + } + + + public static void setRileyLinkService(RileyLinkService rileyLinkService) { + RileyLinkUtil.rileyLinkService = rileyLinkService; + } + + + public static RileyLinkService getRileyLinkService() { + return RileyLinkUtil.rileyLinkService; + } + + + public static void setRileyLinkCommunicationManager(RileyLinkCommunicationManager rileyLinkCommunicationManager) { + RileyLinkUtil.rileyLinkCommunicationManager = rileyLinkCommunicationManager; + } + + + public static RileyLinkCommunicationManager getRileyLinkCommunicationManager() { + return rileyLinkCommunicationManager; + } + + + public static boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { + return rileyLinkService.sendNotification(notification, clientHashcode); + } + + + static ServiceTask currentTask; + + + public static void setCurrentTask(ServiceTask task) { + if (currentTask == null) { + currentTask = task; + } else { + LOG.error("setCurrentTask: Cannot replace current task"); + } + } + + + public static void finishCurrentTask(ServiceTask task) { + if (task != currentTask) { + LOG.error("finishCurrentTask: task does not match"); + } + // hack to force deep copy of transport contents + ServiceTransport transport = task.getServiceTransport().clone(); + + if (transport.hasServiceResult()) { + sendServiceTransportResponse(transport, transport.getServiceResult()); + } + currentTask = null; + } + + + public static void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) { + // get the key (hashcode) of the client who requested this + Integer clientHashcode = transport.getSenderHashcode(); + // make a new bundle to send as the message data + transport.setServiceResult(serviceResult); + // FIXME + //transport.setTransportType(RT2Const.IPC.MSG_ServiceResult); + //rileyLinkIPCConnection.sendTransport(transport, clientHashcode); + } + + +// public static void setRileyLinkIPCConnection(RileyLinkIPCConnection rileyLinkIPCConnection) { +// RileyLinkUtil.rileyLinkIPCConnection = rileyLinkIPCConnection; +// } + + + public static boolean isModelSet() { + return RileyLinkUtil.medtronicPumpModel != null; + } + + + public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) { + if (medtronicPumpModel != null && medtronicPumpModel != MedtronicDeviceType.Unknown_Device) { + RileyLinkUtil.medtronicPumpModel = medtronicPumpModel; + } + } + + + public static MedtronicDeviceType getMedtronicPumpModel() { + return medtronicPumpModel; + } + + + public static void setRileyLinkTargetFrequency(RileyLinkTargetFrequency rileyLinkTargetFrequency) { + RileyLinkUtil.rileyLinkTargetFrequency = rileyLinkTargetFrequency; + } + + + public static RileyLinkTargetFrequency getRileyLinkTargetFrequency() { + return rileyLinkTargetFrequency; + } + + public static MedtronicPumpStatus getPumpStatus() { + return pumpStatus; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java index 20658e8664..8ad6aacd27 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble; -import android.content.Context; import android.os.SystemClock; import org.slf4j.Logger; @@ -8,10 +7,15 @@ import org.slf4j.LoggerFactory; import java.util.UUID; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.GattAttributes; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioResponse; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.CC111XRegister; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RFSpyCommand; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RXFilterMode; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.operations.BLECommOperationResult; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; @@ -24,47 +28,30 @@ public class RFSpy { private static final Logger LOG = LoggerFactory.getLogger(RFSpy.class); - public static final byte RFSPY_GET_STATE = 1; - public static final byte RFSPY_GET_VERSION = 2; - public static final byte RFSPY_GET_PACKET = 3; // aka Listen, receive - public static final byte RFSPY_SEND = 4; - public static final byte RFSPY_SEND_AND_LISTEN = 5; - public static final byte RFSPY_UPDATE_REGISTER = 6; - public static final byte RFSPY_RESET = 7; public static final long RILEYLINK_FREQ_XTAL = 24000000; - public static final byte CC111X_REG_FREQ2 = 0x09; - public static final byte CC111X_REG_FREQ1 = 0x0A; - public static final byte CC111X_REG_FREQ0 = 0x0B; - public static final byte CC111X_MDMCFG4 = 0x0C; - public static final byte CC111X_MDMCFG3 = 0x0D; - public static final byte CC111X_MDMCFG2 = 0x0E; - public static final byte CC111X_MDMCFG1 = 0x0F; - public static final byte CC111X_MDMCFG0 = 0x10; - public static final byte CC111X_AGCCTRL2 = 0x17; - public static final byte CC111X_AGCCTRL1 = 0x18; - public static final byte CC111X_AGCCTRL0 = 0x19; - public static final byte CC111X_FREND1 = 0x1A; - public static final byte CC111X_FREND0 = 0x1B; - public static final int EXPECTED_MAX_BLUETOOTH_LATENCY_MS = 1500; + public static final int EXPECTED_MAX_BLUETOOTH_LATENCY_MS = 7500; // 1500 private RileyLinkBLE rileyLinkBle; private RFSpyReader reader; - private Context context; - UUID radioServiceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); - UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); - UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION); - UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT); + private int previousRegion = 0; + private RileyLinkTargetFrequency selectedTargetFrequency; + + private UUID radioServiceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); + private UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); + private UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION); + private UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT); - public RFSpy(Context context, RileyLinkBLE rileyLinkBle) { - this.context = context; + public RFSpy(RileyLinkBLE rileyLinkBle) { this.rileyLinkBle = rileyLinkBle; - reader = new RFSpyReader(context, rileyLinkBle); + //this.rileyLinkBle.setRFSpy(this); + reader = new RFSpyReader(rileyLinkBle); } + // Call this after the RL services are discovered. // Starts an async task to read when data is available public void startReader() { @@ -77,12 +64,14 @@ public class RFSpy { reader.start(); } + // Call this from the "response count" notification handler. public void newDataIsAvailable() { // pass the message to the reader (which should be internal to RFSpy) reader.newDataIsAvailable(); } + // This gets the version from the BLE113, not from the CC1110. // I.e., this gets the version from the BLE interface, not from the radio. public String getVersion() { @@ -95,6 +84,7 @@ public class RFSpy { } } + // The caller has to know how long the RFSpy will be busy with what was sent to it. private RFSpyResponse writeToData(byte[] bytes, int responseTimeout_ms) { SystemClock.sleep(100); @@ -138,8 +128,29 @@ public class RFSpy { return resp; } + private byte[] getByteArray(byte... input) { + return input; + } + + private byte[] getCommandArray(RFSpyCommand command, byte[] body) { + int bodyLength = body == null ? 0 : body.length; + + byte[] output = new byte[bodyLength + 1]; + + output[0] = command.code; + + if (body != null) { + for (int i = 0; i < body.length; i++) { + output[i + 1] = body[i]; + } + } + + return output; + } + + public RFSpyResponse getRadioVersion() { - RFSpyResponse resp = writeToData(new byte[]{RFSPY_GET_VERSION}, 1000); + RFSpyResponse resp = writeToData(getCommandArray(RFSpyCommand.GetVersion, null), 1000); if (resp == null) { LOG.error("getRadioVersion returned null"); } @@ -155,78 +166,112 @@ public class RFSpy { return resp; } + + public RFSpyResponse transmit(RadioPacket radioPacket) { + + return transmit(radioPacket, (byte) 0, (byte) 0, (byte) 0xFF); + } + + public RFSpyResponse transmit(RadioPacket radioPacket, byte sendChannel, byte repeatCount, byte delay_ms) { // append checksum, encode data, send it. - byte[] fullPacket = ByteUtil.concat(new byte[]{RFSPY_SEND, sendChannel, repeatCount, delay_ms}, radioPacket.getEncoded()); - RFSpyResponse response = writeToData(fullPacket, repeatCount * delay_ms); + byte[] fullPacket = ByteUtil.concat(getCommandArray(RFSpyCommand.Send, getByteArray(sendChannel, repeatCount, delay_ms)), radioPacket.getEncoded()); + RFSpyResponse response = writeToData(fullPacket, delay_ms + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); return response; } + public RFSpyResponse receive(byte listenChannel, int timeout_ms, byte retryCount) { int receiveDelay = timeout_ms * (retryCount + 1); - byte[] listen = {RFSPY_GET_PACKET, listenChannel, - (byte) ((timeout_ms >> 24) & 0x0FF), - (byte) ((timeout_ms >> 16) & 0x0FF), - (byte) ((timeout_ms >> 8) & 0x0FF), - (byte) (timeout_ms & 0x0FF), - retryCount}; + byte[] listen = getCommandArray(RFSpyCommand.GetPacket, getByteArray(listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), retryCount)); return writeToData(listen, receiveDelay); } + public RFSpyResponse transmitThenReceive(RadioPacket pkt, int timeout_ms) { return transmitThenReceive(pkt, (byte) 0, (byte) 0, (byte) 0, (byte) 0, timeout_ms, (byte) 0); } + public RFSpyResponse transmitThenReceive(RadioPacket pkt, byte sendChannel, byte repeatCount, byte delay_ms, byte listenChannel, int timeout_ms, byte retryCount) { int sendDelay = repeatCount * delay_ms; int receiveDelay = timeout_ms * (retryCount + 1); - byte[] sendAndListen = {RFSPY_SEND_AND_LISTEN, sendChannel, repeatCount, delay_ms, listenChannel, - (byte) ((timeout_ms >> 24) & 0x0FF), - (byte) ((timeout_ms >> 16) & 0x0FF), - (byte) ((timeout_ms >> 8) & 0x0FF), - (byte) (timeout_ms & 0x0FF), - retryCount}; + byte[] sendAndListen = getCommandArray(RFSpyCommand.SendAndListen, getByteArray(sendChannel, repeatCount, delay_ms, listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), (byte) retryCount)); byte[] fullPacket = ByteUtil.concat(sendAndListen, pkt.getEncoded()); return writeToData(fullPacket, sendDelay + receiveDelay + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); } - public RFSpyResponse updateRegister(byte addr, byte val) { - byte[] updateRegisterPkt = new byte[]{RFSPY_UPDATE_REGISTER, addr, val}; + + public RFSpyResponse updateRegister(CC111XRegister reg, int val) { + byte[] updateRegisterPkt = getCommandArray(RFSpyCommand.UpdateRegister, getByteArray(reg.value, (byte) val)); RFSpyResponse resp = writeToData(updateRegisterPkt, EXPECTED_MAX_BLUETOOTH_LATENCY_MS); return resp; } + public void setBaseFrequency(double freqMHz) { int value = (int) (freqMHz * 1000000 / ((double) (RILEYLINK_FREQ_XTAL) / Math.pow(2.0, 16.0))); - updateRegister(CC111X_REG_FREQ0, (byte) (value & 0xff)); - updateRegister(CC111X_REG_FREQ1, (byte) ((value >> 8) & 0xff)); - updateRegister(CC111X_REG_FREQ2, (byte) ((value >> 16) & 0xff)); + updateRegister(CC111XRegister.freq0, (byte) (value & 0xff)); + updateRegister(CC111XRegister.freq1, (byte) ((value >> 8) & 0xff)); + updateRegister(CC111XRegister.freq2, (byte) ((value >> 16) & 0xff)); LOG.warn("Set frequency to {}", freqMHz); + + configureRadioForRegion(RileyLinkUtil.getRileyLinkTargetFrequency()); } -// func configureRadio(for region: PumpRegion) throws { -// try session.resetRadioConfig() -// -// switch region { -// case .worldWide: -// //try session.updateRegister(.mdmcfg4, value: 0x59) -// try setRXFilterMode(.wide) -// //try session.updateRegister(.mdmcfg3, value: 0x66) -// //try session.updateRegister(.mdmcfg2, value: 0x33) -// try session.updateRegister(.mdmcfg1, value: 0x62) -// try session.updateRegister(.mdmcfg0, value: 0x1A) -// try session.updateRegister(.deviatn, value: 0x13) -// case .northAmerica: -// //try session.updateRegister(.mdmcfg4, value: 0x99) -// try setRXFilterMode(.narrow) -// //try session.updateRegister(.mdmcfg3, value: 0x66) -// //try session.updateRegister(.mdmcfg2, value: 0x33) -// try session.updateRegister(.mdmcfg1, value: 0x61) -// try session.updateRegister(.mdmcfg0, value: 0x7E) -// try session.updateRegister(.deviatn, value: 0x15) -// } -// } + private void configureRadioForRegion(RileyLinkTargetFrequency frequency) { + + // we update registers only on first run, or if region changed + if (selectedTargetFrequency == frequency) + return; + + switch (frequency) { + case Medtronic_WorldWide: { + //updateRegister(CC111X_MDMCFG4, (byte) 0x59); + setRXFilterMode(RXFilterMode.Wide); + //updateRegister(CC111X_MDMCFG3, (byte) 0x66); + //updateRegister(CC111X_MDMCFG2, (byte) 0x33); + updateRegister(CC111XRegister.mdmcfg1, 0x62); + updateRegister(CC111XRegister.mdmcfg0, 0x1A); + updateRegister(CC111XRegister.deviatn, 0x13); + } + break; + + case Medtronic_US: { + //updateRegister(CC111X_MDMCFG4, (byte) 0x99); + setRXFilterMode(RXFilterMode.Narrow); + //updateRegister(CC111X_MDMCFG3, (byte) 0x66); + //updateRegister(CC111X_MDMCFG2, (byte) 0x33); + updateRegister(CC111XRegister.mdmcfg1, 0x61); + updateRegister(CC111XRegister.mdmcfg0, 0x7E); + updateRegister(CC111XRegister.deviatn, 0x15); + + } + break; + + case Omnipod: { + LOG.debug("No region configuration for RfSpy and {}", frequency.name()); + } + + default: + // no configuration + break; + + } + + this.selectedTargetFrequency = frequency; + } + + + private void setRXFilterMode(RXFilterMode mode) { + + byte drate_e = (byte) 0x9; // exponent of symbol rate (16kbps) + byte chanbw = mode.value; + + updateRegister(CC111XRegister.mdmcfg4, (byte) (chanbw | drate_e)); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpyReader.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpyReader.java index 87db6f01d7..9d8cfff559 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpyReader.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpyReader.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble; -import android.content.Context; import android.os.AsyncTask; import android.os.SystemClock; @@ -24,7 +23,7 @@ public class RFSpyReader { private static final Logger LOG = LoggerFactory.getLogger(RFSpyReader.class); - private Context context; + //private Context context; private RileyLinkBLE rileyLinkBle; private Semaphore waitForRadioData = new Semaphore(0, true); AsyncTask readerTask; @@ -32,16 +31,19 @@ public class RFSpyReader { private int acquireCount = 0; private int releaseCount = 0; - public RFSpyReader(Context context, RileyLinkBLE rileyLinkBle) { - this.context = context; + + public RFSpyReader(/*Context context,*/ RileyLinkBLE rileyLinkBle) { + //this.context = context; this.rileyLinkBle = rileyLinkBle; } - public void init(Context context, RileyLinkBLE rileyLinkBLE) { - this.context = context; + + public void init(/*Context context,*/ RileyLinkBLE rileyLinkBLE) { + //this.context = context; this.rileyLinkBle = rileyLinkBLE; } + public void setRileyLinkBle(RileyLinkBLE rileyLinkBle) { if (readerTask != null) { readerTask.cancel(true); @@ -49,9 +51,10 @@ public class RFSpyReader { this.rileyLinkBle = rileyLinkBle; } + // This timeout must be coordinated with the length of the RFSpy radio operation or Bad Things Happen. public byte[] poll(int timeout_ms) { - LOG.debug(ThreadUtil.sig() + "Entering poll at t==" + SystemClock.uptimeMillis() + ", timeout is " + timeout_ms + " mDataQueue size is " + mDataQueue.size()); + LOG.trace(ThreadUtil.sig() + "Entering poll at t==" + SystemClock.uptimeMillis() + ", timeout is " + timeout_ms + " mDataQueue size is " + mDataQueue.size()); if (mDataQueue.isEmpty()) try { // block until timeout or data available. @@ -69,14 +72,16 @@ public class RFSpyReader { return null; } + // Call this from the "response count" notification handler. public void newDataIsAvailable() { releaseCount++; - LOG.debug(ThreadUtil.sig() + "waitForRadioData released(count=" + releaseCount + ") at t=" + SystemClock.uptimeMillis()); + LOG.trace(ThreadUtil.sig() + "waitForRadioData released(count=" + releaseCount + ") at t=" + SystemClock.uptimeMillis()); waitForRadioData.release(); } + public void start() { readerTask = new AsyncTask() { @Override @@ -88,7 +93,7 @@ public class RFSpyReader { try { acquireCount++; waitForRadioData.acquire(); - LOG.debug(ThreadUtil.sig() + "waitForRadioData acquired (count=" + acquireCount + ") at t=" + SystemClock.uptimeMillis()); + LOG.trace(ThreadUtil.sig() + "waitForRadioData acquired (count=" + acquireCount + ") at t=" + SystemClock.uptimeMillis()); SystemClock.sleep(100); SystemClock.sleep(1); result = rileyLinkBle.readCharacteristic_blocking(serviceUUID, radioDataUUID); @@ -96,7 +101,7 @@ public class RFSpyReader { if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { // only data up to the first null is valid - for (int i = 0; i < result.value.length; i++) { + for(int i = 0; i < result.value.length; i++) { if (result.value[i] == 0) { result.value = ByteUtil.substring(result.value, 0, i); break; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java index 6f0a616eff..8a216f6553 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java @@ -57,17 +57,19 @@ public class RFTools { return rval; } + public static ArrayList fromBytes(byte[] data) { ArrayList rval = new ArrayList<>(); - for (int i = 0; i < data.length; i++) { + for(int i = 0; i < data.length; i++) { rval.add(data[i]); } return rval; } + public static byte[] toBytes(ArrayList data) { byte[] rval = new byte[data.size()]; - for (int i = 0; i < data.size(); i++) { + for(int i = 0; i < data.size(); i++) { rval[i] = data.get(i); } return rval; @@ -110,9 +112,10 @@ public class RFTools { public static final byte[] codes = new byte[]{21, 49, 50, 35, 52, 37, 38, 22, 26, 25, 42, 11, 44, 13, 14, 28}; + /* O(n) lookup. Run on an O(n) translation of a byte-stream, gives O(n**2) performance. Sigh. */ public static int codeIndex(byte b) { - for (int i = 0; i < codes.length; i++) { + for(int i = 0; i < codes.length; i++) { if (b == codes[i]) { return i; } @@ -120,6 +123,7 @@ public class RFTools { return -1; } + public static byte[] encode4b6b(byte[] data) { if ((data.length % 2) != 0) { // LOG.error("Warning: data is odd number of bytes"); @@ -131,7 +135,7 @@ public class RFTools { int acc = 0; int bitcount = 0; int i; - for (i = 0; i < inData.size(); i++) { + for(i = 0; i < inData.size(); i++) { acc <<= 6; acc |= codes[(inData.get(i) >> 4) & 0x0f]; bitcount += 6; @@ -171,6 +175,7 @@ public class RFTools { } + public static void test() { /* {0xa7} -> {0xa9, 0x60} @@ -212,6 +217,7 @@ public class RFTools { return; } + public static byte[] decode4b6b(byte[] raw) throws NumberFormatException { /* if ((raw.length % 2) != 0) { @@ -224,7 +230,7 @@ public class RFTools { int x = 0; //Log.w(TAG,"decode4b6b: untested code"); //Log.w(TAG,String.format("Decoding %d bytes: %s",raw.length,ByteUtil.shortHexString(raw))); - for (int i = 0; i < raw.length; i++) { + for(int i = 0; i < raw.length; i++) { int unsignedValue = raw[i]; if (unsignedValue < 0) { unsignedValue += 256; @@ -274,6 +280,7 @@ public class RFTools { return rval; } + public static String toHexString(byte[] array) { return toHexString(array, 0, array.length); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java index 1a79cecd69..57bf2137f4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java @@ -9,9 +9,7 @@ import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.content.Intent; import android.os.SystemClock; -import android.support.v4.content.LocalBroadcastManager; import android.widget.Toast; import org.apache.commons.lang3.StringUtils; @@ -30,11 +28,14 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.operations import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.operations.CharacteristicReadOperation; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.operations.CharacteristicWriteOperation; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.operations.DescriptorWriteOperation; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpCommon.utils.ThreadUtil; /** * Created by geoff on 5/26/16. + * Added: State handling, configuration of RF for different configuration ranges, connection handling */ public class RileyLinkBLE { @@ -62,7 +63,6 @@ public class RileyLinkBLE { this.context = context; this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - //this.bluetoothAdapter = bluetoothAdapter; LOG.debug("BT Adapter: " + this.bluetoothAdapter); bluetoothGattCallback = new BluetoothGattCallback() { @@ -70,7 +70,7 @@ public class RileyLinkBLE { public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); if (gattDebugEnabled) { - LOG.debug(ThreadUtil.sig() + "onCharacteristicChanged " + GattAttributes.lookup(characteristic.getUuid()) + " " + HexDump.toHexString(characteristic.getValue())); + LOG.trace(ThreadUtil.sig() + "onCharacteristicChanged " + GattAttributes.lookup(characteristic.getUuid()) + " " + HexDump.toHexString(characteristic.getValue())); if (characteristic.getUuid().equals(UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT))) { LOG.debug("Response Count is " + HexDump.toHexString(characteristic.getValue())); } @@ -88,7 +88,7 @@ public class RileyLinkBLE { final String statusMessage = getGattStatusMessage(status); if (gattDebugEnabled) { - LOG.debug(ThreadUtil.sig() + "onCharacteristicRead (" + GattAttributes.lookup(characteristic.getUuid()) + ") " + statusMessage + ":" + HexDump.toHexString(characteristic.getValue())); + LOG.trace(ThreadUtil.sig() + "onCharacteristicRead (" + GattAttributes.lookup(characteristic.getUuid()) + ") " + statusMessage + ":" + HexDump.toHexString(characteristic.getValue())); } mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(), characteristic.getValue()); } @@ -100,7 +100,7 @@ public class RileyLinkBLE { final String uuidString = GattAttributes.lookup(characteristic.getUuid()); if (gattDebugEnabled) { - LOG.debug(ThreadUtil.sig() + "onCharacteristicWrite " + getGattStatusMessage(status) + " " + uuidString + " " + HexDump.toHexString(characteristic.getValue())); + LOG.trace(ThreadUtil.sig() + "onCharacteristicWrite " + getGattStatusMessage(status) + " " + uuidString + " " + HexDump.toHexString(characteristic.getValue())); } mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(), characteristic.getValue()); } @@ -128,18 +128,24 @@ public class RileyLinkBLE { } else if (newState == BluetoothProfile.STATE_DISCONNECTING) { stateMessage = "DISCONNECTING"; } else { - stateMessage = "UNKNOWN (" + newState + ")"; + stateMessage = "UNKNOWN newState (" + newState + ")"; } LOG.warn("onConnectionStateChange " + getGattStatusMessage(status) + " " + stateMessage); } if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(RileyLinkConst.Intents.BluetoothConnected)); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected); + } else if ((newState == BluetoothProfile.STATE_CONNECTING) || // + (newState == BluetoothProfile.STATE_DISCONNECTING)) { + //LOG.debug("We are in {} state.", status == BluetoothProfile.STATE_CONNECTING ? "Connecting" : "Disconnecting"); + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkDisconnected); + if (manualDisconnect) + close(); + LOG.warn("RileyLink Disconnected."); } else { - LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(RileyLinkConst.Intents.BluetoothDisconnected)); - disconnect(); - LOG.warn("Cannot establish Bluetooth connection."); + LOG.warn("Some other state: (status={},newState={})", status, newState); } } @@ -197,8 +203,6 @@ public class RileyLinkBLE { if (status == BluetoothGatt.GATT_SUCCESS) { final List services = gatt.getServices(); - // TODO: in here, we need to determine if this Bluetooth device is a RileyLink with appropriate - // software (subg_rfspy) and set mIsConnected if the GATT is ok. boolean rileyLinkFound = false; @@ -217,8 +221,18 @@ public class RileyLinkBLE { if (gattDebugEnabled) { LOG.warn("onServicesDiscovered " + getGattStatusMessage(status)); } - mIsConnected = true; - RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkReady); + + LOG.warn("Gatt device is RileyLink device: " + rileyLinkFound); + + if (rileyLinkFound) { + mIsConnected = true; + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkReady); + //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_BLE_RileyLinkReady), null); + } else { + mIsConnected = false; + RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkError, RileyLinkError.DeviceIsNotRileyLink); + } + } else { LOG.error("onServicesDiscovered " + getGattStatusMessage(status)); RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkGattFailed); @@ -250,6 +264,7 @@ public class RileyLinkBLE { return false; } + public BluetoothDevice getRileyLinkDevice() { return this.rileyLinkDevice; } @@ -326,7 +341,7 @@ public class RileyLinkBLE { public void findRileyLink(String RileyLinkAddress) { - LOG.debug("Rileylink address: " + RileyLinkAddress); + LOG.debug("RileyLink address: " + RileyLinkAddress); // Must verify that this is a valid MAC, or crash. rileyLinkDevice = bluetoothAdapter.getRemoteDevice(RileyLinkAddress); @@ -349,6 +364,9 @@ public class RileyLinkBLE { } + boolean manualDisconnect = false; + + public void disconnect() { mIsConnected = false; LOG.warn("Closing GATT connection"); @@ -356,6 +374,15 @@ public class RileyLinkBLE { if (bluetoothConnectionGatt != null) { // Not sure if to disconnect or to close first.. bluetoothConnectionGatt.disconnect(); + manualDisconnect = true; + //bluetoothConnectionGatt.close(); + //bluetoothConnectionGatt = null; + } + } + + + public void close() { + if (bluetoothConnectionGatt != null) { bluetoothConnectionGatt.close(); bluetoothConnectionGatt = null; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioPacket.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioPacket.java index 9bd336ae2d..e393a2a229 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioPacket.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioPacket.java @@ -11,14 +11,21 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC; public class RadioPacket { protected byte[] pkt; + public RadioPacket(byte[] pkt) { this.pkt = pkt; } + public byte[] getRaw() { return pkt; } + public byte[] getWithCRC() { + byte[] withCRC = ByteUtil.concat(pkt, CRC.crc8(pkt)); + return withCRC; + } + public byte[] getEncoded() { byte[] withCRC = ByteUtil.concat(pkt, CRC.crc8(pkt)); byte[] encoded = RFTools.encode4b6b(withCRC); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java index 6ea1bd8445..a904d4994b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java @@ -29,6 +29,7 @@ public class RadioResponse { init(rxData); } + public boolean isValid() { if (!decodedOK) { return false; @@ -41,6 +42,7 @@ public class RadioResponse { return false; } + public void init(byte[] rxData) { if (rxData == null) { return; @@ -67,6 +69,7 @@ public class RadioResponse { } } + public byte[] getPayload() { return decodedPayload; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/CC111XRegister.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/CC111XRegister.java new file mode 100644 index 0000000000..9896e85cac --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/CC111XRegister.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 21/05/2018. + */ + +public enum CC111XRegister { + + sync1(0x00), // + sync0(0x01), // + pktlen(0x02), // + pktctrl1(0x03), // + pktctrl0(0x04), // + fsctrl1(0x07), // + freq2(0x09), // + freq1(0x0a), // + freq0(0x0b), // + mdmcfg4(0x0c), // + mdmcfg3(0x0d), // + mdmcfg2(0x0e), // + mdmcfg1(0x0f), // + mdmcfg0(0x10), // + deviatn(0x11), // + mcsm0(0x14), // + foccfg(0x15), // + agcctrl2(0x17), // + agcctrl1(0x18), // + agcctrl0(0x19), // + frend1(0x1a), // + frend0(0x1b), // + fscal3(0x1c), // + fscal2(0x1d), // + fscal1(0x1e), // + fscal0(0x1f), // + test1(0x24), // + test0(0x25), // + paTable0(0x2e), // + + ; + public byte value; + + + CC111XRegister(int value) { + this.value = (byte) value; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java new file mode 100644 index 0000000000..50d5ee014e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 22/05/2018. + */ + +public enum RFSpyCommand { + + GetState(1), // + GetVersion(2), // + GetPacket(3), // aka Listen, receive + Send(4), // + SendAndListen(5), // + UpdateRegister(6), // + Reset(7), // + + ; + + public byte code; + + + RFSpyCommand(int code) { + this.code = (byte) code; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java new file mode 100644 index 0000000000..dc8907745a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 5/6/18. + */ +public interface RLMessage { + + byte[] getTxData(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessageType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessageType.java new file mode 100644 index 0000000000..607bac8a5d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessageType.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 5/6/18. + */ + +public enum RLMessageType { + PowerOn, // for powering on the pump (wakeup) + ReadSimpleData, // for checking if pump is readable (for Medtronic we can use GetModel) + ; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RXFilterMode.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RXFilterMode.java new file mode 100644 index 0000000000..eb200a00ed --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RXFilterMode.java @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 21/05/2018. + */ + +public enum RXFilterMode { + + Wide(0x50), // + Narrow(0x90) // + ; + + public byte value; + + + RXFilterMode(int value) { + this.value = (byte) value; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java new file mode 100644 index 0000000000..3a0ac72dd0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 5/19/18. + */ + +public enum RileyLinkTargetDevice { + MedtronicPump, // + Omnipod, // + ; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java new file mode 100644 index 0000000000..2194080f44 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; + +/** + * Created by andy on 6/7/18. + */ + +public enum RileyLinkTargetFrequency { + + Medtronic_WorldWide(868.25, 868.65, 0.05), // + Medtronic_US(916.45, 916.80, 0.05), // + Omnipod(416.00, 417.00, 0.05), // + ; + + double minFrequency; + double maxFrequency; + double step; + + + RileyLinkTargetFrequency(double minFrequency, double maxFrequency, double step) { + this.minFrequency = minFrequency; + this.maxFrequency = maxFrequency; + this.step = step; + } + + + public double[] getScanFrequencies() { + double diff = maxFrequency - minFrequency; + int count = (int) (diff / step); + + double freq[] = new double[count]; + + for(int i = 0; i < count; i++) { + freq[i] = (minFrequency + (i * step)); + } + + return freq; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/data/RLHistoryItem.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/data/RLHistoryItem.java index f62603db29..66f7caf4e9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/data/RLHistoryItem.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/data/RLHistoryItem.java @@ -1,10 +1,9 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data; -import java.util.Calendar; -import java.util.GregorianCalendar; +import org.joda.time.LocalDateTime; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkErrorCode; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; /** * Created by andy on 5/19/18. @@ -12,38 +11,29 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyL public class RLHistoryItem { - String dateTimeString; - long dateTime; - GregorianCalendar gregorianCalendar; - RileyLinkServiceState serviceState; - RileyLinkErrorCode errorCode; + private LocalDateTime dateTime; + private RileyLinkServiceState serviceState; + private RileyLinkError errorCode; - // 2010 10 11 12 30 00 - - public RLHistoryItem(GregorianCalendar gregorianCalendar, RileyLinkServiceState serviceState, RileyLinkErrorCode errorCode) { - this.dateTime = gregorianCalendar.get(Calendar.SECOND) // - + gregorianCalendar.get(Calendar.MINUTE) * 100 // - + gregorianCalendar.get(Calendar.HOUR_OF_DAY) * 10000 - + gregorianCalendar.get(Calendar.DAY_OF_MONTH) * 1000000 - + (gregorianCalendar.get(Calendar.MONTH) + 1) * 100000000 - + gregorianCalendar.get(Calendar.YEAR) * 10000000000L; - - this.dateTimeString = "" + getNumber(gregorianCalendar.get(Calendar.DAY_OF_MONTH)) + "." + // - getNumber(gregorianCalendar.get(Calendar.MONTH) + 1) + "." + // - gregorianCalendar.get(Calendar.YEAR) + " " + // - getNumber(gregorianCalendar.get(Calendar.HOUR_OF_DAY)) + ":" + // - getNumber(gregorianCalendar.get(Calendar.MINUTE)) + ":" + // - getNumber(gregorianCalendar.get(Calendar.SECOND)); // + public RLHistoryItem(RileyLinkServiceState serviceState, RileyLinkError errorCode) { + this.dateTime = new LocalDateTime(); this.serviceState = serviceState; this.errorCode = errorCode; } - public String getNumber(int number) { - if (number > 9) - return "" + number; - else - return "0" + number; + public LocalDateTime getDateTime() { + return dateTime; + } + + + public RileyLinkServiceState getServiceState() { + return serviceState; + } + + + public RileyLinkError getErrorCode() { + return errorCode; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkErrorCode.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java similarity index 68% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkErrorCode.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java index 701c572738..8130bc9f4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkErrorCode.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java @@ -1,15 +1,18 @@ -package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service; +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs; /** * Created by andy on 14/05/2018. */ -public enum RileyLinkErrorCode { +public enum RileyLinkError { ParametersNotSetOrInvalid, // GattDiscoveryFailed, // TuneUpOfPumpFailed, // UnableToObtainBluetoothAdapter, // BluetoothDisabled, // + GattDeviceNotFound, // + RileyLinkUnreachable, // + DeviceIsNotRileyLink, // } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java new file mode 100644 index 0000000000..c52334179f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs; + +/** + * Created by andy on 14/05/2018. + */ + +public enum RileyLinkServiceState { + + NotStarted, // + + // Bluetooth + BluetoothInitializing, // (S) init BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothError) + BluetoothNotAvailable, // (E) BT not available, would happen only if device has no BT + BluetoothError, // (E) if BT gets disabled ( -> EnableBluetooth) + BluetoothReady, // (OK) + + // RileyLink + RileyLinkInitializing, // (S) start Gatt discovery (OK -> RileyLinkReady, Error -> BluetoothEnabled) ?? + RileyLinkError, // (E) + RileyLinkReady, // (OK) if tunning was already done we go to PumpConnectorReady + + // Tunning + TuneUpPump, // (S) + //TuneUpPumpError, // + PumpConnectorError, // either TuneUp Error or pump couldn't not be contacted error + PumpConnectorReady, // (OK) RileyLink Ready for Pump Communication + + //Initializing, // get all parameters required for connection (if not possible -> Disabled, if sucessful -> EnableBluetooth) + + + //EnableBlueTooth, // enable BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothError) + //BlueToothEnabled, // -> InitializeRileyLink + //RileyLinkInitialized, // + + //RileyLinkConnected, // -> TuneUpPump (on 1st), else PumpConnectorReady + + //PumpConnected, // + + + ; + + public static boolean isReady(RileyLinkServiceState serviceState) { + return (serviceState == RileyLinkReady || serviceState == PumpConnectorReady); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/RileyLinkTargetDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java similarity index 62% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/RileyLinkTargetDevice.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java index e640a8a29b..950e102edb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/RileyLinkTargetDevice.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpCommon.defs; +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs; /** * Created by andy on 5/19/18. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java index 3ad346199d..c185b901c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java @@ -6,31 +6,36 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.PowerManager; import android.support.v4.content.LocalBroadcastManager; import android.widget.Toast; -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.InitializePumpManagerTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTask; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTaskExecutor; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.GregorianCalendar; - -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceNotification; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.DiscoverGattServicesTask; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.InitializePumpManagerTask; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst; import info.nightscout.utils.SP; +import static info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil.getRileyLinkCommunicationManager; + /** * Created by andy on 5/6/18. @@ -45,34 +50,40 @@ public abstract class RileyLinkService extends Service { // Our hardware/software connection public RileyLinkBLE rileyLinkBLE; // android-bluetooth management - protected RFSpy rfspy; // interface for xxx Mhz (916MHz) radio. - protected boolean needBluetoothPermission = true; + protected RFSpy rfspy; // interface for RL xxx Mhz radio. + //protected boolean needBluetoothPermission = true; //protected RileyLinkIPCConnection rileyLinkIPCConnection; protected Context context; public RileyLinkCommunicationManager pumpCommunicationManager; protected BroadcastReceiver mBroadcastReceiver; protected RileyLinkServiceData rileyLinkServiceData; + protected RileyLinkTargetFrequency rileyLinkTargetFrequency; - //protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock"; - //protected static volatile PowerManager.WakeLock lockStatic = null; + protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock"; + protected static volatile PowerManager.WakeLock lockStatic = null; - public RileyLinkService() { + public RileyLinkService(Context context) { super(); - this.context = MainApp.instance().getApplicationContext(); + this.context = context; RileyLinkUtil.setContext(this.context); + determineRileyLinkTargetFrequency(); + RileyLinkUtil.setRileyLinkTargetFrequency(rileyLinkTargetFrequency); initRileyLinkServiceData(); } + /** + * You need to determine which frequencies RileyLink will use, and set rileyLinkTargetFrequency + */ + protected abstract void determineRileyLinkTargetFrequency(); + + /** * If you have customized RileyLinkServiceData you need to override this */ public abstract void initRileyLinkServiceData(); -// { -// rileyLinkServiceData = new RileyLinkServiceData(); -// } @Override @@ -94,6 +105,7 @@ public abstract class RileyLinkService extends Service { super.onDestroy(); LOG.error("I die! I die!"); + // FIXME this might not work if (rileyLinkBLE != null) { rileyLinkBLE.disconnect(); // dispose of Gatt (disconnect and close) rileyLinkBLE = null; @@ -106,18 +118,17 @@ public abstract class RileyLinkService extends Service { super.onCreate(); LOG.debug("onCreate"); - RileyLinkUtil.setRileyLinkServiceData(rileyLinkServiceData); + //rileyLinkIPCConnection = new RileyLinkIPCConnection(context); // TODO We might be able to remove this -- Andy + //RileyLinkUtil.setRileyLinkIPCConnection(rileyLinkIPCConnection); - //rileyLinkIPCConnection = new RileyLinkIPCConnection(context); // We might be able to remove this -- Andy - - // get most recently used RileyLink address - rileyLinkServiceData.rileylinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, ""); - - rileyLinkBLE = new RileyLinkBLE(this); - rfspy = new RFSpy(context, rileyLinkBLE); - rfspy.startReader(); - - RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); + // // get most recently used RileyLink address + // rileyLinkServiceData.rileylinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, ""); + // + // rileyLinkBLE = new RileyLinkBLE(this); + // rfspy = new RFSpy(context, rileyLinkBLE); + // rfspy.startReader(); + // + // RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); loadPumpCommunicationManager(); @@ -137,53 +148,122 @@ public abstract class RileyLinkService extends Service { if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) { LOG.warn("serviceLocal.bluetooth_connected"); //rileyLinkIPCConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink), null); - // ServiceTaskExecutor.startTask(new DiscoverGattServicesTask()); - rileyLinkBLE.discoverServices(); - - + ServiceTaskExecutor.startTask(new DiscoverGattServicesTask()); // If this is successful, // We will get a broadcast of RT2Const.serviceLocal.BLE_services_discovered + } else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) { + if (bluetoothAdapter.isEnabled()) { + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothReady, RileyLinkError.RileyLinkUnreachable); + } else { + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); + } + + } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + + LOG.debug("Bluetooth Action State Changed: " + state); + + switch (state) { + case BluetoothAdapter.STATE_OFF: { + LOG.debug("Bluetooth OFF"); + //RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); + } + break; + + + case BluetoothAdapter.STATE_ON: { + LOG.debug("Bluetooth ON"); + //setButtonText("Bluetooth on"); + } + break; + + case BluetoothAdapter.STATE_TURNING_OFF: + case BluetoothAdapter.STATE_TURNING_ON: + break; + } } else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) { LOG.warn("MedtronicConst.Intents.RileyLinkReady"); // FIXME //rileyLinkIPCConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_WakingPump), null); rileyLinkBLE.enableNotifications(); rfspy.startReader(); // call startReader from outside? + + LOG.debug("RfSpy version (BLE113): " + rfspy.getVersion()); + + RFSpyResponse radioVersion = rfspy.getRadioVersion(); + + byte[] response = radioVersion.getRadioResponse().decodedPayload; + + LOG.debug("Response: " + HexDump.toHexStringDisplayable(response)); + + LOG.debug("RfSpy Radio version (CC110): " + StringUtil.fromBytes(radioVersion.getRadioResponse().decodedPayload)); + ServiceTask task = new InitializePumpManagerTask(); ServiceTaskExecutor.startTask(task); LOG.info("Announcing RileyLink open For business"); - } else if (action.equals(RT2Const.serviceLocal.ipcBound)) { + } /*else if (action.equals(RT2Const.serviceLocal.ipcBound)) { // If we still need permission for bluetooth, ask now. // FIXME removed Andy - doesn't do anything -// if (needBluetoothPermission) { -// sendBLERequestForAccess(); -// } + // if (needBluetoothPermission) { + // sendBLERequestForAccess(); + // } - } else if (RT2Const.IPC.MSG_BLE_accessGranted.equals(action)) { + }*/ /*else if (RT2Const.IPC.MSG_BLE_accessGranted.equals(action)) { //initializeLeAdapter(); //bluetoothInit(); } else if (RT2Const.IPC.MSG_BLE_accessDenied.equals(action)) { LOG.error("BLE_Access_Denied recived. Stoping the service."); stopSelf(); // This will stop the service. - } else if (action.equals(RT2Const.IPC.MSG_PUMP_tunePump)) { + } */ else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_tunePump)) { doTunePump(); - } else if (action.equals(RT2Const.IPC.MSG_PUMP_quickTune)) { + } else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_quickTune)) { doTunePump(); } else if (action.startsWith("MSG_PUMP_")) { handlePumpSpecificIntents(intent); - } else if (RT2Const.IPC.MSG_ServiceCommand.equals(action)) { + } else if (RileyLinkConst.IPC.MSG_ServiceCommand.equals(action)) { handleIncomingServiceTransport(intent); - } -// } else -// if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) { -// Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); -// if (bundle != null) { -// ServiceTransport transport = new ServiceTransport(bundle); -// rileyLinkIPCConnection.sendTransport(transport, transport.getSenderHashcode()); -// } else { -// LOG.error("sessionCompleted: no bundle!"); -// } -// } + } /*else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) { + Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); + if (bundle != null) { + ServiceTransport transport = new ServiceTransport(bundle); + //rileyLinkIPCConnection.sendTransport(transport, transport.getSenderHashcode()); + //RileyLinkUtil.send + } else { + LOG.error("sessionCompleted: no bundle!"); + } + }*/ + + /*else + + if (case RT2Const.local.INTENT_serviceConnected: + case RT2Const.local.INTENT_NEW_rileylinkAddressKey: + showIdle(); + /** + * Client MUST send a "UseThisRileylink" message because it asserts that + * the user has given explicit permission to use bluetooth. + * + * We can change the format so that it is a simple "bluetooth OK" message, + * rather than an explicit address of a Rileylink, and the Service can + * use the last known good value. But the kick-off of bluetooth ops must + * come from an Activity. + */ + /* String RileylinkBLEAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, ""); + if (RileylinkBLEAddress.equals("")) { + // TODO: 11/07/2016 @TIM UI message for user + Log.e(TAG, "No Rileylink BLE Address saved in app"); + } else { + //showBusy("Configuring Service", 50); + MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress); + } + break; + case RT2Const.local.INTENT_NEW_pumpIDKey: + MainApp.getServiceClientConnection().sendPUMP_useThisDevice(SP.getString(MedtronicConst.Prefs.PumpSerial, "")); + break; + + */ + + else { LOG.error("Unhandled broadcast: action=" + action); } @@ -195,20 +275,20 @@ public abstract class RileyLinkService extends Service { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(RileyLinkConst.Intents.BluetoothConnected); intentFilter.addAction(RileyLinkConst.Intents.BluetoothDisconnected); - //intentFilter.addAction(RT2Const.serviceLocal.BLE_services_discovered); AAPS - RileyLinkReady - intentFilter.addAction(RT2Const.serviceLocal.ipcBound); - intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessGranted); - intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessDenied); + intentFilter.addAction(RileyLinkConst.Intents.RileyLinkReady); + intentFilter.addAction(RileyLinkConst.Intents.RileyLinkDisconnected); + intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); + //intentFilter.addAction(RT2Const.serviceLocal.ipcBound); + //intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessGranted); + //intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessDenied); //intentFilter.addAction(RT2Const.IPC.MSG_BLE_useThisDevice); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_tunePump); + intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_tunePump); + intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_quickTune); //intentFilter.addAction(RT2Const.IPC.MSG_PUMP_useThisAddress); - - intentFilter.addAction(RT2Const.IPC.MSG_ServiceCommand); - intentFilter.addAction(RT2Const.serviceLocal.INTENT_sessionCompleted); - // after AAPS refactoring - intentFilter.addAction(RileyLinkConst.Intents.RileyLinkReady); - + intentFilter.addAction(RileyLinkConst.IPC.MSG_ServiceCommand); + //intentFilter.addAction(RT2Const.serviceLocal.INTENT_sessionCompleted); addPumpSpecificIntents(intentFilter); @@ -232,19 +312,37 @@ public abstract class RileyLinkService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { LOG.debug("onStartCommand"); - return START_STICKY; +// if (intent != null) { +// PowerManager.WakeLock lock = getLock(this.getApplicationContext()); +// +// if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) { +// lock.acquire(); +// } +// +// // This will end up running onHandleIntent +// super.onStartCommand(intent, flags, startId); +// } else { +// LOG.error("Received null intent?"); +// } + + RileyLinkUtil.setContext(getApplicationContext()); + + //bluetoothInit(); + + //return (START_REDELIVER_INTENT | START_STICKY); + return (START_STICKY); } - protected void bluetoothInit() { + private boolean bluetoothInit() { LOG.debug("bluetoothInit: attempting to get an adapter"); - setServiceState(RileyLinkServiceState.InitializingBluetooth); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothInitializing); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { LOG.error("Unable to obtain a BluetoothAdapter."); - setServiceState(RileyLinkServiceState.BluetoothNotAvailable, RileyLinkErrorCode.UnableToObtainBluetoothAdapter); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.UnableToObtainBluetoothAdapter); } else { if (!bluetoothAdapter.isEnabled()) { @@ -252,19 +350,21 @@ public abstract class RileyLinkService extends Service { sendBLERequestForAccess(); LOG.error("Bluetooth is not enabled."); - setServiceState(RileyLinkServiceState.BlueToothDisabled, RileyLinkErrorCode.BluetoothDisabled); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); } else { - setServiceState(RileyLinkServiceState.BlueToothEnabled); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothReady); + return true; } } + return false; } // returns true if our Rileylink configuration changed public boolean reconfigureRileylink(String deviceAddress) { - setServiceState(RileyLinkServiceState.RileyLinkInitializing); + RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkInitializing); if (rileyLinkBLE.isConnected()) { if (deviceAddress.equals(rileyLinkServiceData.rileylinkAddress)) { @@ -274,7 +374,7 @@ public abstract class RileyLinkService extends Service { LOG.warn("Disconnecting from old RL (" + rileyLinkServiceData.rileylinkAddress + "), reconnecting to new: " + deviceAddress); rileyLinkBLE.disconnect(); // prolly need to shut down listening thread too? - SP.putString(MedtronicConst.Prefs.RileyLinkAddress, deviceAddress); + //SP.putString(MedtronicConst.Prefs.RileyLinkAddress, deviceAddress); rileyLinkServiceData.rileylinkAddress = deviceAddress; rileyLinkBLE.findRileyLink(rileyLinkServiceData.rileylinkAddress); @@ -283,45 +383,21 @@ public abstract class RileyLinkService extends Service { } else { Toast.makeText(context, "Using RL " + deviceAddress, Toast.LENGTH_SHORT).show(); LOG.debug("handleIPCMessage: Using RL " + deviceAddress); - if (bluetoothAdapter == null) { - bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - } - if (bluetoothAdapter != null) { - if (bluetoothAdapter.isEnabled()) { - // FIXME: this may be a long running function: - rileyLinkBLE.findRileyLink(deviceAddress); - // If successful, we will get a broadcast from RileyLinkBLE: RT2Const.serviceLocal.bluetooth_connected - return true; - } else { - LOG.error("Bluetooth is not enabled."); - setServiceState(RileyLinkServiceState.BlueToothDisabled, RileyLinkErrorCode.BluetoothDisabled); + if (RileyLinkUtil.getServiceState() == RileyLinkServiceState.NotStarted) { + if (!bluetoothInit()) { + LOG.error("RileyLink can't get activated, Bluetooth is not functioning correctly. {}", RileyLinkUtil.getError().name()); return false; } - } else { - LOG.error("Failed to get adapter"); - setServiceState(RileyLinkServiceState.BluetoothNotAvailable, RileyLinkErrorCode.UnableToObtainBluetoothAdapter); - return false; } + + rileyLinkBLE.findRileyLink(deviceAddress); + + return true; } } - - protected void setServiceState(RileyLinkServiceState newState) { - setServiceState(newState, null); - } - - - protected void setServiceState(RileyLinkServiceState newState, RileyLinkErrorCode errorCode) { - this.rileyLinkServiceData.serviceState = newState; - - if (errorCode != null) - this.rileyLinkServiceData.errorCode = errorCode; - - RileyLinkUtil.addHistoryEntry(new RLHistoryItem(new GregorianCalendar(), newState, errorCode)); - } - - +// // public synchronized static PowerManager.WakeLock getLock(Context context) { // if (lockStatic == null) { // PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE); @@ -335,23 +411,22 @@ public abstract class RileyLinkService extends Service { public void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) { - - LOG.warn("UNWANTED: {}", "sendServiceTransportResponse"); - // get the key (hashcode) of the client who requested this - Integer clientHashcode = transport.getSenderHashcode(); + /*Integer clientHashcode = transport.getSenderHashcode(); // make a new bundle to send as the message data transport.setServiceResult(serviceResult); // FIXME - transport.setTransportType(RT2Const.IPC.MSG_ServiceResult); + transport.setTransportType(RT2Const.IPC.MSG_ServiceResult); */ //rileyLinkIPCConnection.sendTransport(transport, clientHashcode); + LOG.error("sendServiceTransportResponse not implemented."); } -// public boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { -// //return rileyLinkIPCConnection.sendNotification(notification, clientHashcode); -// return false; -// } + public boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { + //return rileyLinkIPCConnection.sendNotification(notification, clientHashcode); + LOG.error("sendNotification not implemented."); + return false; + } protected void sendBLERequestForAccess() { @@ -364,9 +439,9 @@ public abstract class RileyLinkService extends Service { // FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc. - protected void doTunePump() { + public void doTunePump() { - setServiceState(RileyLinkServiceState.TuneUpPump); + RileyLinkUtil.setServiceState(RileyLinkServiceState.TuneUpPump); double lastGoodFrequency = 0.0d; @@ -376,9 +451,8 @@ public abstract class RileyLinkService extends Service { lastGoodFrequency = rileyLinkServiceData.lastGoodFrequency; } - //double lastGoodFrequency = SP.getFloat(MedtronicConst.Prefs.LastGoodPumpFrequency, 0.0f); double newFrequency; - if (lastGoodFrequency != 0.0) { + if ((lastGoodFrequency > 0.0d) && getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) { LOG.info("Checking for pump near last saved frequency of {}MHz", lastGoodFrequency); // we have an old frequency, so let's start there. newFrequency = pumpCommunicationManager.quickTuneForPump(lastGoodFrequency); @@ -391,8 +465,8 @@ public abstract class RileyLinkService extends Service { LOG.warn("No saved frequency for pump, doing full scan."); // we don't have a saved frequency, so do the full scan. newFrequency = pumpCommunicationManager.tuneForPump(); - } + if ((newFrequency != 0.0) && (newFrequency != lastGoodFrequency)) { LOG.info("Saving new pump frequency of {}MHz", newFrequency); SP.putDouble(MedtronicConst.Prefs.LastGoodPumpFrequency, newFrequency); @@ -403,40 +477,12 @@ public abstract class RileyLinkService extends Service { if (newFrequency == 0.0d) { // error tuning pump, pump not present ?? - //this.errorCode = RileyLinkErrorCode.TuneUpOfPumpFailed; - setServiceState(RileyLinkServiceState.RileyLinkReady, RileyLinkErrorCode.TuneUpOfPumpFailed); + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfPumpFailed); } - } - // PumpInterface - - public boolean isInitialized() { - return this.rileyLinkServiceData.serviceState == RileyLinkServiceState.RileyLinkReady; + public void disconnectRileyLink() { + this.rileyLinkBLE.disconnect(); } - - - public boolean isConnected() { - return this.rileyLinkServiceData.serviceState == RileyLinkServiceState.RileyLinkReady; - } - - public boolean isConnecting() { - return this.rileyLinkServiceData.serviceState != RileyLinkServiceState.RileyLinkReady; - } - - public void connect(String reason) { - bluetoothInit(); - } - - - public void disconnect(String reason) { - - } - - - public void stopConnecting() { - - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java index 278a9ffb2a..8fdb18a22d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service; -import info.nightscout.androidaps.plugins.PumpCommon.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; /** * Created by andy on 16/05/2018. @@ -9,7 +11,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.defs.RileyLinkTargetDevice; public class RileyLinkServiceData { public boolean tuneUpDone = false; - public RileyLinkErrorCode errorCode; + public RileyLinkError errorCode; public RileyLinkServiceState serviceState = RileyLinkServiceState.NotStarted; public String rileylinkAddress; public long lastTuneUpTime = 0L; @@ -21,6 +23,7 @@ public class RileyLinkServiceData { public String pumpID; public byte[] pumpIDBytes; + public RileyLinkServiceData(RileyLinkTargetDevice targetDevice) { this.targetDevice = targetDevice; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceState.java deleted file mode 100644 index 31e534d921..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceState.java +++ /dev/null @@ -1,30 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service; - -/** - * Created by andy on 14/05/2018. - */ - -public enum RileyLinkServiceState { - - NotStarted, // - - - BluetoothNotAvailable, // BT not available, would happen only if device has no BT - Initializing, // get all parameters required for connection (if not possible -> Disabled, if sucessful -> EnableBluetooth) - - BlueToothDisabled, // if BT gets disabled ( -> EnableBluetooth) - EnableBlueTooth, // enable BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothDisabled) - BlueToothEnabled, // -> InitializeRileyLink - RileyLinkInitializing, // start Gatt discovery (OK -> RileyLinkInitialized, Error -> BluetoothEnabled) ?? - RileyLinkInitialized, // - RileyLinkReady, // - RileyLinkConnected, // -> TuneUpPump (on 1st), else PumpConnectorReady - TuneUpPump, // -> PumpConnectorReady - PumpConnectorReady, // - - PumpConnected, // - - - InitializingBluetooth; - -} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceCommand.java similarity index 82% rename from app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceCommand.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceCommand.java index 6878f7b503..b8f4456016 100644 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceCommand.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceCommand.java @@ -1,4 +1,4 @@ -package com.gxwtech.roundtrip2.ServiceData; +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; import android.os.Bundle; @@ -9,37 +9,46 @@ public class ServiceCommand extends ServiceMessage { public ServiceCommand() { map = new Bundle(); } + + // commandID is a string that the client can set on the message. // The service does not use this value, but passes it back with the result // so that the client can identify it. public ServiceCommand(String commandName, String commandID) { init(); - map.putString("command",commandName); - map.putString("commandID",commandID); + map.putString("command", commandName); + map.putString("commandID", commandID); } + + public ServiceCommand(Bundle commandBundle) { if (commandBundle != null) { map = commandBundle; } else { map = new Bundle(); init(); - map.putString("command","(null)"); + map.putString("command", "(null)"); map.putString("commandID", "(null"); } } + @Override public void init() { - map.putString("ServiceMessageType","ServiceCommand"); + map.putString("ServiceMessageType", "ServiceCommand"); } + public String getCommandID() { return map.getString("commandID"); } + + public String getCommandName() { return map.getString("command"); } + public boolean isPumpCommand() { switch (getCommandName()) { case "FetchPumpHistory": diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceMessage.java new file mode 100644 index 0000000000..95bc7ba12e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceMessage.java @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 7/4/16. + *

+ * Base class for all messages passed between service and client + */ +public class ServiceMessage { + protected Bundle map = new Bundle(); + + + public ServiceMessage() { + init(); + } + + + public void init() { + map.putString("ServiceMessageClass", this.getClass().getCanonicalName()); + map.putString("ServiceMessageType", this.getClass().getSimpleName()); + } + + + public Bundle getMap() { + return map; + } + + + public void setMap(Bundle map) { + this.map = map; + } + + + public String getServiceMessageType() { + return map.getString("ServiceMessageType"); + } + + +} diff --git a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceNotification.java similarity index 77% rename from app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceNotification.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceNotification.java index 72a1e81418..a821e25538 100644 --- a/app/src/main/java/com/gxwtech/roundtrip2/ServiceData/ServiceNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceNotification.java @@ -1,16 +1,17 @@ -package com.gxwtech.roundtrip2.ServiceData; +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; import android.os.Bundle; /** * Created by geoff on 7/6/16. - * + *

* These are "one liner" messages between client and service. * Must still be contained within ServiceTransports - * */ public class ServiceNotification extends ServiceMessage { - public ServiceNotification() {} + public ServiceNotification() { + } + public ServiceNotification(Bundle b) { if (b != null) { @@ -22,22 +23,26 @@ public class ServiceNotification extends ServiceMessage { } } + public ServiceNotification(String notificationType) { setNotificationType(notificationType); } + @Override public void init() { super.init(); - map.putString("ServiceMessageType","ServiceNotification"); + map.putString("ServiceMessageType", "ServiceNotification"); } + public void setNotificationType(String notificationType) { map.putString("NotificationType", notificationType); } + public String getNotificationType() { - return map.getString("NotificationType",""); + return map.getString("NotificationType", ""); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceResult.java new file mode 100644 index 0000000000..a688e017e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceResult.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 6/25/16. + */ +public class ServiceResult extends ServiceMessage { + public ServiceResult() { + init(); + } + + + public ServiceResult(Bundle resultBundle) { + if (resultBundle != null) { + setMap(resultBundle); + } else { + init(); + } + } + + + @Override + public void init() { + super.init(); + map.putString("ServiceMessageType", "ServiceResult"); + setServiceResultType(this.getClass().getSimpleName()); + setResultError(0, "Uninitialized ServiceResult"); + } + + + public void setServiceResultType(String serviceResultType) { + map.putString("ServiceResultType", serviceResultType); + } + + + public String getServiceResultType() { + return map.getString("ServiceResultType", "ServiceResult"); + } + + + public void setResultOK() { + map.putString("result", "OK"); + } + + + public void setResultError(int errorCode) { + setResultError(errorCode, getErrorDescription(errorCode)); + } + + + public void setResultError(int errorCode, String errorDescription) { + map.putString("result", "error"); + map.putInt("errorCode", errorCode); + map.putString("errorDescription", errorDescription); + } + + + public static final int ERROR_MALFORMED_PUMP_RESPONSE = 1; + public static final int ERROR_NULL_PUMP_RESPONSE = 2; + public static final int ERROR_INVALID_PUMP_RESPONSE = 3; + public static final int ERROR_PUMP_BUSY = 4; + + + public static final String getErrorDescription(int errorCode) { + switch (errorCode) { + case ERROR_MALFORMED_PUMP_RESPONSE: + return "Malformed Pump Response"; + case ERROR_NULL_PUMP_RESPONSE: + return "Null pump response"; + case ERROR_INVALID_PUMP_RESPONSE: + return "Invalid pump response"; + case ERROR_PUMP_BUSY: + return "A pump command session is already in progress"; + default: + return "Unknown error code (" + errorCode + ")"; + } + } + + + public boolean resultIsOK() { + return ("OK".equals(map.getString("result", ""))); + } + + + public String getErrorDescription() { + return map.getString("errorDescription", ""); + } + + + public String getResult() { + return map.getString("result", ""); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTransport.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransport.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTransport.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransport.java index 7a9d96dd88..75cca7c201 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTransport.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransport.java @@ -1,14 +1,8 @@ -package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; import android.os.Bundle; import android.os.Parcel; -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.ServiceData.ServiceCommand; -import com.gxwtech.roundtrip2.ServiceData.ServiceMessage; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; - /** * Created by geoff on 7/6/16. *

@@ -17,9 +11,14 @@ import com.gxwtech.roundtrip2.ServiceData.ServiceResult; * May also contain result, if the command is completed. */ public class ServiceTransport extends ServiceMessage { + + private ServiceTransportType serviceTransportType = ServiceTransportType.Undefined; + + public ServiceTransport() { } + public ServiceTransport(Bundle b) { if (b != null) { if ("ServiceTransport".equals(b.getString("ServiceMessageType"))) { @@ -30,6 +29,7 @@ public class ServiceTransport extends ServiceMessage { } } + @Override public void init() { super.init(); @@ -38,76 +38,96 @@ public class ServiceTransport extends ServiceMessage { setSenderHashcode(0); } + public void setSenderHashcode(Integer senderHashcode) { map.putInt("senderHashcode", senderHashcode); } + public Integer getSenderHashcode() { - return new Integer(map.getInt("senderHashCode", 0)); + return map.getInt("senderHashCode", 0); } + public void setServiceCommand(ServiceCommand serviceCommand) { map.putBundle("ServiceCommand", serviceCommand.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceCommand; } + public ServiceCommand getServiceCommand() { return new ServiceCommand(map.getBundle("ServiceCommand")); } + public boolean hasServiceCommand() { return (getMap().containsKey("ServiceCommand")); } + // On remote end, this will be converted to the "action" of a local Intent, // so can be used for separating types of messages to different internal handlers. public void setTransportType(String transportType) { map.putString("transportType", transportType); } + public String getTransportType() { return map.getString("transportType", "unknown"); } + public void setServiceResult(ServiceResult serviceResult) { map.putBundle("ServiceResult", serviceResult.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceResult; } + public ServiceResult getServiceResult() { return new ServiceResult(map.getBundle("ServiceResult")); } + public boolean hasServiceResult() { return (getMap().containsKey("ServiceResult")); } + public void setServiceNotification(ServiceNotification notification) { map.putBundle("ServiceNotification", notification.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceNotification; } + public ServiceNotification getServiceNotification() { return new ServiceNotification(map.getBundle("ServiceNotification")); } + public boolean hasServiceNotification() { - return (getMap().containsKey("ServiceNotification")); + return (map.containsKey("ServiceNotification")); } + public boolean commandDidCompleteOK() { return getServiceResult().resultIsOK(); } + public String getOriginalCommandName() { return getServiceCommand().getCommandName(); } + public String describeContentsShort() { String rval = ""; rval += getTransportType(); - if (RT2Const.IPC.MSG_ServiceNotification.equals(getTransportType())) { + + if (this.serviceTransportType == ServiceTransportType.ServiceNotification) { rval += "note: " + getServiceNotification().getNotificationType(); - } else if (RT2Const.IPC.MSG_ServiceCommand.equals(getTransportType())) { + } else if (this.serviceTransportType == ServiceTransportType.ServiceCommand) { rval += ", cmd=" + getOriginalCommandName(); - } else if (RT2Const.IPC.MSG_ServiceResult.equals(getTransportType())) { + } else if (this.serviceTransportType == ServiceTransportType.ServiceResult) { rval += ", cmd=" + getOriginalCommandName(); rval += ", rslt=" + getServiceResult().getResult(); rval += ", err=" + getServiceResult().getErrorDescription(); @@ -115,6 +135,7 @@ public class ServiceTransport extends ServiceMessage { return rval; } + public ServiceTransport clone() { Parcel p = Parcel.obtain(); Parcel p2 = Parcel.obtain(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransportType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransportType.java new file mode 100644 index 0000000000..a5d44a31dc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/data/ServiceTransportType.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data; + +/** + * Created by andy on 31/05/18. + */ + +public enum ServiceTransportType { + + Undefined, // + ServiceNotification, // + + ServiceCommand, // + ServiceResult; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java index 68e67206f9..e051fbdb97 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTask; - import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; /** @@ -12,6 +10,7 @@ public class DiscoverGattServicesTask extends ServiceTask { public DiscoverGattServicesTask() { } + @Override public void run() { RileyLinkUtil.getRileyLinkBLE().discoverServices(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java new file mode 100644 index 0000000000..31e23feecc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; + +import android.util.Log; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst; +import info.nightscout.utils.SP; + +/** + * Created by geoff on 7/9/16. + *

+ * This class is intended to be run by the Service, for the Service. + * Not intended for clients to run. + */ +public class InitializePumpManagerTask extends ServiceTask { + private static final String TAG = "InitPumpManagerTask"; + + + public InitializePumpManagerTask() { + super(); + } + + + public InitializePumpManagerTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + + // FIXME + double lastGoodFrequency = SP.getDouble(MedtronicConst.Prefs.LastGoodPumpFrequency, 0.0); + + if ((lastGoodFrequency > 0.0d) && RileyLinkUtil.getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) { + + Log.i(TAG, String.format("Setting radio frequency to %.2fMHz", lastGoodFrequency)); + RileyLinkUtil.getRileyLinkCommunicationManager().setRadioFrequencyForPump(lastGoodFrequency); + + boolean foundThePump = RileyLinkUtil.getRileyLinkCommunicationManager().tryToConnectToDevice(); + + // FIXME maybe remove in AAPS + if (foundThePump) { + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady); + //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpFound), null); + } else { + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.GattDeviceNotFound); + //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpLost), null); + } + + //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_Idle), null); + } else { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/PumpTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/PumpTask.java new file mode 100644 index 0000000000..bd4ea9b609 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/PumpTask.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; + +/** + * Created by geoff on 7/10/16. + */ +public class PumpTask extends ServiceTask { + public PumpTask() { + super(); + } + + + public PumpTask(ServiceTransport transport) { + super(transport); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTask.java index cd4759c48e..5e428f6702 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTask.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; /** * Created by geoff on 7/9/16. @@ -10,30 +10,37 @@ public class ServiceTask implements Runnable { protected ServiceTransport mTransport; public boolean completed = false; + public ServiceTask() { init(new ServiceTransport()); } + public ServiceTask(ServiceTransport transport) { init(transport); } + public void init(ServiceTransport transport) { mTransport = transport; } + @Override public void run() { } + public void preOp() { // This function is called by UI thread before running asynch thread. } + public void postOp() { // This function is called by UI thread after running asynch thread. } + public ServiceTransport getServiceTransport() { return mTransport; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java index df71d844f5..58705a5a0d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java @@ -24,11 +24,14 @@ public class ServiceTaskExecutor extends ThreadPoolExecutor { super(1, 1, 10000, TimeUnit.MILLISECONDS, taskQueue); } + public static ServiceTask startTask(ServiceTask task) { instance.execute(task); // task will be run on async thread from pool. return task; } + + // FIXME protected void beforeExecute(Thread t, Runnable r) { // This is run on either caller UI thread or Service UI thread. ServiceTask task = (ServiceTask) r; @@ -37,6 +40,8 @@ public class ServiceTaskExecutor extends ThreadPoolExecutor { task.preOp(); } + + // FIXME protected void afterExecute(Runnable r, Throwable t) { // This is run on either caller UI thread or Service UI thread. ServiceTask task = (ServiceTask) r; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java new file mode 100644 index 0000000000..07cb1a7f62 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService; + +/** + * Created by geoff on 7/16/16. + */ +public class WakeAndTuneTask extends PumpTask { + private static final String TAG = "WakeAndTuneTask"; + + + public WakeAndTuneTask() { + } + + + public WakeAndTuneTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + //RileyLinkMedtronicService.getInstance().pumpCommunicationManager.wakeup(6); + RileyLinkMedtronicService.getInstance().pumpCommunicationManager.tuneForPump(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ByteUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ByteUtil.java index 99f73d01e8..39239e86d3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ByteUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ByteUtil.java @@ -7,27 +7,34 @@ import java.util.List; * Created by geoff on 4/28/15. */ public class ByteUtil { - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; + private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private final static String HEX_DIGITS_STR = "0123456789ABCDEF"; + public static byte highByte(short s) { return (byte) (s / 256); } + public static byte lowByte(short s) { return (byte) (s % 256); } + public static int asUINT8(byte b) { return (b < 0) ? b + 256 : b; } /* For Reference: static void System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) */ + public static byte[] concat(byte[] a, byte[] b) { + + if (b == null) { + return a; + } + int aLen = a.length; int bLen = b.length; byte[] c = new byte[aLen + bLen]; @@ -36,6 +43,7 @@ public class ByteUtil { return c; } + public static byte[] concat(byte[] a, byte b) { int aLen = a.length; byte[] c = new byte[aLen + 1]; @@ -44,12 +52,24 @@ public class ByteUtil { return c; } + + public static byte[] concat(byte a, byte[] b) { + int aLen = b.length; + byte[] c = new byte[aLen + 1]; + c[0] = a; + System.arraycopy(b, 0, c, 1, aLen); + + return c; + } + + public static byte[] substring(byte[] a, int start, int len) { byte[] rval = new byte[len]; System.arraycopy(a, start, rval, 0, len); return rval; } + public static String shortHexString(byte[] ra) { String rval = ""; if (ra == null) { @@ -58,7 +78,7 @@ public class ByteUtil { if (ra.length == 0) { return rval; } - for (int i = 0; i < ra.length; i++) { + for(int i = 0; i < ra.length; i++) { rval = rval + HEX_DIGITS[(ra[i] & 0xF0) >> 4]; rval = rval + HEX_DIGITS[(ra[i] & 0x0F)]; if (i < ra.length - 1) { @@ -68,13 +88,12 @@ public class ByteUtil { return rval; } + public static String showPrintable(byte[] ra) { String s = new String(); - for (int i = 0; i < ra.length; i++) { + for(int i = 0; i < ra.length; i++) { char c = (char) ra[i]; - if (((c >= '0') && (c <= '9')) || - ((c >= 'A') && (c <= 'Z')) || - ((c >= 'a') && (c <= 'z'))) { + if (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) { s = s + c; } else { s = s + '.'; @@ -83,6 +102,7 @@ public class ByteUtil { return s; } + public static byte[] fromHexString(String src) { String s = src.toUpperCase(); byte[] rval = new byte[]{}; @@ -90,7 +110,7 @@ public class ByteUtil { // invalid hex string! return null; } - for (int i = 0; i < s.length(); i += 2) { + for(int i = 0; i < s.length(); i += 2) { int highNibbleOrd = HEX_DIGITS_STR.indexOf(s.charAt(i)); if (highNibbleOrd < 0) { // Not a hex digit. @@ -106,22 +126,25 @@ public class ByteUtil { return rval; } + public static byte[] fromByteArray(List byteArray) { byte[] rval = new byte[byteArray.size()]; - for (int i = 0; i < byteArray.size(); i++) { + for(int i = 0; i < byteArray.size(); i++) { rval[i] = byteArray.get(i); } return rval; } + public static ArrayList toByteArray(byte[] data) { ArrayList rval = new ArrayList<>(data.length); - for (int i = 0; i < data.length; i++) { + for(int i = 0; i < data.length; i++) { rval.add(i, new Byte(data[i])); } return rval; } + // compares byte strings like strcmp public static int compare(byte[] s1, byte[] s2) { int i; @@ -134,7 +157,7 @@ public class ByteUtil { return -1; } int acc = 0; - for (i = 0; i < len1; i++) { + for(i = 0; i < len1; i++) { acc += s1[i]; acc -= s2[i]; if (acc != 0) { @@ -144,4 +167,77 @@ public class ByteUtil { return 0; } + + /** + * Converts 4 (or less) ints into int. (Shorts are objects, so you can send null if you have less parameters) + * + * @param b1 short 1 + * @param b2 short 2 + * @param b3 short 3 + * @param b4 short 4 + * @param flag Conversion Flag (Big Endian, Little endian) + * @return int value + */ + public static int toInt(Integer b1, Integer b2, Integer b3, Integer b4, BitConversion flag) { + switch (flag) { + case LITTLE_ENDIAN: { + if (b4 != null) { + return (b4 & 0xff) << 24 | (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b3 != null) { + return (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b2 != null) { + return (b2 & 0xff) << 8 | b1 & 0xff; + } else { + return b1 & 0xff; + } + } + + default: + case BIG_ENDIAN: { + if (b4 != null) { + return (b1 & 0xff) << 24 | (b2 & 0xff) << 16 | (b3 & 0xff) << 8 | b4 & 0xff; + } else if (b3 != null) { + return (b1 & 0xff) << 16 | (b2 & 0xff) << 8 | b3 & 0xff; + } else if (b2 != null) { + return (b1 & 0xff) << 8 | b2 & 0xff; + } else { + return b1 & 0xff; + } + } + } + } + + + public static int toInt(int b1, int b2) { + return toInt(b1, b2, null, null, BitConversion.BIG_ENDIAN); + } + + + public static int toInt(int b1, int b2, BitConversion flag) { + return toInt(b1, b2, null, null, flag); + } + + + public enum BitConversion { + LITTLE_ENDIAN, // 20 0 0 0 = reverse + BIG_ENDIAN // 0 0 0 20 = normal - java + } + + + public static List getListFromByteArray(byte[] array) { + List listOut = new ArrayList(); + + for(byte val : array) { + listOut.add(val); + } + + return listOut; + } + + + public static int makeUnsignedShort(int i, int j) { + int k = (i & 0xff) << 8 | j & 0xff; + return k; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/CRC.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/CRC.java index 2027551387..81b1538042 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/CRC.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/CRC.java @@ -5,25 +5,17 @@ package info.nightscout.androidaps.plugins.PumpCommon.utils; */ public class CRC { - static final int[] crc8lookup = new int[]{0, 155, 173, 54, 193, 90, 108, 247, 25, 130, 180, 47, - 216, 67, 117, 238, 50, 169, 159, 4, 243, 104, 94, 197, 43, 176, - 134, 29, 234, 113, 71, 220, 100, 255, 201, 82, 165, 62, 8, 147, - 125, 230, 208, 75, 188, 39, 17, 138, 86, 205, 251, 96, 151, 12, - 58, 161, 79, 212, 226, 121, 142, 21, 35, 184, 200, 83, 101, 254, - 9, 146, 164, 63, 209, 74, 124, 231, 16, 139, 189, 38, 250, 97, - 87, 204, 59, 160, 150, 13, 227, 120, 78, 213, 34, 185, 143, 20, - 172, 55, 1, 154, 109, 246, 192, 91, 181, 46, 24, 131, 116, 239, - 217, 66, 158, 5, 51, 168, 95, 196, 242, 105, 135, 28, 42, 177, - 70, 221, 235, 112, 11, 144, 166, 61, 202, 81, 103, 252, 18, 137, - 191, 36, 211, 72, 126, 229, 57, 162, 148, 15, 248, 99, 85, 206, - 32, 187, 141, 22, 225, 122, 76, 215, 111, 244, 194, 89, 174, 53, - 3, 152, 118, 237, 219, 64, 183, 44, 26, 129, 93, 198, 240, 107, - 156, 7, 49, 170, 68, 223, 233, 114, 133, 30, 40, 179, 195, 88, - 110, 245, 2, 153, 175, 52, 218, 65, 119, 236, 27, 128, 182, 45, - 241, 106, 92, 199, 48, 171, 157, 6, 232, 115, 69, 222, 41, 178, - 132, 31, 167, 60, 10, 145, 102, 253, 203, 80, 190, 37, 19, 136, - 127, 228, 210, 73, 149, 14, 56, 163, 84, 207, 249, 98, 140, 23, - 33, 186, 77, 214, 224, 123}; + static final int[] crc8lookup = new int[]{0, 155, 173, 54, 193, 90, 108, 247, 25, 130, 180, 47, 216, 67, 117, 238, 50, 169, // + 159, 4, 243, 104, 94, 197, 43, 176, 134, 29, 234, 113, 71, 220, 100, 255, 201, 82, 165, 62, 8, 147, 125, 230, 208, 75, // + 188, 39, 17, 138, 86, 205, 251, 96, 151, 12, 58, 161, 79, 212, 226, 121, 142, 21, 35, 184, 200, 83, 101, 254, 9, 146, // + 164, 63, 209, 74, 124, 231, 16, 139, 189, 38, 250, 97, 87, 204, 59, 160, 150, 13, 227, 120, 78, 213, 34, 185, 143, 20, // + 172, 55, 1, 154, 109, 246, 192, 91, 181, 46, 24, 131, 116, 239, 217, 66, 158, 5, 51, 168, 95, 196, 242, 105, 135, 28, 42, // + 177, 70, 221, 235, 112, 11, 144, 166, 61, 202, 81, 103, 252, 18, 137, 191, 36, 211, 72, 126, 229, 57, 162, 148, 15, 248, // + 99, 85, 206, 32, 187, 141, 22, 225, 122, 76, 215, 111, 244, 194, 89, 174, 53, 3, 152, 118, 237, 219, 64, 183, 44, 26, 129, // + 93, 198, 240, 107, 156, 7, 49, 170, 68, 223, 233, 114, 133, 30, 40, 179, 195, 88, 110, 245, 2, 153, 175, 52, 218, 65, 119, // + 236, 27, 128, 182, 45, 241, 106, 92, 199, 48, 171, 157, 6, 232, 115, 69, 222, 41, 178, 132, 31, 167, 60, 10, 145, 102, 253, // + 203, 80, 190, 37, 19, 136, 127, 228, 210, 73, 149, 14, 56, 163, 84, 207, 249, 98, 140, 23, 33, 186, 77, 214, 224, 123}; + public static byte crc8(byte[] data, int len) { @@ -34,7 +26,7 @@ public class CRC { if (len > data.length) { len = data.length; } - for (int i = 0; i < len; i++) { + for(int i = 0; i < len; i++) { int tmp = result; int tmp2 = tmp ^ data[i]; int tmp3 = tmp2 & 0xFF; @@ -48,18 +40,20 @@ public class CRC { } + public static byte crc8(byte[] data) { return crc8(data, data.length); } + public static byte[] calculate16CCITT(byte[] data) { int crc = 0xFFFF; int polynomial = 0x1021; if (data != null) { if (data.length > 0) { - for (int j = 0; j < data.length; j++) { + for(int j = 0; j < data.length; j++) { byte b = data[j]; - for (int i = 0; i < 8; i++) { + for(int i = 0; i < 8; i++) { boolean bit = ((b >> (7 - i) & 1) == 1); boolean c15 = ((crc >> 15 & 1) == 1); crc <<= 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/HexDump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/HexDump.java index 0a4042db26..e94a796529 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/HexDump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/HexDump.java @@ -16,19 +16,21 @@ package info.nightscout.androidaps.plugins.PumpCommon.utils; +import java.util.List; + /** * Clone of Android's HexDump class, for use in debugging. Cosmetic changes * only. */ public class HexDump { - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; + private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + public static String dumpHexString(byte[] array) { return dumpHexString(array, 0, array.length); } + public static String dumpHexString(byte[] array, int offset, int length) { StringBuilder result = new StringBuilder(); @@ -38,11 +40,11 @@ public class HexDump { result.append("\n0x"); result.append(toHexString(offset)); - for (int i = offset; i < offset + length; i++) { + for(int i = offset; i < offset + length; i++) { if (lineIndex == 16) { result.append(" "); - for (int j = 0; j < 16; j++) { + for(int j = 0; j < 16; j++) { if (line[j] > ' ' && line[j] < '~') { result.append(new String(line, j, 1)); } else { @@ -66,11 +68,11 @@ public class HexDump { if (lineIndex != 16) { int count = (16 - lineIndex) * 3; count++; - for (int i = 0; i < count; i++) { + for(int i = 0; i < count; i++) { result.append(" "); } - for (int i = 0; i < lineIndex; i++) { + for(int i = 0; i < lineIndex; i++) { if (line[i] > ' ' && line[i] < '~') { result.append(new String(line, i, 1)); } else { @@ -82,19 +84,22 @@ public class HexDump { return result.toString(); } + public static String toHexString(byte b) { return toHexString(toByteArray(b)); } + public static String toHexString(byte[] array) { return toHexString(array, 0, array.length); } + public static String toHexString(byte[] array, int offset, int length) { char[] buf = new char[length * 2]; int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { + for(int i = offset; i < offset + length; i++) { byte b = array[i]; buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; @@ -103,20 +108,80 @@ public class HexDump { return new String(buf); } + + public static String toHexStringDisplayable(byte[] arr) { + StringBuilder sb = new StringBuilder(); + + if (arr == null) { + sb.append("Null array"); + } else { + + if (arr.length == 0) { + sb.append("Zero-length array"); + } else { + + for(byte element : arr) { + sb.append(getCorrectHexValue(element)); + sb.append(" "); + } + } + } + + return sb.toString(); + } + + + public static String toHexStringDisplayable(List data) { + StringBuilder sb = new StringBuilder(); + + for(byte element : data) { + sb.append(getCorrectHexValue(element)); + sb.append(" "); + } + + return sb.toString(); + } + + + public static String getCorrectHexValue(byte inp) { + String hx = Integer.toHexString((char) inp); + hx = hx.toUpperCase(); + + if (hx.length() == 0) + return "00"; + else if (hx.length() == 1) + return "0" + hx; + else if (hx.length() == 2) + return hx; + else if (hx.length() == 4) + return hx.substring(2); + else { + System.out.println("HEX ERROR !!!!!!!!!!!!!!!!"); + } + + // System.out.print(Integer.toHexString((char)arr[i]) + " "); + + return null; + } + + public static String toHexString(int i) { return toHexString(toByteArray(i)); } + public static String toHexString(short i) { return toHexString(toByteArray(i)); } + public static byte[] toByteArray(byte b) { byte[] array = new byte[1]; array[0] = b; return array; } + public static byte[] toByteArray(int i) { byte[] array = new byte[4]; @@ -128,6 +193,7 @@ public class HexDump { return array; } + public static byte[] toByteArray(short i) { byte[] array = new byte[2]; @@ -137,6 +203,7 @@ public class HexDump { return array; } + private static int toByte(char c) { if (c >= '0' && c <= '9') return (c - '0'); @@ -148,15 +215,17 @@ public class HexDump { throw new RuntimeException("Invalid hex char '" + c + "'"); } + public static byte[] hexStringToByteArray(String hexString) { int length = hexString.length(); byte[] buffer = new byte[length / 2]; - for (int i = 0; i < length; i += 2) { - buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString - .charAt(i + 1))); + for(int i = 0; i < length; i += 2) { + buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); } return buffer; } + + } diff --git a/app/src/main/java/com/gxwtech/roundtrip2/util/LocationHelper.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/LocationHelper.java similarity index 69% rename from app/src/main/java/com/gxwtech/roundtrip2/util/LocationHelper.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/LocationHelper.java index 29bc09b6bb..00d4a2c1ca 100644 --- a/app/src/main/java/com/gxwtech/roundtrip2/util/LocationHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/LocationHelper.java @@ -1,29 +1,23 @@ -package com.gxwtech.roundtrip2.util; +package info.nightscout.androidaps.plugins.PumpCommon.utils; -import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.pm.PackageManager; import android.location.LocationManager; import android.os.Build; -import android.support.v4.app.ActivityCompat; -import android.util.Log; +import info.nightscout.androidaps.R; /** * Helper for checking if location services are enabled on the device. */ public class LocationHelper { - - final static String TAG = "LocationHelper"; - /** * Determine if GPS is currently enabled. - * + *

* On Android 6 (Marshmallow), location needs to be enabled for Bluetooth discovery to work. * * @param context The current app context. @@ -46,23 +40,21 @@ public class LocationHelper { // Shamelessly borrowed from http://stackoverflow.com/a/10311877/868533 - Log.e(TAG, "requestLocation: N/A"); - -// AlertDialog.Builder builder = new AlertDialog.Builder(parent); -// builder.setTitle(R.string.location_not_found_title); -// builder.setMessage(R.string.location_not_found_message); -// builder.setPositiveButton(R.string.location_yes, new DialogInterface.OnClickListener() { -// public void onClick(DialogInterface dialogInterface, int i) { -// parent.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); -// } -// }); -// builder.setNegativeButton(R.string.location_no, null); -// builder.create().show(); + AlertDialog.Builder builder = new AlertDialog.Builder(parent); + builder.setTitle(R.string.location_not_found_title); + builder.setMessage(R.string.location_not_found_message); + builder.setPositiveButton(R.string.location_yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialogInterface, int i) { + parent.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + } + }); + builder.setNegativeButton(R.string.location_no, null); + builder.create().show(); } /** * Prompt the user to enable GPS location on devices that need it for Bluetooth discovery. - * + *

* Android 6 (Marshmallow) needs GPS enabled for Bluetooth discovery to work. * * @param activity The currently visible activity. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/StringUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/StringUtil.java index 1c7bf7d031..c2e494e978 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/StringUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/StringUtil.java @@ -1,6 +1,9 @@ package info.nightscout.androidaps.plugins.PumpCommon.utils; +import org.joda.time.LocalDateTime; + import java.nio.charset.Charset; +import java.text.DecimalFormat; import java.util.ArrayList; /** @@ -8,16 +11,21 @@ import java.util.ArrayList; */ public class StringUtil { + + public static DecimalFormat DecimalFormaters[] = {new DecimalFormat("#0"), new DecimalFormat("#0.0"), new DecimalFormat("#0.00"), new DecimalFormat("#0.000")}; + + public static String fromBytes(byte[] ra) { return new String(ra, Charset.forName("UTF-8")); } + // these should go in some project-wide string utils package public static String join(ArrayList ra, String joiner) { int sz = ra.size(); String rval = ""; int n; - for (n = 0; n < sz; n++) { + for(n = 0; n < sz; n++) { rval = rval + ra.get(n); if (n < sz - 1) { rval = rval + joiner; @@ -26,6 +34,7 @@ public class StringUtil { return rval; } + public static String testJoin() { ArrayList ra = new ArrayList(); ra.add("one"); @@ -34,4 +43,41 @@ public class StringUtil { return join(ra, "+"); } + + /** + * Append To StringBuilder + * + * @param stringBuilder + * @param stringToAdd + * @param delimiter + * @return + */ + public static void appendToStringBuilder(StringBuilder stringBuilder, String stringToAdd, String delimiter) { + if (stringBuilder.length() > 0) { + stringBuilder.append(delimiter + stringToAdd); + } else { + stringBuilder.append(stringToAdd); + } + } + + + public static String getFormatedValueUS(Number value, int decimals) { + return DecimalFormaters[decimals].format(value).replace(",", "."); + } + + + public static String getLeadingZero(int number, int places) { + String nn = "" + number; + + while (nn.length() < places) { + nn = "0" + nn; + } + + return nn; + } + + + public static String toDateTimeString(LocalDateTime localDateTime) { + return localDateTime.toString("dd.MM.yyyy HH:mm:ss"); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ThreadUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ThreadUtil.java index b6a8476c93..565c029a4e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ThreadUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/ThreadUtil.java @@ -8,10 +8,12 @@ public class ThreadUtil { return Thread.currentThread().getId(); } + public static String getThreadName() { return Thread.currentThread().getName(); } + public static String sig() { Thread t = Thread.currentThread(); return t.getName() + "[" + t.getId() + "]"; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java index e2aaf98512..df03326272 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java @@ -35,6 +35,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicNewStatus; +import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicRileyLinkStatusChange; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.utils.DateUtil; @@ -175,6 +176,14 @@ public class MedtronicFragment extends SubscriberFragment { } } + + @Subscribe + public void onStatusEvent(final EventMedtronicRileyLinkStatusChange s) { + + + } + + @Subscribe public void onStatusEvent(final EventMedtronicNewStatus s) { updateGUI(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java index 95302d0d02..04994b18d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java @@ -25,7 +25,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpPlugin.class); - //private ServiceClientConnection serviceClientConnection; private RileyLinkMedtronicService medtronicService; protected static MedtronicPumpPlugin plugin = null; @@ -114,4 +113,60 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } + // Pump Plugin + + private boolean isServiceSet() { + return medtronicService != null; + } + + public boolean isInitialized() { + return isServiceSet() && medtronicService.isInitialized(); + } + + public boolean isSuspended() { + return isServiceSet() && medtronicService.isSuspended(); + } + + public boolean isBusy() { + return isServiceSet() && medtronicService.isBusy(); + } + + + public boolean isConnected() { + return isServiceSet() && medtronicService.isConnected(); + } + + + public boolean isConnecting() { + return isServiceSet() && medtronicService.isConnecting(); + } + + + public void connect(String reason) { + if (isServiceSet()) { + medtronicService.connect(reason); + } + } + + + public void disconnect(String reason) { + if (isServiceSet()) { + medtronicService.disconnect(reason); + } + } + + + public void stopConnecting() { + if (isServiceSet()) { + medtronicService.stopConnecting(); + } + } + + + public void getPumpStatus() { + if (isServiceSet()) { + medtronicService.getPumpStatus(); + } + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java index 570a2d2a6a..f51b91e72f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java @@ -1,89 +1,205 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm; import android.content.Context; +import android.os.SystemClock; -import org.joda.time.IllegalFieldValueException; import org.joda.time.Instant; import org.joda.time.LocalDateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.List; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessageType; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; -import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; -import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfile; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.RawHistoryPage; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.TempBasalPair; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.Record; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.ButtonPressCarelinkMessageBody; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.CarelinkLongMessageBody; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.CarelinkShortMessageBody; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.GetHistoryPageCarelinkMessageBody; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.GetPumpModelCarelinkMessageBody; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MedtronicConverter; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageBody; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageType; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PacketType; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpAckMessageBody; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpMessage; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService; import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; -//import com.gxwtech.roundtrip2.ServiceData.ServiceResult; - /** - * Created by geoff on 5/30/16. + * Original file created by geoff on 5/30/16. *

* Split into 2 implementations, so that we can split it by target device. - Andy */ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager { private static final Logger LOG = LoggerFactory.getLogger(MedtronicCommunicationManager.class); + private static final int MAX_COMMAND_RETRIES = 2; + private static final int DEFAULT_TIMEOUT = 2000; - private static double[] scanFrequenciesUS = {916.45, 916.50, 916.55, 916.60, 916.65, 916.70, 916.75, 916.80}; - private static double[] scanFrequenciesWorldwide = {868.25, 868.30, 868.35, 868.40, 868.45, 868.50, 868.55, 868.60, 868.65}; + static MedtronicCommunicationManager medtronicCommunicationManager; + private MedtronicConverter medtronicConverter; - byte[] pumpID; + String errorMessage; - public MedtronicCommunicationManager(Context context, RFSpy rfspy, boolean hasUSfrequency, byte[] pumpID) { - super(context, rfspy, hasUSfrequency ? scanFrequenciesUS : scanFrequenciesWorldwide); - this.pumpID = pumpID; - //prefs = context.getSharedPreferences(RT2Const.serviceLocal.sharedPreferencesKey, Context.MODE_PRIVATE); - this.pumpStatus = MedtronicPumpPlugin.getPlugin().getPumpStatusData(); + + public MedtronicCommunicationManager(Context context, RFSpy rfspy, RileyLinkTargetFrequency targetFrequency) { + super(context, rfspy, targetFrequency); + medtronicCommunicationManager = this; + this.medtronicConverter = new MedtronicConverter(); } + + @Override + protected void configurePumpSpecificSettings() { + pumpStatus = RileyLinkUtil.getMedtronicPumpStatus(); + } + + + // FIXME must not call getPumpModel !!!!!!!!!!!!! + @Override + public boolean tryToConnectToDevice() { + + wakeUp(true); + + MedtronicDeviceType pumpModel = getPumpModel(); + + // Andy (4.6.2018): we do retry if no data returned. We might need to do that everywhere, but that might require little bit of rewrite of RF Code. + if (pumpModel == MedtronicDeviceType.Unknown_Device) { + + SystemClock.sleep(1000); + + pumpModel = getPumpModel(); + } + + return (pumpModel != MedtronicDeviceType.Unknown_Device); + } + + + public static MedtronicCommunicationManager getInstance() { + return medtronicCommunicationManager; + } + + + private boolean debugSetCommands = true; + + + // FIXME remove debugs - Andy private PumpMessage runCommandWithArgs(PumpMessage msg) { + + if (debugSetCommands) + LOG.debug("Run command with Args: "); PumpMessage rval; - PumpMessage shortMessage = makePumpMessage(msg.messageType, new CarelinkShortMessageBody(new byte[]{0})); + PumpMessage shortMessage = makePumpMessage(msg.commandType, new CarelinkShortMessageBody(new byte[]{0})); // look for ack from short message PumpMessage shortResponse = sendAndListen(shortMessage); - if (shortResponse.messageType == MessageType.PumpAck) { + if (shortResponse.commandType == MedtronicCommandType.CommandACK) { + if (debugSetCommands) + LOG.debug("Run command with Args: Got ACK response"); rval = sendAndListen(msg); + if (debugSetCommands) + LOG.debug("2nd Response: {}", rval); return rval; } else { LOG.error("runCommandWithArgs: Pump did not ack Attention packet"); + return new PumpMessage("No ACK after Attention packet."); } - return new PumpMessage(); + } + + + private PumpMessage runCommandWithArgsLong(MedtronicCommandType commandType, byte[] content) { + + LOG.debug("Run command with Args (Long): {}", commandType.name()); + + PumpMessage rval = null; + PumpMessage shortMessage = makePumpMessage(commandType, new CarelinkShortMessageBody(new byte[]{0})); + // look for ack from short message + PumpMessage shortResponse = sendAndListen(shortMessage); + + if (shortResponse.commandType != MedtronicCommandType.CommandACK) { + LOG.error("runCommandWithArgs: Pump did not ack Attention packet"); + + return new PumpMessage("No ACK after start message."); + } + + + int start = 0; + int frameNr = 1; + int len = 0; + + do { + + if (start == 0) + LOG.debug("Run command with Args(Long): Got ACK response for Attention packet"); + else + LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr - 1)); + + if (start + 64 > content.length) { + len = content.length - start; + + if (len == 0) + break; + } else { + len = 64; + } + + byte frame[] = new byte[65]; + + frame[0] = (byte) frameNr; + + System.arraycopy(content, start, frame, 1, len); + + PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(frame)); + + rval = sendAndListen(msg); + + if (rval.commandType != MedtronicCommandType.CommandACK) { + LOG.error("runCommandWithArgs(Long): Pump did not ACK frame #{}", frameNr); + + return new PumpMessage("No ACK after frame #" + frameNr); + } + + if (len != 64) { + LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr)); + break; + } + + start += 64; + frameNr++; + + } while (true); + + + return rval; + + + //return new PumpMessage("No ACK"); } public Page getPumpHistoryPage(int pageNumber) { RawHistoryPage rval = new RawHistoryPage(); - wakeup(receiverDeviceAwakeForMinutes); - PumpMessage getHistoryMsg = makePumpMessage(MessageType.GetHistoryPage, new GetHistoryPageCarelinkMessageBody(pageNumber)); + wakeUp(receiverDeviceAwakeForMinutes, false); + PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData, new GetHistoryPageCarelinkMessageBody(pageNumber)); //LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData())); // Ask the pump to transfer history (we get first frame?) PumpMessage firstResponse = runCommandWithArgs(getHistoryMsg); //LOG.info("getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); - PumpMessage ackMsg = makePumpMessage(MessageType.PumpAck, new PumpAckMessageBody()); + PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse.getMessageBody().getTxData()); int expectedFrameNum = 1; boolean done = false; @@ -112,13 +228,13 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager if (frameData == null) { LOG.error("null frame data, retrying"); } else if (currentResponse.getFrameNumber() != expectedFrameNum) { - LOG.warn("Expected frame number %d, received %d (retrying)", expectedFrameNum, currentResponse.getFrameNumber()); + LOG.warn("Expected frame number {}, received {} (retrying)", expectedFrameNum, currentResponse.getFrameNumber()); } else if (frameData.length == 0) { LOG.warn("Frame has zero length, retrying"); } failures++; if (failures == 6) { - LOG.error("6 failures in attempting to download frame %d of page %d, giving up.", expectedFrameNum, pageNumber); + LOG.error("6 failures in attempting to download frame {} of page {}, giving up.", expectedFrameNum, pageNumber); done = true; // failure completion. } } @@ -140,11 +256,12 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager Page page = new Page(); //page.parseFrom(rval.getData(),PumpModel.MM522); // FIXME - page.parseFrom(rval.getData(), PumpModel.MM522); + page.parseFrom(rval.getData(), MedtronicDeviceType.Medtronic_522); return page; } + public ArrayList getAllHistoryPages() { ArrayList pages = new ArrayList<>(); @@ -155,6 +272,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager return pages; } + public ArrayList getHistoryEventsSinceDate(Instant when) { ArrayList pages = new ArrayList<>(); for (int pageNum = 0; pageNum < 16; pageNum++) { @@ -170,268 +288,452 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager } - public void hunt() { - //tryoutPacket(new byte[] {MessageType.CMD_M_READ_PUMP_STATUS,0}); - //tryoutPacket(new byte[] {MessageType.CMD_M_READ_FIRMWARE_VER,0}); - //tryoutPacket(new byte[] {MessageType.CMD_M_READ_INSULIN_REMAINING,0}); - + public String getErrorResponse() { + return this.errorMessage; } + // See ButtonPressCarelinkMessageBody public void pressButton(int which) { - wakeup(receiverDeviceAwakeForMinutes); - PumpMessage pressButtonMessage = makePumpMessage(MessageType.ButtonPress, new ButtonPressCarelinkMessageBody(which)); + wakeUp(receiverDeviceAwakeForMinutes, false); + PumpMessage pressButtonMessage = makePumpMessage(MedtronicCommandType.PushButton, new ButtonPressCarelinkMessageBody(which)); PumpMessage resp = sendAndListen(pressButtonMessage); - if (resp.messageType != MessageType.PumpAck) { + if (resp.commandType != MedtronicCommandType.CommandACK) { LOG.error("Pump did not ack button press."); } } + // FIXME + //@Override + // public RLMessage makeRLMessage(RLMessageType type, byte[] data) { + // switch (type) { + // case PowerOn: + // return makePumpMessage(MedtronicCommandType.RFPowerOn, new CarelinkShortMessageBody(data)); + // + // case ReadSimpleData: + // return makePumpMessage(MedtronicCommandType.PumpModel, new GetPumpModelCarelinkMessageBody()); + // + // } + // return null; + // } + + + // @Override + // public RLMessage makeRLMessage(byte[] data) { + // return makePumpMessage(data); + // } + + @Override - public RLMessage makeRLMessage(RLMessageType type, byte[] data) { + public byte[] createPumpMessageContent(RLMessageType type) { switch (type) { case PowerOn: - return makePumpMessage(MessageType.PowerOn, new CarelinkShortMessageBody(data)); + return MedtronicUtil.buildCommandPayload(MedtronicCommandType.RFPowerOn, // + new byte[]{2, 1, (byte) receiverDeviceAwakeForMinutes}); // maybe this is better FIXME case ReadSimpleData: - return makePumpMessage(MessageType.GetPumpModel, new GetPumpModelCarelinkMessageBody()); - + return MedtronicUtil.buildCommandPayload(MedtronicCommandType.PumpModel, null); } - return null; + return new byte[0]; } - @Override - public RLMessage makeRLMessage(byte[] data) { - return makePumpMessage(data); - } - - - protected PumpMessage makePumpMessage(MessageType messageType, MessageBody messageBody) { - PumpMessage msg = new PumpMessage(); - msg.init(PacketType.Carelink, pumpID, messageType, messageBody); - return msg; - } - - - protected PumpMessage makePumpMessage(byte msgType, MessageBody body) { - return makePumpMessage(MessageType.getByValue(msgType), body); - } - - - protected PumpMessage makePumpMessage(MessageType messageType, byte[] body) { + protected PumpMessage makePumpMessage(MedtronicCommandType messageType, byte[] body) { return makePumpMessage(messageType, body == null ? new CarelinkShortMessageBody() : new CarelinkShortMessageBody(body)); } - protected PumpMessage makePumpMessage(MessageType messageType) { + protected PumpMessage makePumpMessage(MedtronicCommandType messageType) { return makePumpMessage(messageType, (byte[]) null); } - protected PumpMessage makePumpMessage(byte[] typeAndBody) { + protected PumpMessage makePumpMessage(MedtronicCommandType messageType, MessageBody messageBody) { PumpMessage msg = new PumpMessage(); - msg.init(ByteUtil.concat(ByteUtil.concat(new byte[]{(byte) 0xa7}, pumpID), typeAndBody)); + msg.init(PacketType.Carelink, rileyLinkServiceData.pumpIDBytes, messageType, messageBody); return msg; } - private PumpMessage sendAndGetResponse(MessageType messageType) { - return sendAndGetResponse(messageType, null); + // protected PumpMessage makePumpMessage(byte[] typeAndBody) { + // PumpMessage msg = new PumpMessage(); + // msg.init(ByteUtil.concat(ByteUtil.concat(new byte[]{PacketType.Carelink.getValue()}, rileyLinkServiceData.pumpIDBytes), typeAndBody)); + // return msg; + // } + + + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType) { + + return sendAndGetResponse(commandType, null, DEFAULT_TIMEOUT); } - private PumpMessage sendAndGetResponse(MessageType messageType, byte[] bodyData) { + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, int timeoutMs) { + + return sendAndGetResponse(commandType, null, timeoutMs); + } + + + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData) { + + return sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT); + } + + + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) { // wakeUp - wakeup(receiverDeviceAwakeForMinutes); + wakeUp(receiverDeviceAwakeForMinutes, false); // create message PumpMessage msg; if (bodyData == null) - msg = makePumpMessage(messageType); + msg = makePumpMessage(commandType); else - msg = makePumpMessage(messageType, bodyData); + msg = makePumpMessage(commandType, bodyData); // send and wait for response - PumpMessage response = sendAndListen(msg); + PumpMessage response = sendAndListen(msg, timeoutMs); return response; } - // Get Medtronic specific data - private LocalDateTime parsePumpRTCBytes(byte[] bytes) { - if (bytes == null) return null; - if (bytes.length < 7) return null; - int hours = ByteUtil.asUINT8(bytes[0]); - int minutes = ByteUtil.asUINT8(bytes[1]); - int seconds = ByteUtil.asUINT8(bytes[2]); - int year = (ByteUtil.asUINT8(bytes[4]) & 0x3f) + 1984; - int month = ByteUtil.asUINT8(bytes[5]); - int day = ByteUtil.asUINT8(bytes[6]); - try { - LocalDateTime pumpTime = new LocalDateTime(year, month, day, hours, minutes, seconds); - return pumpTime; - } catch (IllegalFieldValueException e) { - LOG.error("parsePumpRTCBytes: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", year, month, day, hours, minutes, seconds); - return null; - } + // FIXME remove + // private PumpMessage sendAndGetACK(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) { + // // wakeUp + // wakeUp(receiverDeviceAwakeForMinutes, false); + // + // // create message + // PumpMessage msg; + // + // if (bodyData == null) + // msg = makePumpMessage(commandType); + // else + // msg = makePumpMessage(commandType, bodyData); + // + // // send and wait for ACK + // PumpMessage response = send(msg, timeoutMs); + // return response; + // } + + + private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType) { + + return sendAndGetResponseWithCheck(commandType, null); } - public LocalDateTime getPumpRTC() { - //ReadPumpClockResult rval = new ReadPumpClockResult(); - wakeup(receiverDeviceAwakeForMinutes); - PumpMessage getRTCMsg = makePumpMessage(MessageType.ReadTime, new byte[]{0}); - LOG.info("getPumpRTC: " + ByteUtil.shortHexString(getRTCMsg.getTxData())); - PumpMessage response = sendAndListen(getRTCMsg); - if (response.isValid()) { - byte[] receivedData = response.getContents(); - if (receivedData != null) { - if (receivedData.length >= 9) { - LocalDateTime pumpTime = parsePumpRTCBytes(ByteUtil.substring(receivedData, 2, 7)); - return pumpTime; - } + private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData) { + + for (int retries = 0; retries < MAX_COMMAND_RETRIES; retries++) { + + PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); + + String check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength); + + if (check == null) { + + Object dataResponse = medtronicConverter.convertResponse(commandType, response.getRawContent()); + + LOG.debug("Converted response for {} is {}.", commandType.name(), dataResponse); + + return dataResponse; + } else { + this.errorMessage = check; + //return null; } - } else { - LOG.error("Invalid response: {}", ByteUtil.showPrintable(response.getContents())); + } return null; } - public PumpModel getPumpModel() { - wakeup(receiverDeviceAwakeForMinutes); - PumpMessage msg = makePumpMessage(MessageType.GetPumpModel, new GetPumpModelCarelinkMessageBody()); - LOG.info("getPumpModel: " + ByteUtil.shortHexString(msg.getTxData())); - PumpMessage response = sendAndListen(msg); - LOG.info("getPumpModel response: " + ByteUtil.shortHexString(response.getContents())); - byte[] contents = response.getContents(); - PumpModel rval = PumpModel.UNSET; - if (contents != null) { - if (contents.length >= 7) { - rval = PumpModel.fromString(StringUtil.fromBytes(ByteUtil.substring(contents, 3, 3))); - } else { - LOG.warn("getPumpModel: Cannot return pump model number: data is too short."); - } - } else { - LOG.warn("getPumpModel: Cannot return pump model number: null response"); + private String checkResponseContent(PumpMessage response, String method, int expectedLength) { + + if (!response.isValid()) { + String responseData = String.format("%s: Invalid response.", method); + LOG.warn(responseData); + return responseData; } - return rval; + + byte[] contents = response.getRawContent(); + + if (contents != null) { + if (contents.length >= expectedLength) { + LOG.trace("{}: Content: {}", method, HexDump.toHexStringDisplayable(contents)); + return null; + + } else { + String responseData = String.format("%s: Cannot return data. Data is too short [expected=%s, received=%s].", method, "" + expectedLength, "" + contents.length); + + LOG.warn(responseData); + return responseData; + } + } else { + String responseData = String.format("%s: Cannot return data. Null response.", method); + LOG.warn(responseData); + return responseData; + } } + // TODO remove not needed - probably + // @Deprecated + // private void executeSetCommand(MedtronicCommandType commandType, byte[] bodyData) { + // + // LOG.debug("Executing Set for {} - 1st call", commandType.name()); + // + // // first we send command without paramters and wait for ACK + // PumpMessage pumpMessage = sendAndGetACK(commandType, null, 4000); + // + // // FIXME check if ACK + // LOG.debug("Response 1 - {}", HexDump.toHexStringDisplayable(pumpMessage.getRawContent())); + // + // + // LOG.debug("Executing Set for {} - 2nd call", commandType.name()); + // // second we send command with parameters and full package 64 bits with zeroed empty places + // + // byte newBodyData[] = new byte[64]; + // for(int i = 0; i < 64; i++) { + // newBodyData[i] = 0x00; + // } + // + // newBodyData[0] = (byte) bodyData.length; + // + // for(int i = 0; i < bodyData.length; i++) { + // newBodyData[i + 1] = bodyData[i]; + // } + // + // PumpMessage pumpMessage2 = sendAndGetACK(commandType, newBodyData, 4000); + // + // + // LOG.debug("Response 2 - {}", HexDump.toHexStringDisplayable(pumpMessage.getRawContent())); + // + // } + + + // PUMP SPECIFIC COMMANDS + + + public Float getRemainingInsulin() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin); + + return responseObject == null ? null : (Float) responseObject; + } + + + public MedtronicDeviceType getPumpModel() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel); + + if (!RileyLinkUtil.isModelSet()) { + RileyLinkUtil.setMedtronicPumpModel((MedtronicDeviceType) responseObject); + } + + return responseObject == null ? null : (MedtronicDeviceType) responseObject; + } + + + public BasalProfile getBasalProfile() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBasalProfileSTD); + + return responseObject == null ? null : (BasalProfile) responseObject; + } + + + public LocalDateTime getPumpTime() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.RealTimeClock); + + return responseObject == null ? null : (LocalDateTime) responseObject; + } + + + public TempBasalPair getTemporaryBasal() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal); + + return responseObject == null ? null : (TempBasalPair) responseObject; + } + + + public List getPumpSettings() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(RileyLinkUtil.getMedtronicPumpModel())); + + return responseObject == null ? null : (List) responseObject; + } + + + // TODO test with values bigger than 30U + public Boolean setBolus(double units) { + + wakeUp(false); + + byte[] body = MedtronicUtil.getBolusStrokes(units); + + if (debugSetCommands) + LOG.debug("Set Bolus: Body - {}", HexDump.toHexStringDisplayable(body)); + + PumpMessage msg = makePumpMessage(MedtronicCommandType.SetBolus, // + new CarelinkLongMessageBody(ByteUtil.concat((byte) body.length, body))); + + PumpMessage pumpMessage = runCommandWithArgs(msg); + + if (debugSetCommands) + LOG.debug("Set Bolus: {}", pumpMessage.getResponseContent()); + + return pumpMessage.commandType == MedtronicCommandType.CommandACK; + } + + + // TODO WIP test + public boolean setTBR(TempBasalPair tbr) { + + wakeUp(false); + + byte[] body = tbr.getAsRawData(); + + if (debugSetCommands) + LOG.debug("Set TBR: Body - {}", HexDump.toHexStringDisplayable(body)); + + PumpMessage msg = makePumpMessage(MedtronicCommandType.SetTemporaryBasal, // + new CarelinkLongMessageBody(tbr.getAsRawData())); + + PumpMessage pumpMessage = runCommandWithArgs(msg); + + if (debugSetCommands) + LOG.debug("Set TBR: {}", pumpMessage.getResponseContent()); + + return pumpMessage.commandType == MedtronicCommandType.CommandACK; + } + + + public boolean cancelTBR() { + return setTBR(new TempBasalPair(0.0d, false, 0)); + } + + + // FIXME: + public Integer getRemainingBattery() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus); + + return responseObject == null ? null : (Integer) responseObject; + } + + + // FIXME --- After this line commands in development --- REMOVE THIS COMMANDS + + // TODO remove for AAPS // public ISFTable getPumpISFProfile() { // -// PumpMessage response = sendAndGetResponse(MessageType.GetISFProfile); +// PumpMessage response = sendAndGetResponse(MedtronicCommandType.ReadInsulinSensitivities); // // ISFTable table = new ISFTable(); // table.parseFrom(response.getContents()); // return table; // } + // TODO remove for AAPS public PumpMessage getBolusWizardCarbProfile() { - PumpMessage response = sendAndGetResponse(MessageType.CMD_M_READ_CARB_RATIOS); + PumpMessage response = sendAndGetResponse(MedtronicCommandType.GetCarbohydrateRatios); return response; } - // TODO check - public Integer getRemainingBattery() { - PumpMessage response = sendAndGetResponse(MessageType.GetBattery); - // TODO decode here + // TODO test - if (response.isValid()) { - byte[] remainingBatteryBytes = response.getContents(); - if (remainingBatteryBytes != null) { - if (remainingBatteryBytes.length == 5) { - /** - * 0x72 0x03, 0x00, 0x00, 0x82 - * meaning what ???? - */ - // FIXME use RawData and decoding is not correct - // TODO review this !!! Andy + public PumpMessage getPumpState() { + PumpMessage response = sendAndGetResponse(MedtronicCommandType.PumpState); - return ByteUtil.asUINT8(remainingBatteryBytes[5]); - } - } - } + byte[] data = response.getRawContent(); + LOG.debug("Pump State: {}", HexDump.toHexStringDisplayable(data)); + + // 3 TBR running ? return null; } - // TODO check - public Float getRemainingInsulin() { - PumpMessage response = sendAndGetResponse(MessageType.CMD_M_READ_INSULIN_REMAINING); - // TODO decode here + public PumpMessage getBolusStatus() { + PumpMessage response = sendAndGetResponse(MedtronicCommandType.SetBolus, new byte[]{0x03, 0x00, 0x00, 0x00}, 4000); + byte[] data = response.getRawContent(); - float value = MedtronicUtil.makeUnsignedShort(data[1], data[0]) / 10.0f; + LOG.debug("Detect bolus: {}", HexDump.toHexStringDisplayable(data)); - return value; + // 3 TBR running ? + + return null; } - // FIXME check - public TempBasalPair getCurrentBasalRate() { - PumpMessage response = sendAndGetResponse(MessageType.ReadTempBasal); - - TempBasalPair tbr = new TempBasalPair(response.getRawContent()); - - return tbr; - } - - - // TODO test - public BasalProfile getProfile() { - - PumpMessage response = sendAndGetResponse(MessageType.ReadBasalProfileSTD); - - return new BasalProfile(response.getRawContent()); - } // TODO generateRawData (check if it works correctly) and test - public PumpMessage setProfile(BasalProfile basalProfile) { + public Boolean setBasalProfile(BasalProfile basalProfile) { - basalProfile.generateRawData(); + //byte[] body = basalProfile.generateRawData(); - PumpMessage response = sendAndGetResponse(MessageType.SetBasalProfileSTD, basalProfile.getRawData()); + byte[] body = new byte[]{32, 0, 0, 38, 0, 13, 44, 0, 19, 38, 0, 28}; - // what kind of response are we expecting when set it sent - return response; - } + PumpMessage responseMessage; - // TODO test - public PumpMessage setTBR(TempBasalPair tbr) { + if (debugSetCommands) + LOG.debug("Set Basal Profile: Body [{}] - {}", body.length, HexDump.toHexStringDisplayable(body)); - // TODO check getAs Raw Data is correct data + // if (body.length <= 64) { + // + // PumpMessage msg = makePumpMessage(MedtronicCommandType.SetBasalProfileA, // + // new CarelinkLongMessageBody(ByteUtil.concat((byte) body.length, body))); + // + // responseMessage = runCommandWithArgs(msg); + // } else + { - PumpMessage response = sendAndGetResponse(MessageType.ChangeTempBasal, tbr.getAsRawData()); + responseMessage = runCommandWithArgsLong(MedtronicCommandType.SetBasalProfileA, body); + } - return response; + if (debugSetCommands) + LOG.debug("Set Basal Profile: {}", HexDump.toHexStringDisplayable(responseMessage.getRawContent())); + + return responseMessage.commandType == MedtronicCommandType.CommandACK; } - // TODO test - public PumpMessage cancelTBR() { - return setTBR(new TempBasalPair(0.0d, false, 0)); + + public byte[] getFullMessageBody(byte[] bodyData, int length) { + byte newBodyData[] = getEmptyMessage(length); + + newBodyData[0] = (byte) bodyData.length; + + for (int i = 0; i < bodyData.length; i++) { + newBodyData[i + 1] = bodyData[i]; + } + + return newBodyData; } - // TODO test ??? this might work correctly, check low value and some high value 25 (25 is max bolus) - public PumpMessage setBolus(double units) { - PumpMessage response = sendAndGetResponse(MessageType.Bolus, MedtronicUtil.getBolusStrokes(units)); - return response; + public byte[] getEmptyMessage(int length) { + byte newBodyData[] = new byte[length]; + for (int i = 0; i < length; i++) { + newBodyData[i] = 0x00; + } + + return newBodyData; } + public PumpMessage cancelBolus() { //? maybe suspend and resume return null; @@ -440,11 +742,12 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager public PumpMessage setExtendedBolus(double units, int duration) { // FIXME see decocare - PumpMessage response = sendAndGetResponse(MessageType.Bolus, MedtronicUtil.getBolusStrokes(units)); + PumpMessage response = sendAndGetResponse(MedtronicCommandType.SetBolus, MedtronicUtil.getBolusStrokes(units)); return response; } + public PumpMessage cancelExtendedBolus() { // set cancelBolus return null; @@ -454,94 +757,53 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // Cancel TBR (set TBR 100%) // Get Status (40%) - // Set Bolus 20% + // Set Bolus 80% // Set Extended Bolus 20% // Cancel Bolus 0% ? // Cancel Extended Bolus 0% ? - // Get Basal Profile (0x92) Read STD 20% + // Get Basal Profile (0x92) Read STD 100% // Set Basal Profile 20% // Read History 60% // Load TDD ? - public void updatePumpManagerStatus() { + public void updatePumpManagerStatus() { Integer resp = getRemainingBattery(); pumpStatus.batteryRemaining = resp == null ? -1 : resp; - //pumpStatus.remainUnits = getRemainingInsulin(); + pumpStatus.remainUnits = getRemainingInsulin(); /* current basal */ - TempBasalPair basalRate = getCurrentBasalRate(); + //TempBasalPair basalRate = getCurrentBasalRate(); // FIXME -// byte[] basalRateBytes = resp.getContents(); -// if (basalRateBytes != null) { -// if (basalRateBytes.length == 2) { -// /** -// * 0x98 0x06 -// * 0x98 is "basal rate" -// * 0x06 is what? Not currently running a temp basal, current basal is "standard" at 0 -// */ -// double basalRate = ByteUtil.asUINT8(basalRateBytes[1]); -// pumpStatus.currentBasal = basalRate; -// } -// } + // byte[] basalRateBytes = resp.getContents(); + // if (basalRateBytes != null) { + // if (basalRateBytes.length == 2) { + // /** + // * 0x98 0x06 + // * 0x98 is "basal rate" + // * 0x06 is what? Not currently running a temp basal, current basal is "standard" at 0 + // */ + // double basalRate = ByteUtil.asUINT8(basalRateBytes[1]); + // pumpStatus.currentBasal = basalRate; + // } + // } // get last bolus amount // get last bolus time // get tempBasalInProgress // get tempBasalRatio // get tempBasalRemainMin // get tempBasalStart - // get pump time - LocalDateTime clockResult = getPumpRTC(); + LocalDateTime clockResult = getPumpTime(); if (clockResult != null) { - //pumpStatus.time = clockResult.toDate(); + pumpStatus.time = clockResult.toDate(); } // get last sync time } - public void testPageDecode() { - byte[] raw = new byte[]{(byte) 0x6D, (byte) 0x62, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x63, (byte) 0x10, (byte) 0x6D, (byte) 0x63, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x5A, (byte) 0xA5, (byte) 0x49, (byte) 0x04, (byte) 0x10, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x6D, (byte) 0xA5, (byte) 0x49, (byte) 0x04, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x10, (byte) 0x6D, (byte) 0x64, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x64, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x0C, (byte) 0x00, - (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x01, (byte) 0x75, (byte) 0x94, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x64, (byte) 0x01, (byte) 0x44, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x17, (byte) 0x00, (byte) 0x4E, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, (byte) 0x18, (byte) 0x00, (byte) 0x40, (byte) 0x95, (byte) 0x0D, (byte) 0x05, (byte) 0x10, - (byte) 0x19, (byte) 0x00, (byte) 0x40, (byte) 0x81, (byte) 0x15, (byte) 0x05, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x65, (byte) 0x10, (byte) 0x6D, (byte) 0x65, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1A, (byte) 0x00, (byte) 0x47, (byte) 0x82, (byte) 0x09, (byte) 0x06, - (byte) 0x10, (byte) 0x1A, (byte) 0x01, (byte) 0x5C, (byte) 0x82, (byte) 0x09, (byte) 0x06, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x66, (byte) 0x10, (byte) 0x6D, (byte) 0x66, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x67, (byte) 0x10, (byte) 0x6D, (byte) 0x67, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x68, (byte) 0x10, (byte) 0x6D, (byte) 0x68, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x69, (byte) 0x10, (byte) 0x6D, (byte) 0x69, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6A, (byte) 0x10, (byte) 0x6D, (byte) 0x6A, (byte) 0x10, (byte) 0x05, (byte) 0x0C, - (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6B, (byte) 0x10, (byte) 0x6D, (byte) 0x6B, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6C, - (byte) 0x10, (byte) 0x6D, (byte) 0x6C, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6D, (byte) 0x10, (byte) 0x6D, (byte) 0x6D, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6E, (byte) 0x10, (byte) 0x6D, (byte) 0x6E, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x6F, (byte) 0x10, (byte) 0x6D, (byte) 0x6F, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, - (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x19, (byte) 0x00, (byte) 0x40, (byte) 0x81, (byte) 0x03, (byte) 0x10, (byte) 0x10, (byte) 0x1A, (byte) 0x00, (byte) 0x68, (byte) 0x96, (byte) 0x0A, (byte) 0x10, (byte) 0x10, (byte) 0x1A, (byte) 0x01, (byte) 0x40, (byte) 0x97, (byte) 0x0A, (byte) 0x10, (byte) 0x10, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x70, (byte) 0x10, (byte) 0x6D, (byte) 0x70, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x71, (byte) 0x10, (byte) 0x6D, (byte) 0x71, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x72, (byte) 0x10, (byte) 0x6D, (byte) 0x72, (byte) 0x10, (byte) 0x05, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x73, (byte) 0x10, (byte) 0x6D, (byte) 0x73, (byte) 0x10, (byte) 0x05, (byte) 0x0C, - (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0xE8, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x74, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2C, (byte) 0x79, - }; - Page page = new Page(); - page.parseFrom(raw, PumpModel.MM522); - page.parseByDates(raw, PumpModel.MM522); - page.parsePicky(raw, PumpModel.MM522); - LOG.info("testPageDecode: done"); - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfile.java index c3994788bd..aeda12bbc6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfile.java @@ -33,9 +33,10 @@ public class BasalProfile { private static final Logger LOG = LoggerFactory.getLogger(BasalProfile.class); private static final boolean DEBUG_BASALPROFILE = false; - protected static final int MAX_RAW_DATA_SIZE = (21 * 3) + 1; + protected static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1; protected byte[] mRawData; // store as byte array to make transport (via parcel) easier + public BasalProfile() { init(); } @@ -53,17 +54,20 @@ public class BasalProfile { mRawData[2] = 0x3f; } + // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. protected static int readUnsignedByte(byte b) { return (b < 0) ? b + 256 : b; } + public boolean setRawData(byte[] data) { if (data == null) { LOG.error("setRawData: buffer is null!"); return false; } int len = Math.min(MAX_RAW_DATA_SIZE, data.length); + mRawData = new byte[len]; System.arraycopy(data, 0, mRawData, 0, len); if (DEBUG_BASALPROFILE) { LOG.debug(String.format("setRawData: copied raw data buffer of %d bytes.", len)); @@ -71,27 +75,40 @@ public class BasalProfile { return true; } + public void dumpBasalProfile() { LOG.debug("Basal Profile entries:"); List entries = getEntries(); - for (int i = 0; i < entries.size(); i++) { + for(int i = 0; i < entries.size(); i++) { BasalProfileEntry entry = entries.get(i); String startString = entry.startTime.toString("HH:mm"); - LOG.debug(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", - i + 1, entry.rate, entry.rate_raw, - startString, entry.startTime_raw)); + LOG.debug(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", i + 1, entry.rate, entry.rate_raw, startString, entry.startTime_raw)); } } + + public String getBasalProfileAsString() { + StringBuffer sb = new StringBuffer("Basal Profile entries:\n"); + List entries = getEntries(); + for(int i = 0; i < entries.size(); i++) { + BasalProfileEntry entry = entries.get(i); + String startString = entry.startTime.toString("HH:mm"); + + sb.append(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)\n", i + 1, entry.rate, entry.rate_raw, startString, entry.startTime_raw)); + } + + return sb.toString(); + } + + // TODO: this function must be expanded to include changes in which profile is in use. // and changes to the profiles themselves. public BasalProfileEntry getEntryForTime(Instant when) { BasalProfileEntry rval = new BasalProfileEntry(); List entries = getEntries(); if (entries.size() == 0) { - LOG.warn(String.format("getEntryForTime(%s): table is empty", - when.toDateTime().toLocalTime().toString("HH:mm"))); + LOG.warn(String.format("getEntryForTime(%s): table is empty", when.toDateTime().toLocalTime().toString("HH:mm"))); return rval; } //Log.w(TAG,"Assuming first entry"); @@ -107,16 +124,16 @@ public class BasalProfile { while (!done) { BasalProfileEntry entry = entries.get(i); if (DEBUG_BASALPROFILE) { - LOG.debug(String.format("Comparing 'now'=%s to entry 'start time'=%s", - when.toDateTime().toLocalTime().toString("HH:mm"), - entry.startTime.toString("HH:mm"))); + LOG.debug(String.format("Comparing 'now'=%s to entry 'start time'=%s", when.toDateTime().toLocalTime().toString("HH:mm"), entry.startTime.toString("HH:mm"))); } if (localMillis >= entry.startTime.getMillisOfDay()) { rval = entry; - if (DEBUG_BASALPROFILE) LOG.debug("Accepted Entry"); + if (DEBUG_BASALPROFILE) + LOG.debug("Accepted Entry"); } else { // entry at i has later start time, keep older entry - if (DEBUG_BASALPROFILE) LOG.debug("Rejected Entry"); + if (DEBUG_BASALPROFILE) + LOG.debug("Rejected Entry"); done = true; } i++; @@ -125,14 +142,12 @@ public class BasalProfile { } } if (DEBUG_BASALPROFILE) { - LOG.debug(String.format("getEntryForTime(%s): Returning entry: rate=%.3f (%d), start=%s (%d)", - when.toDateTime().toLocalTime().toString("HH:mm"), - rval.rate, rval.rate_raw, - rval.startTime.toString("HH:mm"), rval.startTime_raw)); + LOG.debug(String.format("getEntryForTime(%s): Returning entry: rate=%.3f (%d), start=%s (%d)", when.toDateTime().toLocalTime().toString("HH:mm"), rval.rate, rval.rate_raw, rval.startTime.toString("HH:mm"), rval.startTime_raw)); } return rval; } + public List getEntries() { List entries = new ArrayList<>(); @@ -163,6 +178,11 @@ public class BasalProfile { List listEntries; + /** + * This is used to prepare new profile + * + * @param entry + */ public void addEntry(BasalProfileEntry entry) { if (listEntries == null) listEntries = new ArrayList<>(); @@ -171,40 +191,35 @@ public class BasalProfile { } - public void generateRawData() { + public byte[] generateRawData() { List outData = new ArrayList<>(); - for (BasalProfileEntry profileEntry : listEntries) { + for(BasalProfileEntry profileEntry : listEntries) { byte[] strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true); // TODO check if this is correct - outData.add(strokes[0]); - outData.add(strokes[1]); + outData.add(profileEntry.rate_raw[0]); + outData.add(profileEntry.rate_raw[1]); - int time = profileEntry.startTime.getHourOfDay(); + //int time = profileEntry.startTime.getHourOfDay(); - if (profileEntry.startTime.getMinuteOfHour() == 30) { - time++; - } + //if (profileEntry.startTime.getMinuteOfHour() == 30) { + // time++; + //} - outData.add((byte) time); + outData.add(profileEntry.startTime_raw); } this.setRawData(MedtronicUtil.createByteArray(outData)); + + return this.mRawData; } public static void testParser() { - byte[] testData = new byte[]{ - 32, 0, 0, - 38, 0, 13, - 44, 0, 19, - 38, 0, 28, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0}; + byte[] testData = new byte[]{32, 0, 0, 38, 0, 13, 44, 0, 19, 38, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* from decocare: _test_schedule = {'total': 22.50, 'schedule': [ { 'start': '12:00A', 'rate': 0.80 }, @@ -219,16 +234,15 @@ public class BasalProfile { if (entries.isEmpty()) { LOG.error("testParser: failed"); } else { - for (int i = 0; i < entries.size(); i++) { + for(int i = 0; i < entries.size(); i++) { BasalProfileEntry e = entries.get(i); - LOG.debug(String.format("testParser entry #%d: rate: %.2f, start %d:%d", - i, e.rate, e.startTime.getHourOfDay(), - e.startTime.getMinuteOfHour())); + LOG.debug(String.format("testParser entry #%d: rate: %.2f, start %d:%d", i, e.rate, e.startTime.getHourOfDay(), e.startTime.getMinuteOfHour())); } } } + public byte[] getRawData() { return this.mRawData; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfileEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfileEntry.java index 1c34cf0178..9af7e8e173 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfileEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/BasalProfileEntry.java @@ -2,30 +2,55 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data; import org.joda.time.LocalTime; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; + /** * Created by geoff on 6/1/15. * This is a helper class for BasalProfile, only used for interpreting the contents of BasalProfile + * - fixed rate is not one bit but two */ public class BasalProfileEntry { - public byte rate_raw; + public byte[] rate_raw; public double rate; public byte startTime_raw; public LocalTime startTime; // Just a "time of day" - // FIXME rate is two bits not one -- Andy see MedtronicUtil + public BasalProfileEntry() { rate = -9.999E6; - rate_raw = (byte) 0xFF; + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(0xFF, true); startTime = new LocalTime(0); startTime_raw = (byte) 0xFF; } - public BasalProfileEntry(int rateByte, int startTimeByte) { + + public BasalProfileEntry(int rateStrokes, int startTimeInterval) { // rateByte is insulin delivery rate, U/hr, in 0.025 U increments // startTimeByte is time-of-day, in 30 minute increments - rate_raw = (byte) rateByte; + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateStrokes, true); + rate = rateStrokes * 0.025; + startTime_raw = (byte) startTimeInterval; + startTime = new LocalTime(startTimeInterval / 2, (startTimeInterval % 2) * 30); + } + + + public BasalProfileEntry(byte rateByte, int startTimeByte) { + // rateByte is insulin delivery rate, U/hr, in 0.025 U increments + // startTimeByte is time-of-day, in 30 minute increments + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateByte, true); rate = rateByte * 0.025; startTime_raw = (byte) startTimeByte; startTime = new LocalTime(startTimeByte / 2, (startTimeByte % 2) * 30); } + + + public void setStartTime(LocalTime localTime) { + this.startTime = localTime; + } + + + public void setRate(double rate) { + this.rate = rate; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/Page.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/Page.java index 4a59879a33..e7a58728aa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/Page.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/Page.java @@ -44,21 +44,27 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.PumpTi import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.Record; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.RecordTypeEnum; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeFormat; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.IgnoredHistoryEntry; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; +@Deprecated public class Page { private final static String TAG = "Page"; private static final boolean DEBUG_PAGE = true; private byte[] crc; private byte[] data; - protected PumpModel model; + //protected PumpModel model; + public static MedtronicDeviceType model = MedtronicDeviceType.Medtronic_522; public List mRecordList; + public Page() { - this.model = PumpModel.UNSET; + this.model = MedtronicDeviceType.Unknown_Device; mRecordList = new ArrayList<>(); } + public byte[] getRawData() { if (data == null) { return crc; @@ -69,6 +75,7 @@ public class Page { return ByteUtil.concat(data, crc); } + protected PumpTimeStamp collectTimeStamp(byte[] data, int offset) { try { PumpTimeStamp timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, offset)); @@ -78,7 +85,8 @@ public class Page { } } - public boolean parsePicky(byte[] rawPage, PumpModel model) { + + public boolean parsePicky(byte[] rawPage, MedtronicDeviceType model) { mRecordList = new ArrayList<>(); this.model = model; int pageOffset = 0; @@ -102,8 +110,7 @@ public class Page { while (pageOffset < data.length) { if (data[pageOffset] == 0) { if (record != null) { - Log.i(TAG, String.format("End of page or Previous parse fail: prev opcode 0x%02x, curr offset %d, %d bytes remaining", - record.getRecordOp(), pageOffset, data.length - pageOffset + 1)); + Log.i(TAG, String.format("End of page or Previous parse fail: prev opcode 0x%02x, curr offset %d, %d bytes remaining", record.getRecordOp(), pageOffset, data.length - pageOffset + 1)); break; } else { Log.i(TAG, "WTF?"); @@ -125,8 +132,8 @@ public class Page { ArrayList pickyRecords = new ArrayList<>(); pickyRecords.addAll(mRecordList); parseByDates(rawPage, model); - for (Record r : mRecordList) { - for (Record r2 : pickyRecords) { + for(Record r : mRecordList) { + for(Record r2 : pickyRecords) { if (r.getFoundAtOffset() == r2.getFoundAtOffset()) { Log.v(TAG, "Found matching record at offset " + r.getFoundAtOffset()); } @@ -135,13 +142,14 @@ public class Page { return true; } - public boolean parseByDates(byte[] rawPage, PumpModel model) { + + public boolean parseByDates(byte[] rawPage, MedtronicDeviceType model) { mRecordList = new ArrayList<>(); if (rawPage.length != 1024) { Log.e(TAG, "Unexpected page size. Expected: 1024 Was: " + rawPage.length); //return false; } - this.model = model; + Page.model = model; if (DEBUG_PAGE) { Log.i(TAG, "Parsing page"); } @@ -197,7 +205,8 @@ public class Page { return true; } - public boolean parseFrom(byte[] rawPage, PumpModel model) { + + public boolean parseFrom(byte[] rawPage, MedtronicDeviceType model) { mRecordList = new ArrayList<>(); // wipe old contents each time when parsing. if (rawPage.length != 1024) { Log.e(TAG, "Unexpected page size. Expected: 1024 Was: " + rawPage.length); @@ -229,6 +238,7 @@ public class Page { int dataIndex = 0; boolean done = false; + Record previousRecord = null; while (!done) { Record record = null; if (data[dataIndex] != 0) { @@ -240,24 +250,65 @@ public class Page { } } else { Log.v(TAG, "Zero opcode encountered -- end of page. " + (rawPage.length - dataIndex) + " bytes remaining."); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Possible parsing problem: "); + stringBuilder.append("Previous record: " + previousRecord); + stringBuilder.append(" Content of previous record: " + HexDump.toHexStringDisplayable(previousRecord.getRawbytes())); + + int remainingData = rawPage.length - dataIndex; + byte[] tmpData = new byte[remainingData + 10]; + System.arraycopy(data, dataIndex, tmpData, 0, remainingData - 10); + + stringBuilder.append(" Remaining data: " + HexDump.toHexStringDisplayable(tmpData)); + + Log.v(TAG, stringBuilder.toString()); + break; } + if (record != null) { - Log.v(TAG, "parseFrom: found event " + record.getClass().getSimpleName() + " length=" + record.getLength() + " offset=" + record.getFoundAtOffset()); - mRecordList.add(record); + if (record instanceof IgnoredHistoryEntry) { + IgnoredHistoryEntry he = (IgnoredHistoryEntry) record; + Log.v(TAG, "parseFrom: found event " + he.getShortTypeName() + " length=" + record.getLength() + " offset=" + record.getFoundAtOffset() + " -- IGNORING"); + } else { + Log.v(TAG, "parseFrom: found event " + record.getClass().getSimpleName() + " length=" + record.getLength() + " offset=" + record.getFoundAtOffset()); + mRecordList.add(record); + } + dataIndex += record.getLength(); + } else { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Possible parsing problem: "); + stringBuilder.append("Previous record: " + previousRecord); + stringBuilder.append(" Content of previous record: " + HexDump.toHexStringDisplayable(previousRecord.getRawbytes())); + + int remainingData = data.length - dataIndex; + byte[] tmpData = Arrays.copyOfRange(data, dataIndex, 1022); + + + //new byte[remainingData]; + //System.arraycopy(data, dataIndex, tmpData, 0, remainingData - 2); + + stringBuilder.append(" Remaining data: " + HexDump.toHexStringDisplayable(tmpData)); + + Log.e(TAG, String.format("parseFrom: Failed to parse opcode 0x%02x, offset=%d", data[dataIndex], dataIndex)); done = true; } if (dataIndex >= data.length - 2) { done = true; } + + previousRecord = record; } + if (DEBUG_PAGE) { Log.i(TAG, String.format("Number of records: %d", mRecordList.size())); int index = 1; - for (Record r : mRecordList) { + for(Record r : mRecordList) { Log.v(TAG, String.format("Record #%d: %s", index, r.getShortTypeName())); index += 1; } @@ -265,6 +316,7 @@ public class Page { return true; } + /* attemptParseRecord will attempt to create a subclass of Record from the given * data and offset. It will return NULL if it fails. If it succeeds, the returned * subclass of Record can be examined for its length, so that the next attempt can be made. @@ -283,12 +335,12 @@ public class Page { } //Log.d(TAG,String.format("checking for handler for record type 0x%02X at index %d",data[offsetStart],offsetStart)); RecordTypeEnum en = RecordTypeEnum.fromByte(data[offsetStart]); - T record = en.getRecordClassInstance(PumpModel.MM522); + T record = en.getRecordClassInstance(model); if (record != null) { // have to do this to set the record's opCode byte[] tmpData = new byte[data.length]; System.arraycopy(data, offsetStart, tmpData, 0, data.length - offsetStart); - boolean didParse = record.parseWithOffset(tmpData, PumpModel.MM522, offsetStart); + boolean didParse = record.parseWithOffset(tmpData, model, offsetStart); if (!didParse) { Log.e(TAG, String.format("attemptParseRecord: class %s (opcode 0x%02X) failed to parse at offset %d", record.getShortTypeName(), data[offsetStart], offsetStart)); } @@ -296,6 +348,7 @@ public class Page { return record; } + public static DateTime parseSimpleDate(byte[] data, int offset) { DateTime timeStamp = null; int seconds = 0; @@ -325,6 +378,7 @@ public class Page { return timeStamp; } + public static void discoverRecords(byte[] data) { int i = 0; boolean done = false; @@ -332,7 +386,7 @@ public class Page { ArrayList keyLocations = new ArrayList(); while (!done) { RecordTypeEnum en = RecordTypeEnum.fromByte(data[i]); - if (en != RecordTypeEnum.RECORD_TYPE_NULL) { + if (en != RecordTypeEnum.Null) { keyLocations.add(i); Log.v(TAG, String.format("Possible record of type %s found at index %d", en, i)); } @@ -348,10 +402,10 @@ public class Page { done = (i >= data.length - 2); } // for each of the discovered key locations, attempt to parse a sequence of records - for (RecordTypeEnum en : RecordTypeEnum.values()) { + for(RecordTypeEnum en : RecordTypeEnum.values()) { } - for (int ix = 0; ix < keyLocations.size(); ix++) { + for(int ix = 0; ix < keyLocations.size(); ix++) { } } @@ -369,13 +423,14 @@ public class Page { public List mRecordList; */ + public Bundle pack() { Bundle bundle = new Bundle(); bundle.putByteArray("crc", crc); bundle.putByteArray("data", data); - bundle.putString("model", PumpModel.toString(model)); + bundle.putString("model", model.name()); ArrayList records = new ArrayList<>(); - for (int i = 0; i < mRecordList.size(); i++) { + for(int i = 0; i < mRecordList.size(); i++) { try { records.add(mRecordList.get(i).dictionaryRepresentation()); } catch (NullPointerException e) { @@ -386,14 +441,15 @@ public class Page { return bundle; } + public void unpack(Bundle in) { crc = in.getByteArray("crc"); data = in.getByteArray("data"); - model = PumpModel.fromString(in.getString("model")); + model = MedtronicDeviceType.valueOf(in.getString("model")); ArrayList records = in.getParcelableArrayList("mRecordList"); mRecordList = new ArrayList<>(); if (records != null) { - for (int i = 0; i < records.size(); i++) { + for(int i = 0; i < records.size(); i++) { Record r = RecordTypeEnum.getRecordClassInstance(records.get(i), model); r.readFromBundle(records.get(i)); mRecordList.add(r); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/PumpModel.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/PumpModel.java deleted file mode 100644 index 696191d74a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/PumpModel.java +++ /dev/null @@ -1,58 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data; -// cribbed from: -//package com.nightscout.core.drivers.Medtronic; - -/** - * Created by geoff on 5/13/15. - */ - -public enum PumpModel { - UNSET, - MM508, - MM515, - MM522, - MM523; - - public static boolean isLargerFormat(PumpModel model) { - if (model == MM523) { - return true; - } - return false; - } - - public static String toString(PumpModel model) { - switch (model) { - case UNSET: - return "UNSET"; - case MM508: - return "508"; - case MM515: - return "515"; - case MM522: - return "522"; - case MM523: - return "523"; - default: - return "(error)"; - } - } - - public static PumpModel fromString(String s) { - if ("UNSET".equals(s)) { - return UNSET; - } - if (("508".equals(s)) || ("MM508".equals(s))) { - return MM508; - } - if (("515".equals(s)) || ("MM515".equals(s))) { - return MM515; - } - if (("522".equals(s)) || ("MM522".equals(s))) { - return MM522; - } - if (("523".equals(s)) || ("MM523".equals(s))) { - return MM523; - } - return UNSET; - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/RawHistoryPage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/RawHistoryPage.java index 15e900b595..cd4fa62de2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/RawHistoryPage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/RawHistoryPage.java @@ -2,39 +2,67 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data; import android.util.Log; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; /** * Created by geoff on 6/4/16. */ public class RawHistoryPage { private static final String TAG = "RawHistoryPage"; + private static final Logger LOG = LoggerFactory.getLogger(RawHistoryPage.class); byte[] data = new byte[0]; + public RawHistoryPage() { } + public void appendData(byte[] newdata) { data = ByteUtil.concat(data, newdata); } + public byte[] getData() { return data; } + + public byte[] getOnlyData() { + return Arrays.copyOfRange(data, 0, 1022); + } + + public int getLength() { return data.length; } + public boolean isChecksumOK() { if (getLength() != 1024) { return false; } byte[] computedCRC = CRC.calculate16CCITT(ByteUtil.substring(data, 0, 1022)); - return ((computedCRC[0] == data[1022]) && (computedCRC[1] == data[1023])); + + int crcCalculated = ByteUtil.toInt(computedCRC[0], computedCRC[1]); + int crcStored = ByteUtil.toInt(data[1022], data[1023]); + + if (crcCalculated != crcStored) { + LOG.error("Stored CRC ({}) is different than calculated ({}), but ignored for now.", crcStored, crcCalculated); + } else { + if (MedtronicUtil.isLowLevelDebug()) LOG.debug("CRC ok."); + } + + return crcCalculated == crcStored; } + public void dumpToDebug() { int linesize = 80; int offset = 0; @@ -47,4 +75,6 @@ public class RawHistoryPage { offset += linesize; } } + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/TempBasalPair.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/TempBasalPair.java index 1f312425f4..da8abd75d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/TempBasalPair.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/TempBasalPair.java @@ -1,5 +1,8 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; @@ -11,77 +14,111 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; * Just need a class to keep the pair together, for parcel transport. */ public class TempBasalPair { - private double mInsulinRate = 0.0; - private int mDurationMinutes = 0; - private boolean mIsPercent = false; + + private static final Logger LOG = LoggerFactory.getLogger(TempBasalPair.class); + + private double insulinRate = 0.0; + private int durationMinutes = 0; + private boolean isPercent = false; + public double getInsulinRate() { - return mInsulinRate; + return insulinRate; } + public void setInsulinRate(double insulinRate) { - this.mInsulinRate = insulinRate; + this.insulinRate = insulinRate; } + public int getDurationMinutes() { - return mDurationMinutes; + return durationMinutes; } + public void setDurationMinutes(int durationMinutes) { - this.mDurationMinutes = durationMinutes; + this.durationMinutes = durationMinutes; } + public boolean isPercent() { - return mIsPercent; + return isPercent; } + public void setIsPercent(boolean yesIsPercent) { - this.mIsPercent = yesIsPercent; + this.isPercent = yesIsPercent; } + public TempBasalPair() { } + public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) { - mInsulinRate = insulinRate; - mIsPercent = isPercent; - mDurationMinutes = durationMinutes; + this.insulinRate = insulinRate; + this.isPercent = isPercent; + this.durationMinutes = durationMinutes; } public TempBasalPair(byte[] response) { - mIsPercent = response[0] == 1; + LOG.debug("Received response: " + response); - if (mIsPercent) { - mInsulinRate = response[1]; + isPercent = response[0] == 1; + + if (isPercent) { + insulinRate = response[1]; } else { int strokes = MedtronicUtil.makeUnsignedShort(response[2], response[3]); - mInsulinRate = strokes / 40.0d; + insulinRate = strokes / 40.0d; } - mDurationMinutes = MedtronicUtil.makeUnsignedShort(response[4], response[5]); + durationMinutes = MedtronicUtil.makeUnsignedShort(response[4], response[5]); } + public byte[] getAsRawData() { + // TODO check if this works with 523 and higher List list = new ArrayList(); - list.add((byte) 0); // absolute - list.add((byte) 0); // percent amount + list.add((byte) 5); - byte[] insulinRate = MedtronicUtil.getBasalStrokes(mInsulinRate, true); + byte[] insulinRate = MedtronicUtil.getBasalStrokes(this.insulinRate, true); + byte[] timeMin = MedtronicUtil.getByteArrayFromUnsignedShort(MedtronicUtil.getIntervalFromMinutes(durationMinutes), true); + + //list.add((byte) 0); // ? + + //list.add((byte) 0); // is_absolute + + if (insulinRate.length == 1) + list.add((byte) 0x00); + else + list.add(insulinRate[1]); list.add(insulinRate[0]); - list.add(insulinRate[1]); + //list.add((byte) 0); // percent amount - byte[] timeMin = MedtronicUtil.getByteArrayFromUnsignedShort(mDurationMinutes, true); + list.add(timeMin[0]); // 3 (time) - OK - list.add(timeMin[0]); - list.add(timeMin[1]); + if (insulinRate.length == 1) + list.add((byte) 0x00); + else + list.add(insulinRate[1]); + + list.add(insulinRate[0]); return MedtronicUtil.createByteArray(list); } + + + @Override + public String toString() { + return "TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent=" + isPercent + "]"; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/Record.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/Record.java index d2247ea26a..2fb68848b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/Record.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/Record.java @@ -2,38 +2,44 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history; import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; abstract public class Record { - protected PumpModel model; + protected MedtronicDeviceType model; protected byte recordOp; //protected int length; protected int foundAtOffset; protected byte[] rawbytes = new byte[0]; //protected String recordTypeName = this.getClass().getSimpleName(); + public String getRecordTypeName() { return this.getClass().getSimpleName(); } + public String getShortTypeName() { return this.getClass().getSimpleName(); } - public void setPumpModel(PumpModel model) { + + public void setPumpModel(MedtronicDeviceType model) { this.model = model; } + public int getFoundAtOffset() { return foundAtOffset; } + public Record() { } - public boolean parseWithOffset(byte[] data, PumpModel model, int foundAtOffset) { + + public boolean parseWithOffset(byte[] data, MedtronicDeviceType model, int foundAtOffset) { // keep track of where the record was found for later analysis this.foundAtOffset = foundAtOffset; if (data == null) { @@ -50,37 +56,45 @@ abstract public class Record { return didParse; } + public void captureRawBytes(byte[] data) { this.rawbytes = new byte[getLength()]; System.arraycopy(data, 0, this.rawbytes, 0, getLength() - 1); } - public boolean parseFrom(byte[] data, PumpModel model) { + + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { return true; } + public PumpTimeStamp getTimestamp() { return new PumpTimeStamp(); } + public int getLength() { return 1; } + public byte getRecordOp() { return recordOp; } + protected static int asUINT8(byte b) { return (b < 0) ? b + 256 : b; } + public Bundle dictionaryRepresentation() { Bundle rval = new Bundle(); writeToBundle(rval); return rval; } + public boolean readFromBundle(Bundle in) { // length is determined at instantiation // record type name is "static" @@ -88,6 +102,12 @@ abstract public class Record { return true; } + + public boolean isLargerFormat() { + return MedtronicDeviceType.isLargerFormat(model); + } + + public void writeToBundle(Bundle in) { in.putInt("length", getLength()); in.putInt("foundAtOffset", foundAtOffset); @@ -97,6 +117,12 @@ abstract public class Record { in.putByteArray("rawbytes", rawbytes); } + + public byte[] getRawbytes() { + return rawbytes; + } + + public abstract boolean isAAPSRelevant(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/RecordTypeEnum.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/RecordTypeEnum.java index ecfee5c792..c7546d918e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/RecordTypeEnum.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/RecordTypeEnum.java @@ -4,8 +4,8 @@ import android.os.Bundle; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Map; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.AlarmClockReminderPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.AlarmSensorPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.BGReceivedPumpEvent; @@ -43,6 +43,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.DeleteBolusReminderTimePumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.DeleteOtherDeviceIDPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.EnableDisableRemotePumpEvent; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.IgnoredHistoryEntry; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.InsulinMarkerEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.JournalEntryExerciseMarkerPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.JournalEntryPumpLowBatteryPumpEvent; @@ -54,103 +55,181 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.ResultDailyTotalPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.ResumePumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.RewindPumpEvent; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.Sara6EPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.SuspendPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.TempBasalDurationPumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.TempBasalRatePumpEvent; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.UnabsorbedInsulin; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record.Unknown7ByteEvent1; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; /** * Created by geoff on 5/28/15. */ +@Deprecated public enum RecordTypeEnum { - RECORD_TYPE_NULL((byte) 0x00, null), - RECORD_TYPE_BOLUSNORMAL((byte) 0x01, BolusNormalPumpEvent.class), - RECORD_TYPE_PRIME((byte) 0x03, PrimePumpEvent.class), - RECORD_TYPE_ALARMPUMP((byte) 0x06, PumpAlarmPumpEvent.class), - RECORD_TYPE_RESULTDAILYTOTAL((byte) 0x07, ResultDailyTotalPumpEvent.class), - RECORD_TYPE_CHANGEBASALPROFILEPATTERN((byte) 0x08, ChangeBasalProfilePatternPumpEvent.class), - RECORD_TYPE_CHANGEBASALPROFILE((byte) 0x09, ChangeBasalProfilePumpEvent.class), - RECORD_TYPE_CALBGFORPH((byte) 0x0A, CalBgForPhPumpEvent.class), - RECORD_TYPE_ALARMSENSOR((byte) 0x0B, AlarmSensorPumpEvent.class), - RECORD_TYPE_CLEARALARM((byte) 0x0C, ClearAlarmPumpEvent.class), - //RECORD_TYPE_SELECTBASALPROFILE((byte)0x14,SelectBasalProfile.class), - RECORD_TYPE_TEMPBASALDURATION((byte) 0x16, TempBasalDurationPumpEvent.class), - RECORD_TYPE_CHANGETIME((byte) 0x17, ChangeTimePumpEvent.class), - RECORD_TYPE_NEWTIMESET((byte) 0x18, NewTimeSet.class), - RECORD_TYPE_JournalEntryPumpLowBattery((byte) 0x19, JournalEntryPumpLowBatteryPumpEvent.class), - RECORD_TYPE_BATTERY((byte) 0x1A, BatteryPumpEvent.class), - RECORD_TYPE_PUMPSUSPENDED((byte) 0x1E, SuspendPumpEvent.class), - RECORD_TYPE_PUMPRESUMED((byte) 0x1F, ResumePumpEvent.class), - RECORD_TYPE_REWIND((byte) 0x21, RewindPumpEvent.class), - RECORD_TYPE_CHANGECHILDBLOCKENABLE((byte) 0x23, ChangeChildBlockEnablePumpEvent.class), - RECORD_TYPE_CHANGEMAXBOLUS((byte) 0x24, ChangeMaxBolusPumpEvent.class), - RECORD_TYPE_ENABLEDISABLEREMOTE((byte) 0x26, EnableDisableRemotePumpEvent.class), - RECORD_TYPE_TEMPBASALRATE((byte) 0x33, TempBasalRatePumpEvent.class), - RECORD_TYPE_LOWRESERVOIR((byte) 0x34, JournalEntryPumpLowReservoirPumpEvent.class), - RECORD_TYPE_AlarmClockReminder((byte) 0x35, AlarmClockReminderPumpEvent.class), - RECORD_TYPE_BGRECEIVED((byte) 0x3F, BGReceivedPumpEvent.class), - RECORD_TYPE_JournalEntryExerciseMarker((byte) 0x41, JournalEntryExerciseMarkerPumpEvent.class), - RECORD_TYPE_Unknown7Byte_1((byte) 0x42, Unknown7ByteEvent1.class), - RECORD_TYPE_InsulinMarker((byte) 0x43, InsulinMarkerEvent.class), - RECORD_TYPE_CHANGESENSORSETUP2((byte) 0x50, ChangeSensorSetup2PumpEvent.class), - RECORD_TYPE_ChangeSensorRateOfChangeAlertSetup((byte) 0x56, ChangeSensorRateOfChangeAlertSetupPumpEvent.class), - RECORD_TYPE_ChangeBolusScrollStepSize((byte) 0x57, ChangeBolusScrollStepSizePumpEvent.class), - RECORD_TYPE_ChangeBolusWizardSetup((byte) 0x5A, ChangeBolusWizardSetupPumpEvent.class), - RECORD_TYPE_BolusWizardBolusEstimate((byte) 0x5B, BolusWizardBolusEstimatePumpEvent.class), - RECORD_TYPE_UNABSORBEDINSULIN((byte) 0x5C, UnabsorbedInsulin.class), - RECORD_TYPE_CHANGEVARIABLEBOLUS((byte) 0x5e, ChangeVariableBolusPumpEvent.class), - RECORD_TYPE_CHANGEAUDIOBOLUS((byte) 0x5f, ChangeAudioBolusPumpEvent.class), - RECORD_TYPE_ChangeBGReminderEnable((byte) 0x60, ChangeBGReminderEnablePumpEvent.class), - RECORD_TYPE_ChangeAlarmClockEnable((byte) 0x61, ChangeAlarmClockEnablePumpEvent.class), - RECORD_TYPE_ChangeTempBasalType((byte) 0x62, ChangeTempBasalTypePumpEvent.class), - RECORD_TYPE_ChangeAlarmNotifyMode((byte) 0x63, ChangeAlarmNotifyModePumpEvent.class), - RECORD_TYPE_ChangeTimeFormat((byte) 0x64, ChangeTimeFormatPumpEvent.class), - RECORD_TYPE_ChangeReservoirWarningTime((byte) 0x65, ChangeReservoirWarningTimePumpEvent.class), - RECORD_TYPE_ChangeBolusReminderEnable((byte) 0x66, ChangeBolusReminderEnablePumpEvent.class), - RECORD_TYPE_ChangeBolusReminderTime((byte) 0x67, ChangeBolusReminderTimePumpEvent.class), - RECORD_TYPE_DeleteBolusReminderTime((byte) 0x68, DeleteBolusReminderTimePumpEvent.class), - RECORD_TYPE_DeleteAlarmClockTime((byte) 0x6a, DeleteAlarmClockTimePumpEvent.class), - RECORD_TYPE_MODEL522RESULTTOTALS((byte) 0x6D, Model522ResultTotalsPumpEvent.class), - RECORD_TYPE_SARA6E((byte) 0x6E, Sara6EPumpEvent.class), - RECORD_TYPE_ChangeCarbUnits((byte) 0x6f, ChangeCarbUnitsPumpEvent.class), - RECORD_TYPE_BASALPROFILESTART((byte) 0x7B, BasalProfileStart.class), - RECORD_TYPE_ChangeWatchdogEnable((byte) 0x7c, ChangeWatchdogEnablePumpEvent.class), - RECORD_TYPE_CHANGEOTHERDEVICEID((byte) 0x7d, ChangeOtherDeviceIDPumpEvent.class), - RECORD_TYPE_ChangeWatchdogMarriageProfile((byte) 0x81, ChangeWatchdogMarriageProfilePumpEvent.class), - RECORD_TYPE_DeleteOtherDeviceID((byte) 0x82, DeleteOtherDeviceIDPumpEvent.class), - RECORD_TYPE_ChangeCaptureEventEnable((byte) 0x83, ChangeCaptureEventEnablePumpEvent.class); + + Null((byte) 0x00, null, 0), // + + // Good Events + BolusNormal(0x01, BolusNormalPumpEvent.class), // OK + Prime((byte) 0x03, PrimePumpEvent.class), // OK + AlarmPump((byte) 0x06, PumpAlarmPumpEvent.class), // + ResultDailyTotal((byte) 0x07, ResultDailyTotalPumpEvent.class), // OK + ChangeBasalProfile_old_profile((byte) 0x08, ChangeBasalProfilePatternPumpEvent.class), // OK + ChangeBasalProfile_new_profile((byte) 0x09, ChangeBasalProfilePumpEvent.class), // OK + + CalBgForPh((byte) 0x0A, CalBgForPhPumpEvent.class), // + AlarmSensor((byte) 0x0B, AlarmSensorPumpEvent.class), // + ClearAlarm((byte) 0x0C, ClearAlarmPumpEvent.class), // + SelectBasalProfile((byte) 0x14, IgnoredHistoryEntry.class, 7), // OK + TempBasalDuration((byte) 0x16, TempBasalDurationPumpEvent.class), // OK + ChangeTime((byte) 0x17, ChangeTimePumpEvent.class), // OK + NewTimeSet((byte) 0x18, NewTimeSet.class), // OK + JournalEntryPumpLowBattery((byte) 0x19, JournalEntryPumpLowBatteryPumpEvent.class), // + RECORD_TYPE_BATTERY((byte) 0x1A, BatteryPumpEvent.class), // + SetAutoOff(0x1b, 7), // + Suspend((byte) 0x1E, SuspendPumpEvent.class), // OK + Resume((byte) 0x1F, ResumePumpEvent.class), // OK + SelfTest(0x20, 7), // + Rewind((byte) 0x21, RewindPumpEvent.class), // + ClearSettings(0x22, 7), // + ChangeChildBlockEnable((byte) 0x23, ChangeChildBlockEnablePumpEvent.class), // + ChangeMaxBolus((byte) 0x24, ChangeMaxBolusPumpEvent.class), // + EnableDisableRemote((byte) 0x26, EnableDisableRemotePumpEvent.class), // + ChangeMaxBasal(0x2c, 7), // + EnableBolusWizard(0x2d, 7), // + Andy2E(0x2e, 7), // + Andy2F(0x2f, 7), // + Andy30(0x30, 7), // + ChangeBGReminderOffset(0x31, 7), // + ChangeAlarmClockTime(0x32, 7), // + tempBasal((byte) 0x33, TempBasalRatePumpEvent.class), // + journalEntryPumpLowReservoir((byte) 0x34, JournalEntryPumpLowReservoirPumpEvent.class), // + AlarmClockReminder((byte) 0x35, AlarmClockReminderPumpEvent.class), // + ChangeMeterId(0x36, 7), // 715 = 21 ?? + MM512_Event_0x37(0x37, 7), // + MM512_Event_0x38(0x38, 7), // + MM512_Event_0x39(0x39, 7), // + MM512_Event_0x3A(0x3A, 7), // + MM512_Event_0x3B(0x3b, 7), // Questionable3b + changeParadigmLinkID(0x3c, 7), // + MM512_Event_0x3D(0x3D, 7), // + MM512_Event_0x3E(0x3e, 7), // + bgReceived((byte) 0x3F, BGReceivedPumpEvent.class), // + JournalEntryMealMarker(0x40, 7), // + JournalEntryExerciseMarker((byte) 0x41, JournalEntryExerciseMarkerPumpEvent.class), // + JournalEntryInsulinMarker((byte) 0x42, Unknown7ByteEvent1.class), // + journalEntryOtherMarker((byte) 0x43, InsulinMarkerEvent.class), // + + MM512_Event_0x44(0x44, 7), // + MM512_Event_0x45(0x45, 7), // + MM512_Event_0x46(0x46, 7), // + MM512_Event_0x47(0x47, 7), // + MM512_Event_0x48(0x48, 7), // + MM512_Event_0x49(0x49, 7), // + MM512_Event_0x4a(0x4a, 7), // + MM512_Event_0x4b(0x4b, 7), // + MM512_Event_0x4c(0x4c, 7), // + MM512_Event_0x4d(0x4d, 7), // + MM512_Event_0x4e(0x4e, 7), // + + + // case changeBolusWizardSetup = 0x4f, 7), // + + changeSensorSetup2((byte) 0x50, ChangeSensorSetup2PumpEvent.class), // + // case restoreMystery51 = 0x51, 7), // + // case restoreMystery52 = 0x52, 7), // + // case changeSensorAlarmSilenceConfig = 0x53, 7), // + // case restoreMystery54 = 0x54, 7), // + // case restoreMystery55 = 0x55, 7), // + ChangeSensorRateOfChangeAlertSetup((byte) 0x56, ChangeSensorRateOfChangeAlertSetupPumpEvent.class), // + ChangeBolusScrollStepSize((byte) 0x57, ChangeBolusScrollStepSizePumpEvent.class), // + ChangeBolusWizardSetup((byte) 0x5A, ChangeBolusWizardSetupPumpEvent.class), // + BolusWizardBolusEstimate((byte) 0x5B, BolusWizardBolusEstimatePumpEvent.class), // + unabsorbedInsulin((byte) 0x5C, UnabsorbedInsulin.class), // + // case saveSettings = 0x5d, 7), // + changeVariableBolus((byte) 0x5e, ChangeVariableBolusPumpEvent.class), // + changeAudioBolus((byte) 0x5f, ChangeAudioBolusPumpEvent.class), // + ChangeBGReminderEnable((byte) 0x60, ChangeBGReminderEnablePumpEvent.class), // + ChangeAlarmClockEnable((byte) 0x61, ChangeAlarmClockEnablePumpEvent.class), // + + + ChangeTempBasalType((byte) 0x62, ChangeTempBasalTypePumpEvent.class), // + ChangeAlarmNotifyMode((byte) 0x63, ChangeAlarmNotifyModePumpEvent.class), // + ChangeTimeFormat((byte) 0x64, ChangeTimeFormatPumpEvent.class), // + ChangeReservoirWarningTime((byte) 0x65, ChangeReservoirWarningTimePumpEvent.class), // + ChangeBolusReminderEnable((byte) 0x66, ChangeBolusReminderEnablePumpEvent.class), // + ChangeBolusReminderTime((byte) 0x67, ChangeBolusReminderTimePumpEvent.class), // + DeleteBolusReminderTime((byte) 0x68, DeleteBolusReminderTimePumpEvent.class), // + // case bolusReminder = 0x69, 7), // + DeleteAlarmClockTime((byte) 0x6a, DeleteAlarmClockTimePumpEvent.class), // + DailyTotal515(0x6c, 38), // FIXME + dailyTotal522((byte) 0x6D, Model522ResultTotalsPumpEvent.class), // + dailyTotal523((byte) 0x6E, IgnoredHistoryEntry.class, 52), // Sara6E // FIXME + ChangeCarbUnits((byte) 0x6f, ChangeCarbUnitsPumpEvent.class), // + basalProfileStart((byte) 0x7B, BasalProfileStart.class), // + ChangeWatchdogEnable((byte) 0x7c, ChangeWatchdogEnablePumpEvent.class), // + ChangeOtherDeviceID((byte) 0x7d, ChangeOtherDeviceIDPumpEvent.class), // + ChangeWatchdogMarriageProfile((byte) 0x81, ChangeWatchdogMarriageProfilePumpEvent.class), // + DeleteOtherDeviceID((byte) 0x82, DeleteOtherDeviceIDPumpEvent.class), // + ChangeCaptureEventEnable((byte) 0x83, ChangeCaptureEventEnablePumpEvent.class), + + // Irelevant records (events that don't concern us for AAPS usage) + + + ; + + private static Map mapByOpCode = null; private byte opcode; private Class mRecordClass; + private int length; + private String shortTypeName; + public byte opcode() { return opcode; } + public Class recordClass() { return mRecordClass; } - RecordTypeEnum(byte b, Class c) { - opcode = b; + + RecordTypeEnum(int b, Class c) { + opcode = (byte) b; mRecordClass = c; } + + RecordTypeEnum(int b, Class c, int length) { + opcode = (byte) b; + mRecordClass = c; + this.length = length; + } + + + RecordTypeEnum(int b, int length) { + this(b, IgnoredHistoryEntry.class, length); + } + + public static RecordTypeEnum fromByte(byte b) { - for (RecordTypeEnum en : RecordTypeEnum.values()) { + for(RecordTypeEnum en : RecordTypeEnum.values()) { if (en.opcode() == b) { return en; } } - return RECORD_TYPE_NULL; + return Null; } + private static final String TAG = "RecordTypeEnum"; - public T getRecordClassInstance(PumpModel model) { + + public T getRecordClassInstance(MedtronicDeviceType model) { Constructor ctor; T record = null; try { @@ -160,6 +239,12 @@ public enum RecordTypeEnum { if (ctor != null) { record = ctor.newInstance(); record.setPumpModel(model); + + // if this is IgnoredHistoryEntry we need to set type so that we get correct length and name + if (record instanceof IgnoredHistoryEntry) { + IgnoredHistoryEntry he = (IgnoredHistoryEntry) record; + he.init(this); + } } } } catch (NoSuchMethodException e) { @@ -175,10 +260,30 @@ public enum RecordTypeEnum { return record; } - public static T getRecordClassInstance(Bundle bundle, PumpModel model) { + + public static T getRecordClassInstance(Bundle bundle, MedtronicDeviceType model) { byte opcode = bundle.getByte("_opcode"); RecordTypeEnum e = RecordTypeEnum.fromByte(opcode); return e.getRecordClassInstance(model); } + + public int getLength() { + return length; + } + + + public void setLength(int length) { + this.length = length; + } + + + public String getShortTypeName() { + return shortTypeName; + } + + + public void setShortTypeName(String shortTypeName) { + this.shortTypeName = shortTypeName; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/TimeStampedRecord.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/TimeStampedRecord.java index 9e5b832f46..ace918d9a5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/TimeStampedRecord.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/TimeStampedRecord.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history; import android.os.Bundle; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; /* * Many events in the history only consist of a single opcode and a datestamp. @@ -14,31 +14,38 @@ abstract public class TimeStampedRecord extends Record { //private final static String TAG = "TimeStampedRecord"; private final static boolean DEBUG_TIMESTAMPEDRECORD = false; + @Override public int getLength() { return 7; } + public int getDatestampOffset() { return 2; } + protected PumpTimeStamp timestamp; + public TimeStampedRecord() { timestamp = new PumpTimeStamp(); } + @Override public PumpTimeStamp getTimestamp() { return timestamp; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { return simpleParse(data, getDatestampOffset()); } + // This is useful if there is no data inside, or we don't care about the data. public boolean simpleParse(byte[] data, int fiveByteDateOffset) { if (getLength() > data.length) { @@ -51,6 +58,7 @@ abstract public class TimeStampedRecord extends Record { return true; } + protected boolean collectTimeStamp(byte[] data, int offset) { try { timestamp = new PumpTimeStamp(TimeFormat.parse5ByteDate(data, offset)); @@ -60,6 +68,7 @@ abstract public class TimeStampedRecord extends Record { return true; } + @Override public boolean readFromBundle(Bundle in) { String timestampString = in.getString("timestamp"); @@ -67,6 +76,7 @@ abstract public class TimeStampedRecord extends Record { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BGReceivedPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BGReceivedPumpEvent.java index e9f3991798..e9f46ab6ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BGReceivedPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BGReceivedPumpEvent.java @@ -4,28 +4,32 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class BGReceivedPumpEvent extends TimeStampedRecord { private int amount = 0; private byte[] meter = new byte[3]; + public BGReceivedPumpEvent() { } + @Override public int getLength() { return 10; } + @Override public String getShortTypeName() { return "BG Received"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!super.simpleParse(data, 2)) { return false; } @@ -34,6 +38,7 @@ public class BGReceivedPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { amount = in.getInt("amount"); @@ -41,6 +46,7 @@ public class BGReceivedPumpEvent extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); @@ -48,6 +54,7 @@ public class BGReceivedPumpEvent extends TimeStampedRecord { in.putByteArray("meter", meter); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BasalProfileStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BasalProfileStart.java index fc8d28abb0..2427237a59 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BasalProfileStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BasalProfileStart.java @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class BasalProfileStart extends TimeStampedRecord { private static final String TAG = "BasalProfileStart"; @@ -11,21 +11,25 @@ public class BasalProfileStart extends TimeStampedRecord { private double rate = 0.0; private int profileIndex = 0; + public BasalProfileStart() { } + @Override public int getLength() { return 10; } + @Override public String getShortTypeName() { return "Basal Profile Start"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } @@ -36,6 +40,7 @@ public class BasalProfileStart extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { offset = in.getInt("offset"); @@ -44,6 +49,7 @@ public class BasalProfileStart extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); @@ -52,6 +58,7 @@ public class BasalProfileStart extends TimeStampedRecord { in.putInt("profileIndex", profileIndex); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusNormalPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusNormalPumpEvent.java index f4d437b9d1..c4ab31b916 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusNormalPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusNormalPumpEvent.java @@ -3,10 +3,10 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.PumpTimeStamp; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeFormat; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class BolusNormalPumpEvent extends TimeStampedRecord { private final static String TAG = "BolusNormalPumpEvent"; @@ -17,29 +17,34 @@ public class BolusNormalPumpEvent extends TimeStampedRecord { private double unabsorbedInsulinTotal = 0.0; private String bolusType = "Unset"; + public BolusNormalPumpEvent() { } + @Override public int getLength() { - return PumpModel.isLargerFormat(model) ? 13 : 9; + return isLargerFormat() ? 13 : 9; } + @Override public String getShortTypeName() { return "Normal Bolus"; } + private double insulinDecode(int a, int b) { return ((a << 8) + b) / 40.0; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (getLength() > data.length) { return false; } - if (PumpModel.isLargerFormat(model)) { + if (MedtronicDeviceType.isLargerFormat(model)) { programmedAmount = insulinDecode(asUINT8(data[1]), asUINT8(data[2])); deliveredAmount = insulinDecode(asUINT8(data[3]), asUINT8(data[4])); unabsorbedInsulinTotal = insulinDecode(asUINT8(data[5]), asUINT8(data[6])); @@ -66,6 +71,7 @@ public class BolusNormalPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { programmedAmount = in.getDouble("programmedAmount", 0.0); @@ -76,6 +82,7 @@ public class BolusNormalPumpEvent extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); @@ -86,6 +93,7 @@ public class BolusNormalPumpEvent extends TimeStampedRecord { in.putString("bolusType", bolusType); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusWizardBolusEstimatePumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusWizardBolusEstimatePumpEvent.java index 00bf735dcd..2667fe1428 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusWizardBolusEstimatePumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/BolusWizardBolusEstimatePumpEvent.java @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { @@ -18,6 +18,7 @@ public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { private int insulinSensitivity; private double carbRatio; + public BolusWizardBolusEstimatePumpEvent() { correctionEstimate = (double) 0.0; bloodGlucose = 0; @@ -31,16 +32,19 @@ public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { unabsorbedInsulinTotal = 0.0; } + @Override public int getLength() { - return PumpModel.isLargerFormat(model) ? 22 : 20; + return isLargerFormat() ? 22 : 20; } + @Override public String getShortTypeName() { return "Bolus Wizard Est."; } + @Override public boolean readFromBundle(Bundle in) { carbohydrates = in.getInt("carbohydrates", 0); @@ -56,6 +60,7 @@ public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); @@ -71,56 +76,68 @@ public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { in.putDouble("carbRatio", carbRatio); } + public double getCorrectionEstimate() { return correctionEstimate; } + public long getBG() { return bloodGlucose; } + public int getCarbohydrates() { return carbohydrates; } + public double getICRatio() { return carbRatio; } + public int getInsulinSensitivity() { return insulinSensitivity; } + public int getBgTargetLow() { return bgTargetLow; } + public int getBgTargetHigh() { return bgTargetHigh; } + public double getBolusEstimate() { return bolusEstimate; } + public double getFoodEstimate() { return foodEstimate; } + public double getUnabsorbedInsulinTotal() { return unabsorbedInsulinTotal; } + private double insulinDecode(int a, int b) { return ((a << 8) + b) / 40.0; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } - if (PumpModel.isLargerFormat(model)) { + if (MedtronicDeviceType.isLargerFormat(model)) { carbohydrates = (asUINT8(data[8]) & 0x0c << 6) + asUINT8(data[7]); bloodGlucose = (asUINT8(data[8]) & 0x03 << 8) + asUINT8(data[1]); foodEstimate = insulinDecode(asUINT8(data[14]), asUINT8(data[15])); @@ -147,6 +164,7 @@ public class BolusWizardBolusEstimatePumpEvent extends TimeStampedRecord { return true; } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/CalBgForPhPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/CalBgForPhPumpEvent.java index fd3dbcb6c4..a72d06c9e4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/CalBgForPhPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/CalBgForPhPumpEvent.java @@ -2,22 +2,25 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class CalBgForPhPumpEvent extends TimeStampedRecord { private int amount = 0; + public CalBgForPhPumpEvent() { } + @Override public String getShortTypeName() { return "Cal Bg For Ph"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } @@ -25,18 +28,21 @@ public class CalBgForPhPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { amount = in.getInt("amount", 0); return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); in.putInt("amount", amount); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ChangeTempBasalTypePumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ChangeTempBasalTypePumpEvent.java index 05401855db..c418a8ad5f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ChangeTempBasalTypePumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ChangeTempBasalTypePumpEvent.java @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; /** * Created by geoff on 6/5/16. @@ -11,16 +11,19 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeSt public class ChangeTempBasalTypePumpEvent extends TimeStampedRecord { private boolean isPercent = false; // either absolute or percent + public ChangeTempBasalTypePumpEvent() { } + @Override public String getShortTypeName() { return "Ch Temp Basal Type"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } @@ -32,18 +35,21 @@ public class ChangeTempBasalTypePumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { isPercent = in.getBoolean("isPercent", false); return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { in.putBoolean("isPercent", isPercent); super.writeToBundle(in); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/IgnoredHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/IgnoredHistoryEntry.java new file mode 100644 index 0000000000..182b6d1529 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/IgnoredHistoryEntry.java @@ -0,0 +1,54 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record; + +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.Record; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.RecordTypeEnum; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; + +/** + * Created by andy on 6/1/18. + */ + +public class IgnoredHistoryEntry extends Record { + + //public int lngth = 7; + private RecordTypeEnum typeEnum = RecordTypeEnum.Null; + + + public IgnoredHistoryEntry() { + } + + + public void init(RecordTypeEnum typeEnum) { + this.typeEnum = typeEnum; + } + + + @Override + public int getLength() { + return this.typeEnum.getLength(); + } + + + @Override + public String getRecordTypeName() { + return typeEnum.name(); + } + + + @Override + public String getShortTypeName() { + return typeEnum.name(); + } + + + @Override + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { + return true; + } + + + @Override + public boolean isAAPSRelevant() { + return false; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/NewTimeSet.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/NewTimeSet.java index eb29926961..9fd85b67a3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/NewTimeSet.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/NewTimeSet.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; // This event existed as 0x18 in Roundtrip and early Decocare, // but I don't see a corresponding event in RileyLink_ios. @@ -9,11 +9,13 @@ public class NewTimeSet extends TimeStampedRecord { public NewTimeSet() { } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { return false; } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PrimePumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PrimePumpEvent.java index 908bbe718b..79b4d1b538 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PrimePumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PrimePumpEvent.java @@ -3,29 +3,33 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class PrimePumpEvent extends TimeStampedRecord { private double amount = 0.0; private double programmedAmount = 0.0; private String primeType = "unknown"; + public PrimePumpEvent() { } + @Override public int getLength() { return 10; } + @Override public String getShortTypeName() { return "Prime Pump"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 5)) { return false; } @@ -35,6 +39,7 @@ public class PrimePumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { amount = in.getDouble("amount", 0.0); @@ -43,6 +48,7 @@ public class PrimePumpEvent extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { in.putDouble("amount", amount); @@ -51,6 +57,7 @@ public class PrimePumpEvent extends TimeStampedRecord { super.writeToBundle(in); } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PumpAlarmPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PumpAlarmPumpEvent.java index 172a354f4f..ff9ca9949c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PumpAlarmPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/PumpAlarmPumpEvent.java @@ -3,27 +3,31 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class PumpAlarmPumpEvent extends TimeStampedRecord { private int rawtype = 0; + public PumpAlarmPumpEvent() { } + @Override public int getLength() { return 9; } + @Override public String getShortTypeName() { return "Pump Alarm"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 4)) { return false; } @@ -31,18 +35,21 @@ public class PumpAlarmPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { rawtype = in.getInt("rawtype", 0); return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { in.putInt("rawtype", rawtype); super.writeToBundle(in); } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ResultDailyTotalPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ResultDailyTotalPumpEvent.java index 6a62f0ea9a..97f113a9ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ResultDailyTotalPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/ResultDailyTotalPumpEvent.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.PumpTimeStamp; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeFormat; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; @@ -8,19 +7,23 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeSt public class ResultDailyTotalPumpEvent extends TimeStampedRecord { private static final String TAG = "ResultDailyTotalPumpEvent"; + public ResultDailyTotalPumpEvent() { } + @Override public int getDatestampOffset() { return 5; } + @Override public int getLength() { - return PumpModel.isLargerFormat(model) ? 10 : 7; + return isLargerFormat() ? 10 : 7; } + @Override protected boolean collectTimeStamp(byte[] data, int offset) { try { @@ -32,11 +35,13 @@ public class ResultDailyTotalPumpEvent extends TimeStampedRecord { return true; } + @Override public String getShortTypeName() { return "Result Daily Total"; } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/Sara6EPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/Sara6EPumpEvent.java index 502ec56b7d..10a69750d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/Sara6EPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/Sara6EPumpEvent.java @@ -1,26 +1,29 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.record; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.PumpTimeStamp; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeFormat; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class Sara6EPumpEvent extends TimeStampedRecord { public Sara6EPumpEvent() { } + @Override public int getLength() { return 52; } + @Override public String getShortTypeName() { return "Sara6E"; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { // We don't understand this event... // Minimum 16 characters? date components? if (16 > data.length) { @@ -34,6 +37,7 @@ public class Sara6EPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean isAAPSRelevant() { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalDurationPumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalDurationPumpEvent.java index dcdb60d4a5..633a60f35e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalDurationPumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalDurationPumpEvent.java @@ -2,26 +2,30 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class TempBasalDurationPumpEvent extends TimeStampedRecord { private int durationMinutes = 0; + public TempBasalDurationPumpEvent() { } + @Override public String getShortTypeName() { return "Temp Basal Duration"; } + public int getDurationMinutes() { return durationMinutes; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } @@ -29,18 +33,21 @@ public class TempBasalDurationPumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { durationMinutes = in.getInt("durationMinutes", 0); return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { super.writeToBundle(in); in.putInt("durationMinutes", durationMinutes); } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalRatePumpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalRatePumpEvent.java index 6297afdcc2..13440a798f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalRatePumpEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/TempBasalRatePumpEvent.java @@ -3,36 +3,42 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.recor import android.os.Bundle; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.TimeStampedRecord; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class TempBasalRatePumpEvent extends TimeStampedRecord { private double basalRate = 0.0; // rate in Units/hr private boolean mIsPercent = false; // The value is either an absolute number or a percentage + public TempBasalRatePumpEvent() { } + @Override public int getLength() { return 8; } + @Override public String getShortTypeName() { return "Temp Basal Rate"; } + public double getBasalRate() { return basalRate; } + public boolean isPercent() { return mIsPercent; } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (!simpleParse(data, 2)) { return false; } @@ -46,6 +52,7 @@ public class TempBasalRatePumpEvent extends TimeStampedRecord { return true; } + @Override public boolean readFromBundle(Bundle in) { basalRate = in.getDouble("basalRate", 0); @@ -53,6 +60,7 @@ public class TempBasalRatePumpEvent extends TimeStampedRecord { return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { in.putDouble("basalRate", basalRate); @@ -60,6 +68,7 @@ public class TempBasalRatePumpEvent extends TimeStampedRecord { super.writeToBundle(in); } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/UnabsorbedInsulin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/UnabsorbedInsulin.java index b9cd4d1e73..140a938e27 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/UnabsorbedInsulin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history/record/UnabsorbedInsulin.java @@ -7,27 +7,31 @@ import android.util.Log; import java.util.ArrayList; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; -import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.PumpModel; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.Record; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; public class UnabsorbedInsulin extends Record { private static final String TAG = "UnabsorbedInsulin"; private int length = 2; + @Override public int getLength() { return length; /* this is a variable sized record */ } + @Override public String getShortTypeName() { return "Unabsorbed Insulin"; } + class UnabsorbedInsulinRecord { public double amount = 0.0; public int age = 0; + public UnabsorbedInsulinRecord(double amount, int age) { this.amount = amount; this.age = age; @@ -36,11 +40,13 @@ public class UnabsorbedInsulin extends Record { ArrayList records = new ArrayList<>(); + public UnabsorbedInsulin() { } + @Override - public boolean parseFrom(byte[] data, PumpModel model) { + public boolean parseFrom(byte[] data, MedtronicDeviceType model) { if (data.length < 2) { return false; } @@ -53,7 +59,7 @@ public class UnabsorbedInsulin extends Record { } int numRecords = (asUINT8(data[1]) - 2) / 3; - for (int i = 0; i < numRecords; i++) { + for(int i = 0; i < numRecords; i++) { double amount = (double) (asUINT8(data[2 + (i * 3)])) / 40.0; int age = asUINT8(data[3 + (i * 3)]) + (((asUINT8(data[4 + (i * 3)])) & 0b110000) << 4); records.add(new UnabsorbedInsulinRecord(amount, age)); @@ -62,6 +68,7 @@ public class UnabsorbedInsulin extends Record { return true; } + @Override public boolean readFromBundle(Bundle in) { float[] storedAmounts = in.getFloatArray("amounts"); @@ -71,20 +78,21 @@ public class UnabsorbedInsulin extends Record { } else if (storedAges.length != storedAmounts.length) { Log.e(TAG, "readFromBundle: failed to load from bundle: array size mismatch"); } else { - for (int i = 0; i < storedAges.length; i++) { + for(int i = 0; i < storedAges.length; i++) { records.add(new UnabsorbedInsulinRecord(storedAmounts[i], storedAges[i])); } } return super.readFromBundle(in); } + @Override public void writeToBundle(Bundle in) { // Use parallel arrays to serialize the data. Note there is a small loss // of precision when going from double to float. float[] storedAmounts = new float[records.size()]; int[] storedAges = new int[records.size()]; - for (int i = 0; i < records.size(); i++) { + for(int i = 0; i < records.size(); i++) { storedAmounts[i] = (float) records.get(i).amount; storedAges[i] = records.get(i).age; } @@ -95,6 +103,7 @@ public class UnabsorbedInsulin extends Record { } + @Override public boolean isAAPSRelevant() { return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryDecoder.java new file mode 100644 index 0000000000..09f102fbea --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryDecoder.java @@ -0,0 +1,190 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.RawHistoryPage; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: DeviceIdentification + * Description: Class for display of Device Identification. + *

+ * Author: Andy {andy@atech-software.com} + */ +public abstract class MedtronicHistoryDecoder { + + private static final Logger LOG = LoggerFactory.getLogger(MedtronicHistoryDecoder.class); + + protected ByteUtil bitUtils; + + // STATISTICS (remove at later time or not) + protected boolean statisticsEnabled = true; + protected Map unknownOpCodes; + protected Map> mapStatistics; + + + public MedtronicHistoryDecoder() { + } + + + public abstract RecordDecodeStatus decodeRecord(MedtronicHistoryEntry record); + + + public abstract void postProcess(); + + + //public abstract void refreshOutputWriter(); + + + public boolean decodePage(RawHistoryPage dataPage) throws Exception { + //refreshOutputWriter(); + + List minimedHistoryRecords = processPageAndCreateRecords(dataPage); + + for(MedtronicHistoryEntry record : minimedHistoryRecords) { + decodeRecord(record); + } + + runPostDecodeTasks(); + + return true; + } + + + protected abstract void runPostDecodeTasks(); + + + // TODO_ extend this to also use bigger pages (for now we support only 1024 + // pages) + public List checkPage(RawHistoryPage page) throws RuntimeException { + List byteList = new ArrayList(); + + if (page.getData().length != 1024 /*page.commandType.getRecordLength()*/) { + LOG.error("Page size is not correct. Size should be {}, but it was {} instead.", 1024, page.getData().length); + // throw exception perhaps + return byteList; + } + + if (MedtronicUtil.getDeviceType() == null) { + LOG.error("Device Type is not defined."); + return byteList; + } + + if (page.isChecksumOK()) { + return ByteUtil.getListFromByteArray(page.getOnlyData()); + } else { + return null; + } + } + + + public abstract List processPageAndCreateRecords(RawHistoryPage page) throws Exception; + + + protected void prepareStatistics() { + if (!statisticsEnabled) return; + + unknownOpCodes = new HashMap(); + mapStatistics = new HashMap>(); + + for(RecordDecodeStatus stat : RecordDecodeStatus.values()) { + mapStatistics.put(stat, new HashMap()); + } + } + + + protected void addToStatistics(MedtronicHistoryEntry pumpHistoryEntry, RecordDecodeStatus status, Integer opCode) { + if (!statisticsEnabled) return; + + if (opCode != null) { + if (!unknownOpCodes.containsKey(opCode)) { + unknownOpCodes.put(opCode, opCode); + } + return; + } + + if (!mapStatistics.get(status).containsKey(pumpHistoryEntry.getEntryType().name())) { + mapStatistics.get(status).put(pumpHistoryEntry.getEntryType().name(), ""); + } + } + + + protected void showStatistics() { + StringBuilder sb = new StringBuilder(); + + for(Map.Entry unknownEntry : unknownOpCodes.entrySet()) { + StringUtil.appendToStringBuilder(sb, "" + unknownEntry.getKey(), ", "); + } + + LOG.debug("STATISTICS OF PUMP DECODE"); + + if (unknownOpCodes.size() > 0) { + LOG.debug("Unknown Op Codes: {}", sb.toString()); + } + + for(Map.Entry> entry : mapStatistics.entrySet()) { + sb = new StringBuilder(); + + if (entry.getKey() != RecordDecodeStatus.OK) { + if (entry.getValue().size() == 0) continue; + + for(Map.Entry entrysub : entry.getValue().entrySet()) { + StringUtil.appendToStringBuilder(sb, entrysub.getKey(), ", "); + } + + String spaces = StringUtils.repeat(" ", 14 - entry.getKey().name().length()); + + LOG.debug(" {}{} - {}. Elements: {}", entry.getKey().name(), spaces, entry.getValue().size(), sb.toString()); + } else { + LOG.debug(" {} - {}", entry.getKey().name(), entry.getValue().size()); + } + } + } + + + private int getUnsignedByte(byte value) { + if (value < 0) return value + 256; + else return value; + } + + + protected int getUnsignedInt(int value) { + if (value < 0) return value + 256; + else return value; + } + + + public String getFormattedFloat(float value, int decimals) { + return StringUtil.getFormatedValueUS(value, decimals); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryEntry.java new file mode 100644 index 0000000000..f5605a6889 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicHistoryEntry.java @@ -0,0 +1,213 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + + +import org.joda.time.LocalDateTime; + +import java.util.List; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpTimeStampedRecord; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: MinimedHistoryRecord + * Description: Minimed History Record. + *

+ * Author: Andy {andy@atech-software.com} + */ + +public abstract class MedtronicHistoryEntry { + + protected List rawData; + + protected int[] sizes = new int[3]; + + protected byte[] head; + protected byte[] datetime; + protected byte[] body; + + protected LocalDateTime dateTime; + protected PumpTimeStampedRecord historyEntryDetails; + + + public void setData(List listRawData, boolean doNotProcess) { + this.rawData = listRawData; + + // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + + // ", body=" + sizes[2]); + + if (doNotProcess) + return; + + head = new byte[getHeadLength() - 1]; + for(int i = 1; i < (getHeadLength()); i++) { + head[i - 1] = listRawData.get(i); + } + + if (getDateTimeLength() > 0) { + datetime = new byte[getDateTimeLength()]; + + for(int i = getHeadLength(), j = 0; j < getDateTimeLength(); i++, j++) { + datetime[j] = listRawData.get(i); + } + } + + if (getBodyLength() > 0) { + body = new byte[getBodyLength()]; + + for(int i = (getHeadLength() + getDateTimeLength()), j = 0; j < getBodyLength(); i++, j++) { + body[j] = listRawData.get(i); + } + + } + + } + + + public int getHeadLength() { + return sizes[0]; + } + + + public int getDateTimeLength() { + return sizes[1]; + } + + + public int getBodyLength() { + return sizes[2]; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(getToStringStart()); + sb.append(", DT: " + ((this.dateTime == null) ? "x" : StringUtil.toDateTimeString(this.dateTime))); + sb.append(", length="); + sb.append(getHeadLength()); + sb.append(","); + sb.append(getDateTimeLength()); + sb.append(","); + sb.append(getBodyLength()); + sb.append("("); + sb.append((getHeadLength() + getDateTimeLength() + getBodyLength())); + sb.append(")"); + + if (head != null) { + sb.append(", head="); + sb.append(HexDump.toHexStringDisplayable(this.head)); + } + + if (datetime != null) { + sb.append(", datetime="); + sb.append(HexDump.toHexStringDisplayable(this.datetime)); + } + + if (body != null) { + sb.append(", body="); + sb.append(HexDump.toHexStringDisplayable(this.body)); + } + + sb.append(", rawData="); + sb.append(HexDump.toHexStringDisplayable(this.rawData)); + sb.append("]"); + + sb.append(" DT: "); + sb.append(this.dateTime == null ? " - " : this.dateTime.toString("dd.MM.yyyy HH:mm:ss")); + + sb.append(" Ext: "); + + return sb.toString(); + } + + + public abstract int getOpCode(); + + + public abstract String getToStringStart(); + + + public List getRawData() { + return rawData; + } + + + public void setRawData(List rawData) { + this.rawData = rawData; + } + + + public byte[] getHead() { + return head; + } + + + public void setHead(byte[] head) { + this.head = head; + } + + + public byte[] getDatetime() { + return datetime; + } + + + public void setDatetime(byte[] datetime) { + this.datetime = datetime; + } + + + public byte[] getBody() { + return body; + } + + + public void setBody(byte[] body) { + this.body = body; + } + + + public void setLocalDateTime(LocalDateTime atdate) { + this.dateTime = atdate; + } + + + public LocalDateTime getLocalDateTime() { + return this.dateTime; + } + + + public String toShortString() { + if (head == null) { + return "Unidentified record. "; + } else { + return "HistoryRecord: head=[" + HexDump.toHexStringDisplayable(this.head) + "]"; + } + } + + + // if we extend to CGMS this need to be changed back + public abstract PumpHistoryEntryType getEntryType(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicPumpHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicPumpHistoryDecoder.java new file mode 100644 index 0000000000..9ae9dbe2af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/MedtronicPumpHistoryDecoder.java @@ -0,0 +1,775 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + + +import android.util.Log; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfileEntry; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.RawHistoryPage; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusDTO; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusWizardDTO; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpBolusType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: MedtronicPumpHistoryDecoder + * Description: Decoder for history data. + *

+ * Author: Andy {andy@atech-software.com} + */ + +public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder { + + private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpHistoryDecoder.class); + private static final String TAG = "MdtPumpHistoryDecoder"; + + //PumpValuesWriter pumpValuesWriter = null; + + // DataAccessPlugInBase dataAccess = DataAccessPump.getInstance(); + + // Temporary records for processing + private PumpHistoryEntry tbrPreviousRecord; + private PumpHistoryEntry changeTimeRecord; + + + public MedtronicPumpHistoryDecoder() { + + } + + + public List processPageAndCreateRecords(RawHistoryPage page) { + List dataClear = checkPage(page); + return createRecords(dataClear); + } + + + public List createRecords(List dataClear) { + prepareStatistics(); + + int counter = 0; + int record = 0; + boolean incompletePacket = false; + + List outList = new ArrayList(); + String skipped = null; + int elementStart = 0; + + do { + int opCode = dataClear.get(counter); + boolean special = false; + incompletePacket = false; + + + if (opCode == 0) { + counter++; + if (skipped == null) + skipped = "0x00"; + else + skipped += " 0x00"; + continue; + } else { + if (skipped != null) { + Log.v(TAG, " ... Skipped " + skipped); + skipped = null; + } + } + + PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(opCode); + + PumpHistoryEntry pe = new PumpHistoryEntry(); + pe.setEntryType(entryType); + pe.setOffset(counter); + + counter++; + + if (counter >= 1022) { + break; + } + + List listRawData = new ArrayList(); + listRawData.add((byte) opCode); + + if (entryType == PumpHistoryEntryType.UnabsorbedInsulin) { + int elements = dataClear.get(counter); + listRawData.add((byte) elements); + counter++; + + int els = getUnsignedInt(elements); + + for(int k = 0; k < (els - 2); k++) { + listRawData.add((byte) dataClear.get(counter)); + counter++; + } + + special = true; + } else { + + for(int j = 0; j < (entryType.getTotalLength() - 1); j++) { + + try { + listRawData.add(dataClear.get(counter)); + counter++; + } catch (Exception ex) { + Log.e(TAG, "OpCode: " + HexDump.getCorrectHexValue((byte) opCode) + ", Invalid package: " + HexDump.toHexStringDisplayable(listRawData)); + //throw ex; + incompletePacket = true; + break; + } + + + } + + + if (incompletePacket) + break; + + } + + if (entryType == PumpHistoryEntryType.None) { + LOG.error("Error in code. We should have not come into this branch."); + // System.out.println("!!! Unknown Entry: 0x" + + // bitUtils.getCorrectHexValue(opCode) + "[" + opCode + "]"); + // + // addToStatistics(null, null, opCode); + // counter += 6; // we assume this is unknown packet with size + // // 2,5,0 (standard packet) + // + // pe.setEntryType(PumpHistoryEntryType.UnknownBasePacket); + // pe.setOpCode(opCode); + + } else { + + // System.out.println(pe.getEntryType()); + + if (pe.getEntryType() == PumpHistoryEntryType.UnknownBasePacket) { + pe.setOpCode(opCode); + } + + if (entryType.getHeadLength() == 0) + special = true; + + pe.setData(listRawData, special); + + RecordDecodeStatus decoded = decodeRecord(pe); + + // if (pe.getEntryType() == + // PumpHistoryEntryType.UnknownBasePacket) + // { + // decoded = RecordDecodeStatus.Unknown; + // } + // else + // { + // decoded = decodeRecord(pe); + // } + + // System.out.println("Found entry: " + entryType.name() + + // " [" + // + bitUtils.getDebugByteListHex(listRawData) + "] "); + + // FIXME + + // if (!decoded) + // System.out.println("#" + record + " " + pe); + + // if (decoded) + // LOG.info("#" + record + " " + pe); + // else + // LOG.warn("#" + record + " BAD: " + pe); + + if ((decoded == RecordDecodeStatus.OK) || (decoded == RecordDecodeStatus.Ignored)) { + LOG.info("#" + record + " " + decoded.getDescription() + " " + pe); + Log.i(TAG, "#" + record + " " + decoded.getDescription() + " -- " + pe); + } else { + LOG.warn("#" + record + " " + decoded.getDescription() + " " + pe); + Log.w(TAG, "#" + record + " " + decoded.getDescription() + " -- " + pe); + } + + addToStatistics(pe, decoded, null); + + record++; + + if (decoded == RecordDecodeStatus.OK) // we add only OK records, all others are ignored + { + outList.add(pe); + } + } + + // System.out.println("Counter: " + counter); + + // if (counter > 100) + // break; + + } while (counter < dataClear.size()); + + return outList; + } + + + public RecordDecodeStatus decodeRecord(MedtronicHistoryEntry entryIn) { + PumpHistoryEntry precord = (PumpHistoryEntry) entryIn; + try { + return decodeRecord(entryIn, false); + } catch (Exception ex) { + LOG.error(" Error decoding: type={}, ex={}", precord.getEntryType().name(), ex.getMessage(), ex); + return RecordDecodeStatus.Error; + } + } + + + public RecordDecodeStatus decodeRecord(MedtronicHistoryEntry entryIn, boolean x) { + // FIXME + // TODO + PumpHistoryEntry entry = (PumpHistoryEntry) entryIn; + + if (entry.getDateTimeLength() > 0) { + decodeDateTime(entry); + } + + // LOG.debug("decodeRecord: type={}", entry.getEntryType()); + decodeDateTime(entry); + + switch (entry.getEntryType()) { + // not implemented + case ChangeBasalProfile_NewProfile: + case ChangeBasalProfile_OldProfile: + case SelectBasalProfile: + case DailyTotals522: + + //case IanA8: + case DailyTotals523: + case DailyTotals512: + return RecordDecodeStatus.NotSupported; + + + // WORK IN PROGRESS + + // POSSIBLY READY + + case BasalProfileStart: + return decodeBasalProfileStart(entry); + + + // AAPS Implementation - Not yet done + + + // AAPS Implementation - OK entries + + // AAPS events (Tbr, Bolus) + + // AAPS alerts + + + // AAPS TDDs + + + // AAPS Implementation - Ignored entries + case CalBGForPH: + case ChangeRemoteId: + case ClearAlarm: + case ChangeAlarmNotifyMode: // ChangeUtility: + case ToggleRemote: + case UnabsorbedInsulin: + case BGReceived: // Ian3F: CGMS + case SensorAlert: // Ian08 CGMS + case ChangeTempBasalType: + case ChangeTimeFormat: + case ChangeReservoirWarningTime: + case ChangeBolusReminderEnable: + case ChangeBolusReminderTime: + case ChangeChildBlockEnable: + case ChangeMaxBolus: + case ChangeMaxBasal: + case BolusWizardEnabled: + case ChangeBGReminderOffset: + case ChangeAlarmClockTime: + case ChangeMeterId: + case ChangeParadigmLinkID: + case JournalEntryMealMarker: + case JournalEntryExerciseMarker: + case DeleteBolusReminderTime: + case SetAutoOff: + case SelfTest: + case ClearSettings: + case JournalEntryInsulinMarker: + case JournalEntryOtherMarker: + case ChangeBolusWizardSetup: + case ChangeSensorSetup2: + case RestoreMystery51: + case RestoreMystery52: + case ChangeSensorAlarmSilenceConfig: + case RestoreMystery54: + case RestoreMystery55: + case ChangeSensorRateOfChangeAlertSetup: + case ChangeBolusScrollStepSize: + case BolusWizardChange: + case SaveSettings: + case ChangeVariableBolus: + case ChangeAudioBolus: + case ChangeBGReminderEnable: + case ChangeAlarmClockEnable: + case BolusReminder: + case DeleteAlarmClockTime: + case ChangeCarbUnits: + case ChangeWatchdogEnable: + case ChangeOtherDeviceID: + case ChangeWatchdogMarriageProfile: + case DeleteOtherDeviceID: + case ChangeCaptureEventEnable: + case EventUnknown_MM522_0x45: + case EventUnknown_MM522_0x46: + case EventUnknown_MM522_0x47: + case EventUnknown_MM522_0x48: + case EventUnknown_MM522_0x49: + case EventUnknown_MM522_0x4a: + case EventUnknown_MM522_0x4b: + case EventUnknown_MM522_0x4c: + case EventUnknown_MM512_0x10: + case EventUnknown_MM512_0x2e: + case EventUnknown_MM512_0x2f: + case EventUnknown_MM512_0x37: + case EventUnknown_MM512_0x38: + case EventUnknown_MM512_0x39: + case EventUnknown_MM512_0x3b: + case EventUnknown_MM512_0x4e: + case EventUnknown_MM522_0x70: + case EventUnknown_MM512_0x88: + case EventUnknown_MM512_0x94: + case EventUnknown_MM522_0xE8: + case EventUnknown_0x4d: + // LOG.debug(" -- ignored Pump Entry: " + entry.getEntryType().name()); + return RecordDecodeStatus.Ignored; + + + // **** Implemented records **** + + case ChangeTime: + changeTimeRecord = entry; + return RecordDecodeStatus.OK; + + case NewTimeSet: + decodeChangeTime(entry); + return RecordDecodeStatus.OK; + + + case TempBasalDuration: + decodeTempBasal(entry); + return RecordDecodeStatus.OK; + + case TempBasalRate: + decodeTempBasal(entry); + return RecordDecodeStatus.OK; + + case Bolus: + decodeBolus(entry); + return RecordDecodeStatus.OK; + + case EndResultTotals: + decodeEndResultTotals(entry); + return RecordDecodeStatus.OK; + + case BatteryActivity: + decodeBatteryActivity(entry); + return RecordDecodeStatus.OK; + + case LowReservoir: + decodeLowReservoir(entry); + return RecordDecodeStatus.OK; + + case LowBattery: + //this.writeData(PumpBaseType.Event, PumpEventType.BatteryLow, entry.getATechDate()); + return RecordDecodeStatus.OK; + + case PumpSuspend: + //this.writeData(PumpBaseType.Event, PumpEventType.BasalStop, entry.getATechDate()); + return RecordDecodeStatus.OK; + + case PumpResume: + //this.writeData(PumpBaseType.Event, PumpEventType.BasalRun, entry.getATechDate()); + return RecordDecodeStatus.OK; + + case Rewind: + //this.writeData(PumpBaseType.Event, PumpEventType.CartridgeRewind, entry.getATechDate()); + return RecordDecodeStatus.OK; + + + case EventUnknown_MM522_0x05: + break; + case NoDeliveryAlarm: + //this.writeData(PumpBaseType.Alarm, PumpAlarms.NoDelivery, entry.getATechDate()); + return RecordDecodeStatus.OK; + + case BolusWizardBolusEstimate: + decodeBolusWizard(entry); + return RecordDecodeStatus.OK; + + case Prime: + decodePrime(entry); + return RecordDecodeStatus.OK; + + case None: + case UnknownBasePacket: + return RecordDecodeStatus.Error; + + //case Andy0d: + + //case Andy58: + + //case Andy90: + + default: { + LOG.debug("Not supported: " + entry.getEntryType()); + return RecordDecodeStatus.NotSupported; + } + + } + + + return RecordDecodeStatus.Error; + + + } + + + // FIXME + private void decodeChangeTime(PumpHistoryEntry entry) { + if (changeTimeRecord == null) + return; + + //String timeChange = String.format(PumpEventType.DateTimeChanged.getValueTemplate(), this.changeTimeRecord.getATechDate().getDateTimeString(), entry.getATechDate().getDateTimeString()); + + //writeData(PumpBaseType.Event, PumpEventType.DateTimeChanged, timeChange, entry.getATechDate()); + + this.changeTimeRecord = null; + } + + + // private void decodeCalBGForPH(PumpHistoryEntry entry) { + // int high = (entry.getDatetime()[4] & 0x80) >> 7; + // int bg = bitUtils.toInt(high, getUnsignedInt(entry.getHead()[0])); + // + // writeData(PumpBaseType.AdditionalData, PumpAdditionalDataType.BloodGlucose, "" + bg, entry.getATechDate()); + // } + + + // masks = [ ( 0x80, 7), (0x40, 6), (0x20, 5), (0x10, 4) ] + // nibbles = [ ] + // for mask, shift in masks: + // nibbles.append( ( (year & mask) >> shift ) ) + // return nibbles + + + // FIXME + private void decodeBatteryActivity(PumpHistoryEntry entry) { + //this.writeData(PumpBaseType.Event, entry.getHead()[0] == 0 ? PumpEventType.BatteryRemoved : PumpEventType.BatteryReplaced, entry.getATechDate()); + } + + + // FIXME + private void decodeEndResultTotals(PumpHistoryEntry entry) { + float totals = bitUtils.toInt(entry.getHead()[2], entry.getHead()[3]) * 0.025f; + + //this.writeData(PumpBaseType.Report, PumpReport.InsulinTotalDay, getFormattedFloat(totals, 2), entry.getATechDate()); + } + + + // FIXME + private RecordDecodeStatus decodeBasalProfileStart(PumpHistoryEntry entry) { + byte[] body = entry.getBody(); + // int bodyOffset = headerSize + timestampSize; + int offset = body[0] * 1000 * 30 * 60; + Float rate = null; + int index = body[2]; + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) { + rate = body[1] * 0.025f; + } + + if (rate == null) { + LOG.warn("Basal Profile Start (ERROR): offset={}, rate={}, index={}, body_raw={}", offset, rate, index, body); + return RecordDecodeStatus.Error; + } else { + //writeData(PumpBaseType.Basal, PumpBasalType.ValueChange, getFormattedFloat(rate, 3), entry.getATechDate()); + return RecordDecodeStatus.OK; + } + + } + + + private void decodeBolusWizard(PumpHistoryEntry entry) { + byte[] body = entry.getBody(); + + BolusWizardDTO dto = new BolusWizardDTO(); + + float bolus_strokes = 10.0f; + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) { + // https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102 + bolus_strokes = 40.0f; + + dto.carbs = ((body[1] & 0x0c) << 6) + body[0]; + + dto.bloodGlucose = ((body[1] & 0x03) << 8) + entry.getHead()[0]; + dto.carbRatio = body[1] / 10.0f; + // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / + // 10.0s + dto.insulinSensitivity = new Float(body[4]); + dto.bgTargetLow = (int) body[5]; + dto.bgTargetHigh = (int) body[14]; + dto.correctionEstimate = (((body[9] & 0x38) << 5) + body[6]) / bolus_strokes; + dto.foodEstimate = ((body[7] << 8) + body[8]) / bolus_strokes; + dto.unabsorbedInsulin = ((body[10] << 8) + body[11]) / bolus_strokes; + dto.bolusTotal = ((body[12] << 8) + body[13]) / bolus_strokes; + } else { + dto.bloodGlucose = (((body[1] & 0x0F) << 8) | entry.getHead()[0]); + dto.carbs = (int) body[0]; + dto.carbRatio = new Float(body[2]); + dto.insulinSensitivity = new Float(body[3]); + dto.bgTargetLow = (int) body[4]; + dto.bgTargetHigh = (int) body[12]; + dto.bolusTotal = body[11] / 10.0f; + dto.foodEstimate = body[6] / 10.0f; + dto.unabsorbedInsulin = body[9] / 10.0f; + dto.bolusTotal = body[11] / 10.0f; + dto.correctionEstimate = (body[7] + (body[5] & 0x0F)) / 10.0f; + } + + entry.setHistoryEntryDetails(dto); + + //this.writeData(PumpBaseType.Event, PumpEventType.BolusWizard, dto.getValue(), entry.getATechDate()); + + } + + + // FIXME + private void decodeLowReservoir(PumpHistoryEntry entry) { + float amount = (getUnsignedInt(entry.getHead()[0]) * 1.0f / 10.0f); + //this.writeData(PumpBaseType.Event, PumpEventType.ReservoirLowDesc, getFormattedFloat(amount, 1), entry.getATechDate()); + } + + + // FIXME + private void decodePrime(PumpHistoryEntry entry) { + float amount = bitUtils.toInt(entry.getHead()[2], entry.getHead()[3]) / 10.0f; + float fixed = bitUtils.toInt(entry.getHead()[0], entry.getHead()[1]) / 10.0f; + + //this.writeData(PumpBaseType.Event, PumpEventType.PrimeInfusionSet, fixed > 0 ? getFormattedFloat(fixed, 1) : getFormattedFloat(amount, 1), entry.getATechDate()); + } + + + @Override + public void postProcess() { + if (bolusEntry != null) { + writeBolus(pumpHistoryEntry4BolusEntry, bolusEntry); + } + } + + + @Override + protected void runPostDecodeTasks() { + this.showStatistics(); + } + + + BolusDTO bolusEntry; + PumpHistoryEntry pumpHistoryEntry4BolusEntry; + + + private void decodeBolus(PumpHistoryEntry entry) { + BolusDTO bolus = new BolusDTO(); + + byte[] data = entry.getHead(); + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) { + bolus.setRequestedAmount(bitUtils.toInt(data[0], data[1]) / 40.0f); + bolus.setDeliveredAmount(bitUtils.toInt(data[2], data[3]) / 10.0f); + bolus.setInsulinOnBoard(bitUtils.toInt(data[4], data[5]) / 40.0f); + bolus.setDuration(data[6] * 30); + } else { + bolus.setRequestedAmount(data[0] / 40.0f); + bolus.setDeliveredAmount(data[1] / 10.0f); + bolus.setDuration(data[2] * 30); + } + + bolus.setBolusType((bolus.getDuration() != null && (bolus.getDuration() > 0)) ? PumpBolusType.Extended : PumpBolusType.Normal); + bolus.setLocalDateTime(entry.getLocalDateTime()); + + if (bolusEntry != null) { + if (bolus.getBolusType() == PumpBolusType.Extended) { + if (bolusEntry.getLocalDateTime().equals(bolus.getLocalDateTime())) { + bolus.setImmediateAmount(bolusEntry.getDeliveredAmount()); + bolus.setBolusType(PumpBolusType.Multiwave); + + writeBolus(entry, bolus); + } else { + // FIXME ths might not be correct + writeBolus(entry, bolusEntry); + } + } else { + writeBolus(entry, bolusEntry); + } + } + + bolusEntry = bolus; + pumpHistoryEntry4BolusEntry = entry; + } + + + private void resetBolusEntry() { + bolusEntry = null; + pumpHistoryEntry4BolusEntry = null; + } + + + private void writeBolus(PumpHistoryEntry pumpHistoryEntry, BolusDTO bolus) { + //writeData(PumpBaseType.Bolus, bolus.getBolusType(), bolus.getValue(), bolus.getATechDate()); + pumpHistoryEntry.setHistoryEntryDetails(bolus); + resetBolusEntry(); + } + + + // FIXME + private void decodeTempBasal(PumpHistoryEntry entry) { + if (this.tbrPreviousRecord == null) { + // LOG.debug(this.tbrPreviousRecord.toString()); + this.tbrPreviousRecord = entry; + return; + } + + PumpHistoryEntry tbrRate = null, tbrDuration = null; + + if (entry.getEntryType() == PumpHistoryEntryType.TempBasalRate) { + tbrRate = entry; + } else { + tbrDuration = entry; + } + + if (tbrRate != null) { + tbrDuration = tbrPreviousRecord; + } else { + tbrRate = tbrPreviousRecord; + } + + // LOG.debug("Rate: " + tbrRate.toString()); + // LOG.debug("Durration: " + tbrDuration.toString()); + + BasalProfileEntry basalProfileEntry = new BasalProfileEntry(tbrRate.getHead()[0], tbrDuration.getHead()[0]); + + + // System.out.println( + // "TBR: amount=" + tbr.getAmount() + ", duration=" + tbr.getDuration() + // + " min. Packed: " + tbr.getValue()); + + // FIXME set Unit + + // FIXME AAPS + // if (tbr.getDuration() > 0) { + // writeData(PumpBaseType.Basal, PumpBasalType.TemporaryBasalRate, tbr.getValue(), entry.getATechDate()); + // } else { + // writeData(PumpBaseType.Basal, PumpBasalType.TemporaryBasalRateCanceled, "", entry.getATechDate()); + // } + + tbrPreviousRecord = null; + } + + + private void decodeDateTime(PumpHistoryEntry entry) { + byte[] dt = entry.getDatetime(); + + if (dt == null) { + LOG.warn("DateTime not set."); + } + + if (entry.getDateTimeLength() == 5) { + + int seconds = dt[0] & 0x3F; + int minutes = dt[1] & 0x3F; + int hour = dt[2] & 0x1F; + + int month = ((dt[0] >> 4) & 0x0c) + ((dt[1] >> 6) & 0x03); + // ((dt[0] & 0xC0) >> 6) | ((dt[1] & 0xC0) >> 4); + + + int dayOfMonth = dt[3] & 0x1F; + int year = fix2DigitYear(dt[4] & 0x3F); // Assuming this is correct, need to verify. Otherwise this will be a problem in 2016. + + LocalDateTime atdate = new LocalDateTime(year, month, dayOfMonth, hour, minutes, seconds); + + entry.setLocalDateTime(atdate); + } else if (entry.getDateTimeLength() == 2) { + int low = ByteUtil.asUINT8(dt[0]) & 0x1F; + int mhigh = (ByteUtil.asUINT8(dt[0]) & 0xE0) >> 4; + int mlow = (ByteUtil.asUINT8(dt[1]) & 0x80) >> 7; + int month = mhigh + mlow; + int dayOfMonth = low + 1; + int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F); + + //LocalDate rval = new LocalDate(year, month, dayOfMonth); + + // int dayOfMonth = dt[0] & 0x1F; + // int month = (((dt[0] & 0xE0) >> 4) + ((dt[1] & 0x80) >> 7)); + // int year = fix2DigitYear(dt[1] & 0x3F); + + LocalDateTime atdate = new LocalDateTime(year, month, dayOfMonth, 0, 0); + + entry.setLocalDateTime(atdate); + } else { + LOG.warn("Unknown datetime format: " + entry.getDateTimeLength()); + } + // return new DateTime(year + 2000, month, dayOfMonth, hour, minutes, + // seconds); + + } + + + private int fix2DigitYear(int year) { + if (year > 90) { + year += 1900; + } else { + year += 2000; + } + + return year; + } + + + // WRITE DATA + + + // private void writeData(PumpBaseType baseType, CodeEnumWithTranslation subType, ATechDate aTechDate) { + // this.pumpValuesWriter.writeObject(baseType.name() + "_" + subType.getName(), aTechDate); + // } + // + // + // private void writeData(PumpBaseType baseType, CodeEnumWithTranslation subType, String value, ATechDate aTechDate) { + // this.pumpValuesWriter.writeObject(baseType.name() + "_" + subType.getName(), aTechDate, value); + // } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntry.java new file mode 100644 index 0000000000..399502c830 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntry.java @@ -0,0 +1,92 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpTimeStampedRecord; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: PumpHistoryEntry + * Description: Pump History Entry. + *

+ * Author: Andy {andy@atech-software.com} + */ + +public class PumpHistoryEntry extends MedtronicHistoryEntry { + + private PumpHistoryEntryType entryType; + private Integer opCode; // this is set only when we have unknown entry... + //private LocalDateTime timeOfEntry; + private int offset; + + + public PumpHistoryEntryType getEntryType() { + return entryType; + } + + + public void setEntryType(PumpHistoryEntryType entryType) { + this.entryType = entryType; + + this.sizes[0] = entryType.getHeadLength(); + this.sizes[1] = entryType.getDateLength(); + this.sizes[2] = entryType.getBodyLength(); + } + + + @Override + public int getOpCode() { + if (opCode == null) + return entryType.getOpCode(); + else + return opCode; + } + + + @Override + public String getToStringStart() { + return "PumpHistoryRecord [type=" + entryType.name() + " [" + getOpCode() + ", 0x" + HexDump.getCorrectHexValue((byte) getOpCode()) + "]"; + } + + + public void setOpCode(Integer opCode) { + this.opCode = opCode; + } + + + public PumpTimeStampedRecord getHistoryEntryDetails() { + return historyEntryDetails; + } + + + public void setHistoryEntryDetails(PumpTimeStampedRecord historyEntryDetails) { + this.historyEntryDetails = historyEntryDetails; + } + + + public int getOffset() { + return offset; + } + + + public void setOffset(int offset) { + this.offset = offset; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntryType.java new file mode 100644 index 0000000000..760cf44416 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/PumpHistoryEntryType.java @@ -0,0 +1,411 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + + +import org.apache.commons.collections.CollectionUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: PumpHistoryEntryType + * Description: Pump History Entry Type. + *

+ * Data is from several sources, so in comments there are "versions". + * Version: + * v1 - default doc from decoding-carelink + * v2 - nightscout code + * v3 - testing + * v4 - Andy testing (?) + * v5 - Loop code and another batch of testing with 512 + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum PumpHistoryEntryType //implements CodeEnum +{ + + None(0, "None", 1, 0, 0), // Bolus(0x01, "Bolus", 4, 5, 4), // 4,5,0 -> 4,5,4 Bolus(0x01, "Bolus", 2, 5, 4), + + Bolus(0x01, "Bolus", 4, DateFormat.LongDate, 0), // 523+[H=8] + + Prime(0x03, "Prime", 5, 5, 0), // + + EventUnknown_MM522_0x05((byte) 0x05, 2, 5, 28), // + + NoDeliveryAlarm(0x06, "NoDelivery", 4, 5, 0), // + EndResultTotals(0x07, "ResultTotals", 5, 2, 0), // V1: 5/5/41 V2: 5,2,3 V3, 5,2,0 V5: 7/10(523) + ChangeBasalProfile_OldProfile(0x08, 2, 5, 145), // // V1: 2,5,42 V2:2,5,145; V4: V5 + ChangeBasalProfile_NewProfile(0x09, 2, 5, 145), // + EventUnknown_MM512_0x10(0x10), // 29, 5, 0 + CalBGForPH(0x0a, "CalBGForPH"), // + SensorAlert(0x0b, "SensorAlert", 3, 5, 0), // Ian08 + ClearAlarm(0x0c, "ClearAlarm", 2, 5, 0), // 2,5,4 + + //Andy0d(0x0d, "Unknown", 2, 5, 0), + + SelectBasalProfile(0x14, "SelectBasalProfile"), // + TempBasalDuration(0x16, "TempBasalDuration"), // + ChangeTime(0x17, "ChangeTime"), // + NewTimeSet(0x18, "NewTimeSet"), // + LowBattery(0x19, "LowBattery"), // + BatteryActivity(0x1a, "Battery Activity"), // + SetAutoOff(0x1b, "SetAutoOff"), // + PumpSuspend(0x1e, "PumpSuspend"), // + PumpResume(0x1f, "PumpResume"), // + SelfTest(0x20, "SelfTest"), // + Rewind(0x21, "Rewind"), // + ClearSettings(0x22, "ClearSettings"), // 8? + ChangeChildBlockEnable(0x23, "ChangeChildBlockEnable"), // 8? + ChangeMaxBolus(0x24), // 8? + EventUnknown_MM522_0x25(0x25), // 8? + ToggleRemote(0x26, "EnableDisableRemote", 2, 5, 0), // 2, 5, 14 + ChangeRemoteId(0x27, "ChangeRemoteID"), // ?? + + ChangeMaxBasal(0x2c), // + BolusWizardEnabled(0x2d), // V3 ? + EventUnknown_MM512_0x2e(0x2e), // + EventUnknown_MM512_0x2f(0x2f), // + ChangeBGReminderOffset(0x31), // + ChangeAlarmClockTime(0x32), // + TempBasalRate(0x33, "TempBasal", 2, 5, 1), // + LowReservoir(0x34), // + + ChangeMeterId(0x36), // + EventUnknown_MM512_0x37(0x37), // V:MM512 + EventUnknown_MM512_0x38(0x38), // + EventUnknown_MM512_0x39(0x39), // + EventUnknown_MM512_0x3b(0x3b), // + ChangeParadigmLinkID(0x3c), // V3 ? + + BGReceived(0x3f, "BGReceived", 2, 5, 3), // Ian3F + JournalEntryMealMarker(0x40, 2, 5, 2), // + JournalEntryExerciseMarker(0x41, 2, 5, 1), // ?? JournalEntryExerciseMarkerPumpEvent + JournalEntryInsulinMarker(0x42, 2, 5, 1), // ?? InsulinMarkerEvent + JournalEntryOtherMarker(0x43), // + EventUnknown_MM522_0x45(0x45, 2, 5, 1), // + EventUnknown_MM522_0x46(0x46, 2, 5, 1), // + EventUnknown_MM522_0x47(0x47, 2, 5, 1), // + EventUnknown_MM522_0x48(0x48, 2, 5, 1), // + EventUnknown_MM522_0x49(0x49, 2, 5, 1), // + EventUnknown_MM522_0x4a(0x4a, 2, 5, 1), // + EventUnknown_MM522_0x4b(0x4b, 2, 5, 1), // + EventUnknown_MM522_0x4c(0x4c, 2, 5, 1), // + + + EventUnknown_0x4d(0x4d), // V5: 512: 7, 522: 8 ????NS + EventUnknown_MM512_0x4e(0x4e), // + + ChangeBolusWizardSetup(0x4f, 2, 5, 32), // + ChangeSensorSetup2(0x50, 2, 5, 30), // Ian50 + RestoreMystery51(0x51), // + RestoreMystery52(0x52), // + ChangeSensorAlarmSilenceConfig(0x53, 2, 5, 1), // 8 + RestoreMystery54(0x54), // Ian54 + RestoreMystery55(0x55), // + ChangeSensorRateOfChangeAlertSetup(0x56, 2, 5, 5), // 12 + ChangeBolusScrollStepSize(0x57), // + + + // V4 + //Andy58(0x58, "Unknown", 13, 5, 0), // TODO is this one really there ??? + + + BolusWizardChange(0x5a, "BolusWizard", 2, 5, 117), // V2: 522+[B=143] + BolusWizardBolusEstimate(0x5b, "BolusWizardBolusEstimate", 2, 5, 13), // 15 // V2: 523+[B=15] + UnabsorbedInsulin(0x5c, "UnabsorbedInsulinBolus", 5, 0, 0), // head[1] -> body length + SaveSettings(0x5d), // + ChangeVariableBolus(0x5e), // + ChangeAudioBolus(0x5f, "EasyBolusEnabled"), // V3 ? + ChangeBGReminderEnable(0x60), // questionable60 + ChangeAlarmClockEnable((byte) 0x61), // + ChangeTempBasalType((byte) 0x62), // ChangeTempBasalTypePumpEvent + ChangeAlarmNotifyMode(0x63), // + ChangeTimeFormat(0x64), // + ChangeReservoirWarningTime((byte) 0x65), // + ChangeBolusReminderEnable(0x66, 2, 5, 2), // 9 + ChangeBolusReminderTime((byte) 0x67, 2, 5, 2), // 9 + DeleteBolusReminderTime((byte) 0x68, 2, 5, 2), // 9 + BolusReminder(0x69, 2, 5, 0), // Ian69 + DeleteAlarmClockTime(0x6a, "DeleteAlarmClockTime", 2, 5, 7), // 14 + + DailyTotals512(0x6c, "Daily Totals 512", 0, 0, 36), // + DailyTotals522(0x6d, "Daily Totals 522", 1, 2, 41), // // hack1(0x6d, "hack1", 46, 5, 0), + DailyTotals523(0x6e, "Daily Totals 523", 1, 2, 49), // 1102014-03-17T00:00:00 + ChangeCarbUnits((byte) 0x6f), // + + EventUnknown_MM522_0x70((byte) 0x70, 2, 5, 1), // + + + BasalProfileStart(0x7b, 2, 5, 3), // // 722 + ChangeWatchdogEnable((byte) 0x7c), // + ChangeOtherDeviceID((byte) 0x7d, 2, 5, 30), // + + ChangeWatchdogMarriageProfile((byte) 0x81, 2, 5, 5), // 12 + DeleteOtherDeviceID((byte) 0x82, 2, 5, 5), // + ChangeCaptureEventEnable((byte) 0x83), // + + EventUnknown_MM512_0x88((byte) 0x88), // + EventUnknown_MM512_0x94((byte) 0x94), // + //IanA8(0xA8, "xx", 10, 5, 0), // + + //Andy90(0x90, "Unknown", 7, 5, 0), + + //AndyB4(0xb4, "Unknown", 7, 5, 0), + // Andy4A(0x4a, "Unknown", 5, 5, 0), + + // head[1], + // body[49] op[0x6e] + + EventUnknown_MM522_0xE8(0xe8, 2, 5, 25), // + + UnknownBasePacket(0xFF, "Unknown Base Packet"); + + // private PumpHistoryEntryType(String description, List opCode, + // byte length) + // { + // + // } + + private int opCode; + private String description; + private int headLength = 0; + private int dateLength; + private int bodyLength; + private int totalLength; + // private MinimedDeviceType deviceType; + + // special rules need to be put in list from highest to lowest (e.g.: + // 523andHigher=12, 515andHigher=10 and default (set in cnstr) would be 8) + private List specialRulesHead; + private List specialRulesBody; + private boolean hasSpecialRules = false; + + private static Map opCodeMap = new HashMap(); + + static { + for (PumpHistoryEntryType type : values()) { + opCodeMap.put(type.opCode, type); + } + + setSpecialRulesForEntryTypes(); + } + + + static void setSpecialRulesForEntryTypes() { + EndResultTotals.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 3)); + Bolus.addSpecialRuleHead(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 8)); + BolusWizardChange.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_522andHigher, 143)); + BolusWizardBolusEstimate.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 15)); + BolusReminder.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 2)); + } + + + PumpHistoryEntryType(int opCode, String name) { + this(opCode, name, 2, 5, 0); + } + + + PumpHistoryEntryType(int opCode) { + this(opCode, null, 2, 5, 0); + } + + + PumpHistoryEntryType(int opCode, int head, int date, int body) { + this(opCode, null, head, date, body); + } + + + PumpHistoryEntryType(int opCode, String name, int head, DateFormat dateFormat, int body) { + this(opCode, name, head, dateFormat.getLength(), body); + } + + + PumpHistoryEntryType(int opCode, String name, int head, int date, int body) { + this.opCode = (byte) opCode; + this.description = name; + this.headLength = head; + this.dateLength = date; + this.bodyLength = body; + this.totalLength = (head + date + body); + } + + + public int getCode() { + return this.opCode; + } + + + // + // private PumpHistoryEntryType(int opCode, String name, int head, int date, + // int body) + // { + // this.opCode = (byte) opCode; + // this.description = name; + // this.headLength = head; + // this.dateLength = date; + // this.bodyLength = body; + // this.totalLength = (head + date + body); + // } + // + + + public int getTotalLength() { + if (hasSpecialRules()) { + return getHeadLength() + getBodyLength() + getDateLength(); + } else { + return totalLength; + } + } + + + private boolean hasSpecialRules() { + return hasSpecialRules; + } + + + void addSpecialRuleHead(SpecialRule rule) { + if (CollectionUtils.isEmpty(specialRulesHead)) { + specialRulesHead = new ArrayList(); + } + + specialRulesHead.add(rule); + hasSpecialRules = true; + } + + + void addSpecialRuleBody(SpecialRule rule) { + if (CollectionUtils.isEmpty(specialRulesBody)) { + specialRulesBody = new ArrayList(); + } + + specialRulesBody.add(rule); + hasSpecialRules = true; + } + + + public static PumpHistoryEntryType getByCode(int opCode) { + if (opCodeMap.containsKey(opCode)) { + return opCodeMap.get(opCode); + } else { + return PumpHistoryEntryType.UnknownBasePacket; + } + } + + + public int getOpCode() { + return opCode; + } + + + public String getDescription() { + return this.description == null ? name() : this.description; + } + + + public int getHeadLength() { + if (hasSpecialRules) { + if (CollectionUtils.isNotEmpty(specialRulesHead)) { + return determineSizeByRule(headLength, specialRulesHead); + } else { + return headLength; + } + } else { + return headLength; + } + } + + + public int getDateLength() { + return dateLength; + } + + + public int getBodyLength() { + if (hasSpecialRules) { + if (CollectionUtils.isNotEmpty(specialRulesBody)) { + return determineSizeByRule(bodyLength, specialRulesBody); + } else { + return bodyLength; + } + } else { + return bodyLength; + } + } + + + private int determineSizeByRule(int defaultValue, List rules) { + int size = defaultValue; + + for (SpecialRule rule : rules) { + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), rule.deviceType)) { + size = rule.size; + break; + } + } + + return size; + } + + // byte[] dh = { 2, 3 }; + + public static class SpecialRule { + + MedtronicDeviceType deviceType; + int size; + + + public SpecialRule(MedtronicDeviceType deviceType, int size) { + this.deviceType = deviceType; + this.size = size; + } + } + + + enum DateFormat { + None(0), // + LongDate(5), // + ShortDate(2); + + private int length; + + + DateFormat(int length) { + this.length = length; + } + + + public int getLength() { + return length; + } + + + public void setLength(int length) { + this.length = length; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/RecordDecodeStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/RecordDecodeStatus.java new file mode 100644 index 0000000000..c16a97920b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/data/history2/RecordDecodeStatus.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history2; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: GGC PlugIn Base (base class for all plugins) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: Record Decode Status + * Description: Record Decode Status shows if entry was decoded. Used mostly for statistics. + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum RecordDecodeStatus { + OK("OK "), // + Ignored("IGNORE "), // + NotSupported("N/A YET"), // + Error("ERROR "), // + WIP("WIP "), // + Unknown("UNK "); + + String description; + + + RecordDecodeStatus(String description) { + this.description = description; + + } + + + public String getDescription() { + return description; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkLongMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkLongMessageBody.java index be30057100..69bc6c4ac3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkLongMessageBody.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkLongMessageBody.java @@ -7,30 +7,35 @@ public class CarelinkLongMessageBody extends MessageBody { public static final int LONG_MESSAGE_BODY_LENGTH = 65; protected byte[] data; + public CarelinkLongMessageBody() { init(new byte[0]); } + public CarelinkLongMessageBody(byte[] payload) { init(payload); } + @Override public void init(byte[] rxData) { data = new byte[LONG_MESSAGE_BODY_LENGTH]; if (rxData != null) { int size = rxData.length < LONG_MESSAGE_BODY_LENGTH ? rxData.length : LONG_MESSAGE_BODY_LENGTH; - for (int i = 0; i < size; i++) { + for(int i = 0; i < size; i++) { data[i] = rxData[i]; } } } + @Override public int getLength() { return LONG_MESSAGE_BODY_LENGTH; } + @Override public byte[] getTxData() { return data; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkShortMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkShortMessageBody.java index bbde3ff332..8b564451ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkShortMessageBody.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/CarelinkShortMessageBody.java @@ -3,40 +3,49 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message; /** * Created by geoff on 5/29/16. */ +// Andy: See comments in message body public class CarelinkShortMessageBody extends MessageBody { byte[] body; + @Override public int getLength() { return body.length; } + public CarelinkShortMessageBody() { init(new byte[]{0}); } + public CarelinkShortMessageBody(byte[] data) { init(data); } + @Override public void init(byte[] rxData) { body = rxData; } + public byte[] getRxData() { return body; } + public void setRxData(byte[] rxData) { init(rxData); } + @Override public byte[] getTxData() { return body; } + public void setTxData(byte[] txData) { init(txData); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java new file mode 100644 index 0000000000..f8ab15a668 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java @@ -0,0 +1,360 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message; + + +import org.joda.time.IllegalFieldValueException; +import org.joda.time.LocalDateTime; +import org.joda.time.LocalTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfile; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.TempBasalPair; +import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpConfigurationGroup; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; + +/** + * Created by andy on 5/9/18. + */ + +public class MedtronicConverter { + + private static final Logger LOG = LoggerFactory.getLogger(MedtronicConverter.class); + + MedtronicDeviceType pumpModel; + + + public Object convertResponse(MedtronicCommandType commandType, byte[] rawContent) { + + LOG.debug("Raw response before convert: " + HexDump.toHexStringDisplayable(rawContent)); + + this.pumpModel = RileyLinkUtil.getMedtronicPumpModel(); + + switch (commandType) { + + case PumpModel: { + return MedtronicDeviceType.getByDescription(StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3))); + } + + case RealTimeClock: { + return decodeTime(rawContent); + } + + case GetRemainingInsulin: { + return decodeRemainingInsulin(rawContent); + } + + case GetBatteryStatus: { + return decodeBatteryStatus(rawContent); + } + + case GetBasalProfileSTD: { + return new BasalProfile(rawContent); + } + + case ReadTemporaryBasal: { + return new TempBasalPair(rawContent); + } + + case Settings_512: { + return decodeSettings512(rawContent); + } + + case Settings: { + return decodeSettings(rawContent); + } + + case SetBolus: { + return rawContent; + } + + + default: { + throw new RuntimeException("Unsupported command Type: " + commandType); + } + + } + + + } + + + protected BasalProfile decodeProfile2(byte[] rep) { + //byte rep[] = minimedReply.getRawData(); + + // String profile = getProfileName(minimedReply); + + BasalProfile basalProfile = new BasalProfile(); + + // 0x12 0x00 0x00 0x16 0x00 0x11 0x00 + + if ((rep.length >= 3) && (rep[2] == 0x3F)) { + //String i18value = i18nControl.getMessage("NOT_SET"); + //writeSetting(key, i18value, i18value, PumpConfigurationGroup.Basal); + return null; + } + + int time_x; + double vald; + + for (int i = 0; i < rep.length; i += 3) { + + + vald = MedtronicUtil.decodeBasalInsulin(rep[i + 1], rep[i]); + + time_x = rep[i + 2]; + + LocalTime atd = MedtronicUtil.getTimeFrom30MinInterval(time_x); + + if ((i != 0) && (time_x == 0)) { + break; + } + + //String value = i18nControl.getMessage("CFG_BASE_FROM") + "=" + atd.getTimeString() + ", " + // + i18nControl.getMessage("CFG_BASE_AMOUNT") + "=" + vald; + + //writeSetting(key, value, value, PumpConfigurationGroup.Basal); + + + } + + return basalProfile; + } + + + private Integer decodeBatteryStatus(byte[] rawData) { + //00 00 7C 00 00 + + if (rawData.length <= 2) { + + int status = rawData[0]; + + if (status == 0) { + return 75; // NORMAL + } else if (status == 1) { + return 20; // LOW + } else if (status == 2) { + + } + + return null; + } else { + // if response in 3 bytes then we add additional information + //double d = MedtronicUtil.makeUnsignedShort(rawData[2], rawData[1]) / 100.0d; + + double d = ByteUtil.toInt(rawData[1], rawData[2]) / 100.0d; + + double perc = (d - BatteryType.Alkaline.lowVoltage) / (BatteryType.Alkaline.highVoltage - BatteryType.Alkaline.lowVoltage); + + LOG.warn("Percent status: " + perc); + LOG.warn("Unknown status: " + rawData[0]); + LOG.warn("Full result: " + d); + + int percent = (int) (perc * 100.0d); + + return percent; + } + + } + + + protected Float decodeRemainingInsulin(byte[] rawData) { + //float value = MedtronicUtil.makeUnsignedShort(rawData[0], rawData[1]) / 10.0f; + + float value = ByteUtil.toInt(rawData[0], rawData[1]) / 10.0f; + + System.out.println("Remaining insulin: " + value); + return value; + } + + + private LocalDateTime decodeTime(byte[] rawContent) { + + int hours = ByteUtil.asUINT8(rawContent[0]); + int minutes = ByteUtil.asUINT8(rawContent[1]); + int seconds = ByteUtil.asUINT8(rawContent[2]); + int year = (ByteUtil.asUINT8(rawContent[4]) & 0x3f) + 1984; + int month = ByteUtil.asUINT8(rawContent[5]); + int day = ByteUtil.asUINT8(rawContent[6]); + try { + LocalDateTime pumpTime = new LocalDateTime(year, month, day, hours, minutes, seconds); + return pumpTime; + } catch (IllegalFieldValueException e) { + LOG.error("decodeTime: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", year, month, day, hours, minutes, seconds); + return null; + } + + } + + + public List decodeSettings512(byte[] rd) { + + List outList = new ArrayList<>(); + + outList.add(new PumpSettingDTO("PCFG_AUTOOFF_TIMEOUT", "" + rd[0], PumpConfigurationGroup.General)); + + + if (rd[1] == 4) { + outList.add(new PumpSettingDTO("PCFG_ALARM_MODE", "Silent", PumpConfigurationGroup.Sound)); + } else { + outList.add(new PumpSettingDTO("PCFG_ALARM_MODE", "Normal", PumpConfigurationGroup.Sound)); + outList.add(new PumpSettingDTO("PCFG_ALARM_BEEP_VOLUME", "" + rd[1], PumpConfigurationGroup.Sound)); + } + + outList.add(new PumpSettingDTO("PCFG_AUDIO_BOLUS_ENABLED", parseResultEnable(rd[2]), PumpConfigurationGroup.Bolus)); + + if (rd[2] == 1) { + outList.add(new PumpSettingDTO("PCFG_AUDIO_BOLUS_STEP_SIZE", "" + decodeBolusInsulin(ByteUtil.asUINT8(rd[3])), PumpConfigurationGroup.Bolus)); + } + + outList.add(new PumpSettingDTO("PCFG_VARIABLE_BOLUS_ENABLED", parseResultEnable(rd[4]), PumpConfigurationGroup.Bolus)); + outList.add(new PumpSettingDTO("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus)); + outList.add(new PumpSettingDTO("PCFG_MAX_BASAL", "" + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal)); + outList.add(new PumpSettingDTO("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h", PumpConfigurationGroup.General)); + outList.add(new PumpSettingDTO("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] != 0 ? 50 : 100), PumpConfigurationGroup.Insulin)); + outList.add(new PumpSettingDTO("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal)); + + if (rd[10] == 1) { + String patt; + switch (rd[11]) { + case 0: + patt = "STD"; + break; + + case 1: + patt = "A"; + break; + + case 2: + patt = "B"; + break; + + default: + patt = "???"; + break; + } + + outList.add(new PumpSettingDTO("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal)); + + } + + outList.add(new PumpSettingDTO("CFG_MM_RF_ENABLED", parseResultEnable(rd[12]), PumpConfigurationGroup.General)); + outList.add(new PumpSettingDTO("CFG_MM_BLOCK_ENABLED", parseResultEnable(rd[13]), PumpConfigurationGroup.General)); + + outList.add(new PumpSettingDTO("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal)); + + if (rd[14] == 1) { + outList.add(new PumpSettingDTO("PCFG_TEMP_BASAL_PERCENT", "" + rd[15], PumpConfigurationGroup.Basal)); + } + + outList.add(new PumpSettingDTO("CFG_PARADIGM_LINK_ENABLE", parseResultEnable(rd[16]), PumpConfigurationGroup.General)); + + decodeInsulinActionSetting(rd, outList); + + return outList; + } + + + public List decodeSettings(byte[] rd) { + List outList = decodeSettings512(rd); + + outList.add(new PumpSettingDTO("PCFG_MM_RESERVOIR_WARNING_TYPE_TIME", rd[18] != 0 ? "PCFG_MM_RESERVOIR_WARNING_TYPE_TIME" : "PCFG_MM_RESERVOIR_WARNING_TYPE_UNITS", PumpConfigurationGroup.Other)); + + outList.add(new PumpSettingDTO("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), PumpConfigurationGroup.Other)); + + outList.add(new PumpSettingDTO("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20]), PumpConfigurationGroup.Other)); + + + if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + + outList.add(new PumpSettingDTO("PCFG_BOLUS_SCROLL_STEP_SIZE", "" + rd[21], PumpConfigurationGroup.Bolus)); + outList.add(new PumpSettingDTO("PCFG_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22]), PumpConfigurationGroup.Other)); + outList.add(new PumpSettingDTO("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23]), PumpConfigurationGroup.Other)); + outList.add(new PumpSettingDTO("PCFG_OTHER_DEVICE_PAIRED_STATE", parseResultEnable(rd[24]), PumpConfigurationGroup.Other)); + } + + return outList; + } + + + protected String parseResultEnable(int i) { + switch (i) { + case 0: + return "No"; + case 1: + return "Yes"; + default: + return "???"; + } + } + + + public float getStrokesPerUnit(boolean isBasal) { + return isBasal ? 40.0f : 10.0f; + } + + + // 512 + public void decodeInsulinActionSetting(byte ai[], List outList) { + if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_512_712)) { + outList.add(new PumpSettingDTO("PCFG_INSULIN_ACTION_TYPE", (ai[17] != 0 ? "Regular" : "Fast"), PumpConfigurationGroup.Insulin)); + } else { + int i = ai[17]; + String s = ""; + + if ((i == 0) || (i == 1)) { + s = ai[17] != 0 ? "Regular" : "Fast"; + } else { + if (i == 15) + s = "Unset"; + else + s = "Curve: " + i; + } + + outList.add(new PumpSettingDTO("PCFG_INSULIN_ACTION_TYPE", s, PumpConfigurationGroup.Insulin)); + } + } + + + public double decodeBasalInsulin(int i) { + return (double) i / (double) getStrokesPerUnit(true); + } + + + public double decodeBolusInsulin(int i) { + + return (double) i / (double) getStrokesPerUnit(false); + } + + + private int getSettingIndexMaxBasal() { + return is523orHigher() ? 7 : 6; + } + + + private int getSettingIndexTimeDisplayFormat() { + return is523orHigher() ? 9 : 8; + } + + + public double decodeMaxBolus(byte ai[]) { + return is523orHigher() ? decodeBolusInsulin(ByteUtil.toInt(ai[5], ai[6])) : decodeBolusInsulin(ByteUtil.asUINT8(ai[5])); + } + + + private boolean is523orHigher() { + return (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageBody.java index c20b8647c0..f4698be922 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageBody.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageBody.java @@ -1,17 +1,38 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; + /** * Created by geoff on 5/29/16. */ + +// Andy (4.6.2018): We probably need rewrite of this message body code. If there is no data sent, body is 00, which denotes, +// no parameters. If we have 3 parameters sent (1 2 3), the body would actually be length of 4, first byte beeing the length +// of the message, so the body would be 3 1 2 3. This is not done that way now. public class MessageBody { public int getLength() { return 0; } + public void init(byte[] rxData) { } + public byte[] getTxData() { return new byte[]{}; } + + + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + + sb.append(" [txData="); + sb.append(HexDump.toHexStringDisplayable(getTxData())); + sb.append("]"); + + return sb.toString(); + } + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageType.java index 3f2344d52c..2b7da8949d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MessageType.java @@ -12,30 +12,30 @@ import java.util.Map; // changed to Enum, since this is now enum, I had to remove duplicate entries, so if entry is on first list, it was removed // from second (commented out) +@Deprecated public enum MessageType { - Invalid((byte) 0x00), - Alert((byte) 0x01), - AlertCleared((byte) 0x02), - DeviceTest((byte) 0x03), - PumpStatus((byte) 0x04), - PumpAck((byte) 0x06), - PumpBackfill((byte) 0x08), - FindDevice((byte) 0x09), - DeviceLink((byte) 0x0a), - ChangeTime((byte) 0x40), - Bolus((byte) 0x42), - ChangeTempBasal((byte) 0x4c), - ButtonPress((byte) 0x5b), - PowerOn((byte) 0x5d), - ReadTime((byte) 0x70), - GetBattery((byte) 0x72), - GetHistoryPage((byte) 0x80), - GetISFProfile((byte) 0x8b), - GetPumpModel((byte) 0x8d), - ReadTempBasal((byte) 0x98), - ReadSettings((byte) 0xc0), - SetBasalProfileSTD((byte) 111), - ReadBasalProfileSTD((byte) 146), + Invalid((byte) 0x00), Alert((byte) 0x01), // + AlertCleared((byte) 0x02), // + DeviceTest((byte) 0x03), // + PumpStatus((byte) 0x04), // + PumpAck((byte) 0x06), // + PumpBackfill((byte) 0x08), // + FindDevice((byte) 0x09), // + DeviceLink((byte) 0x0a), // + ChangeTime((byte) 0x40), // + Bolus((byte) 0x42), // + ChangeTempBasal((byte) 0x4c), // + ButtonPress((byte) 0x5b), // + PowerOn((byte) 0x5d), // + ReadTime((byte) 0x70), // + GetBattery((byte) 0x72), // + GetHistoryPage((byte) 0x80), // + GetISFProfile((byte) 0x8b), // + GetPumpModel((byte) 0x8d), // + ReadTempBasal((byte) 0x98), // + ReadSettings((byte) 0xc0), // + SetBasalProfileSTD((byte) 0x6f), // + ReadBasalProfileSTD((byte) 0x92), // The above codes include codes that are not 522/722 specific. @@ -115,7 +115,7 @@ public enum MessageType { boolean foundErrors = false; - for (MessageType messageType : values()) { + for(MessageType messageType : values()) { if (mapByValue.containsKey(messageType.getValue())) { // leave this check in case someone adds any new commands @@ -127,8 +127,7 @@ public enum MessageType { } if (foundErrors) { - LOG.error("MessageType has duplicate entries. Each items needs to have unique value associated with it. " + - "If this is not the case, application might not work correctly. Fix this and restart application."); + LOG.error("MessageType has duplicate entries. Each items needs to have unique value associated with it. " + "If this is not the case, application might not work correctly. Fix this and restart application."); System.exit(0); } @@ -138,10 +137,12 @@ public enum MessageType { byte mtype; + MessageType(byte mtype) { this.mtype = mtype; } + public static MessageBody constructMessageBody(MessageType messageType, byte[] bodyData) { switch (messageType) { case PumpAck: @@ -151,10 +152,12 @@ public enum MessageType { } } + public byte getValue() { return this.mtype; } + public static MessageType getByValue(byte msgType) { if (mapByValue.containsKey(msgType)) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PacketType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PacketType.java index 5588cf9b19..650edba836 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PacketType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PacketType.java @@ -15,30 +15,30 @@ public enum PacketType { Sensor(0xa8) // ; - private short value = 0; - public static Map mapByValue; + private byte value = 0; + public static Map mapByValue; static { mapByValue = new HashMap<>(); - for (PacketType packetType : values()) { + for(PacketType packetType : values()) { mapByValue.put(packetType.value, packetType); } } PacketType(int value) { - this.value = (short) value; + this.value = (byte) value; } - public short getValue() { + + public byte getValue() { return value; } + public static PacketType getByValue(short value) { - if (mapByValue.containsKey(value)) - return mapByValue.get(value); - else - return PacketType.Invalid; + if (mapByValue.containsKey(value)) return mapByValue.get(value); + else return PacketType.Invalid; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java index a2467e50f8..573930343f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java @@ -1,31 +1,62 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; +import android.util.Log; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessage; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; /** * Created by geoff on 5/29/16. */ +// FIXME: Andy Message body problem, see comment in MessageBody public class PumpMessage implements RLMessage { + public PacketType packetType = PacketType.Carelink; public byte[] address = new byte[]{0, 0, 0}; - public MessageType messageType = MessageType.Invalid; + public MedtronicCommandType commandType; + public Byte invalidCommandType; public MessageBody messageBody = new MessageBody(); + public String error = null; - public PumpMessage() { + + public PumpMessage(String error) { + this.error = error; } + public PumpMessage(byte[] rxData) { init(rxData); } - public void init(PacketType packetType, byte[] address, MessageType messageType, MessageBody messageBody) { + + public PumpMessage() { + + } + + + public boolean isErrorResponse() { + return (this.error != null); + } + + + // public void init(PacketType packetType, byte[] address, MessageType messageType, MessageBody messageBody) { + // this.packetType = packetType; + // this.address = address; + // this.messageType = messageType; + // this.messageBody = messageBody; + // } + + + public void init(PacketType packetType, byte[] address, MedtronicCommandType commandType, MessageBody messageBody) { this.packetType = packetType; this.address = address; - this.messageType = messageType; + this.commandType = commandType; this.messageBody = messageBody; } + public void init(byte[] rxData) { if (rxData == null) { return; @@ -37,43 +68,140 @@ public class PumpMessage implements RLMessage { this.address = ByteUtil.substring(rxData, 1, 3); } if (rxData.length > 4) { - this.messageType = MessageType.getByValue(rxData[4]); + this.commandType = MedtronicCommandType.getByCode(rxData[4]); + if (this.commandType == MedtronicCommandType.InvalidCommand) { + Log.e("PumpMessage", "Unknown commandType " + rxData[4]); + } } if (rxData.length > 5) { - this.messageBody = MessageType.constructMessageBody(messageType, ByteUtil.substring(rxData, 5, rxData.length - 5)); + this.messageBody = MedtronicCommandType.constructMessageBody(commandType, ByteUtil.substring(rxData, 5, rxData.length - 5)); } } + @Override public byte[] getTxData() { byte[] rval = ByteUtil.concat(new byte[]{(byte) packetType.getValue()}, address); - rval = ByteUtil.concat(rval, messageType.getValue()); + rval = ByteUtil.concat(rval, commandType.getCommandCode()); rval = ByteUtil.concat(rval, messageBody.getTxData()); return rval; } + public byte[] getContents() { - return ByteUtil.concat(new byte[]{messageType.getValue()}, messageBody.getTxData()); + return ByteUtil.concat(new byte[]{commandType.getCommandCode()}, messageBody.getTxData()); } - public byte[] getRawContent() { - byte[] arrayOut = new byte[messageBody.getTxData().length - 1]; - System.arraycopy(messageBody.getTxData(), 1, arrayOut, 0, arrayOut.length); + // rawContent = just response without code (contents-2, messageBody.txData-1); + public byte[] getRawContent() { + + if ((messageBody == null) || (messageBody.getTxData() == null) || (messageBody.getTxData().length == 0)) + return null; + + byte[] data = messageBody.getTxData(); + + int length = ByteUtil.asUINT8(data[0]); // length is not always correct so, we check whole array if we have data, after length + int originalLength = length; + + // check if displayed length is invalid + if (length > data.length - 1) { + return data; + } + + // check Old Way + boolean oldWay = false; + for(int i = (length + 1); i < data.length; i++) { + if (data[i] != 0x00) { + oldWay = true; + } + } + + if (oldWay) { + length = data.length - 1; + } + + byte[] arrayOut = new byte[length]; + + System.arraycopy(messageBody.getTxData(), 1, arrayOut, 0, length); + + Log.d("PumpMessage", "Length: " + length + ", Original Length: " + originalLength + ", CommandType: " + commandType); return arrayOut; } + public boolean isValid() { - if (packetType == null) return false; - if (address == null) return false; - if (messageType == null) return false; - if (messageBody == null) return false; + if (packetType == null) + return false; + if (address == null) + return false; + if (commandType == null) + return false; + if (messageBody == null) + return false; return true; } + public MessageBody getMessageBody() { return messageBody; } + + public String getResponseContent() { + StringBuilder sb = new StringBuilder("PumpMessage [response="); + boolean showData = true; + + if (commandType != null) { + if (commandType == MedtronicCommandType.CommandACK) { + sb.append("Acknowledged"); + showData = false; + } else if (commandType == MedtronicCommandType.CommandNAK) { + sb.append("NOT Acknowledged"); + showData = false; + } else { + sb.append(commandType.name()); + } + } else { + sb.append("Unknown_Type"); + sb.append(" (" + invalidCommandType + ")"); + } + + if (showData) { + sb.append(", rawResponse="); + sb.append(HexDump.toHexStringDisplayable(getRawContent())); + } + + sb.append("]"); + + return sb.toString(); + } + + + public String toString() { + StringBuilder sb = new StringBuilder("PumpMessage ["); + + sb.append("packetType="); + sb.append(packetType == null ? "null" : packetType.name()); + + sb.append(", address=("); + sb.append(HexDump.toHexStringDisplayable(this.address)); + + sb.append("), commandType="); + sb.append(commandType == null ? "null" : commandType.name()); + + if (invalidCommandType != null) { + sb.append(", invalidCommandType="); + sb.append(invalidCommandType); + } + + sb.append(", messageBody=("); + sb.append(this.messageBody == null ? "null" : this.messageBody); + + sb.append(")]"); + + return sb.toString(); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusDTO.java new file mode 100644 index 0000000000..ad2510d3ac --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusDTO.java @@ -0,0 +1,138 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: Pump Tool (support for Pump devices) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: BolusDTO + * Description: Bolus DTO + *

+ * Author: Andy {andy@atech-software.com} + */ + +public class BolusDTO extends PumpTimeStampedRecord { + + private Float requestedAmount; + private Float deliveredAmount; + private Float immediateAmount; // when Multiwave this is used + private Integer duration; + private PumpBolusType bolusType; + private Float insulinOnBoard; + + + public BolusDTO() { + //this.decimalPrecission = 2; + } + + + public Float getRequestedAmount() { + return requestedAmount; + } + + + public void setRequestedAmount(Float requestedAmount) { + this.requestedAmount = requestedAmount; + } + + + public Float getDeliveredAmount() { + return deliveredAmount; + } + + + public void setDeliveredAmount(Float deliveredAmount) { + this.deliveredAmount = deliveredAmount; + } + + + public Integer getDuration() { + return duration; + } + + + public void setDuration(Integer duration) { + this.duration = duration; + } + + + public PumpBolusType getBolusType() { + return bolusType; + } + + + public void setBolusType(PumpBolusType bolusType) { + this.bolusType = bolusType; + } + + + public Float getInsulinOnBoard() { + return insulinOnBoard; + } + + + public void setInsulinOnBoard(Float insulinOnBoard) { + this.insulinOnBoard = insulinOnBoard; + } + + + private String getDurationString() { + int minutes = this.duration; + + int h = minutes / 60; + + minutes -= (h * 60); + + return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2); + } + + + public String getValue() { + if ((bolusType == PumpBolusType.Normal) || (bolusType == PumpBolusType.Audio)) { + return getFormattedDecimal(this.deliveredAmount); + } else if (bolusType == PumpBolusType.Extended) { + return String.format("AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.deliveredAmount), getDurationString()); + } else { + return String.format("AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.immediateAmount), getFormattedDecimal(this.deliveredAmount), getDurationString()); + } + } + + + public Float getImmediateAmount() { + return immediateAmount; + } + + + public void setImmediateAmount(Float immediateAmount) { + this.immediateAmount = immediateAmount; + } + + + public String getFormattedDecimal(double value) { + return StringUtil.getFormatedValueUS(value, 2); + } + + + public String getBolusKey() { + return "Bolus_" + this.bolusType.name(); + + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusWizardDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusWizardDTO.java new file mode 100644 index 0000000000..fac92fa7d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/BolusWizardDTO.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + + +import org.joda.time.LocalDateTime; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; + +/** + * Created by andy on 18.05.15. + */ +public class BolusWizardDTO extends PumpTimeStampedRecord { + + // bloodGlucose and bgTarets are in mg/dL + public Integer bloodGlucose = 0; // mg/dL + public Integer carbs = 0; + public String chUnit = "g"; + + public Float carbRatio = 0.0f; + public Float insulinSensitivity = 0.0f; + public Integer bgTargetLow = 0; + public Integer bgTargetHigh = 0; + public Float bolusTotal = 0.0f; + public Float correctionEstimate = 0.0f; + public Float foodEstimate = 0.0f; + public Float unabsorbedInsulin = 0.0f; + public LocalDateTime localDateTime; + + + public String getValue() { + return String.format("BG=%d;CH=%d;CH_UNIT=%s;CH_INS_RATIO=%5.3f;BG_INS_RATIO=%5.3f;" + "BG_TARGET_LOW=%d;BG_TARGET_HIGH=%d;BOLUS_TOTAL=%5.3f;" + "BOLUS_CORRECTION=%5.3f;BOLUS_FOOD=%5.3f;UNABSORBED_INSULIN=%5.3f", // + bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, // + bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin); + } + + + public String toString() { + return "BolusWizardDTO [dateTime=" + StringUtil.toDateTimeString(localDateTime) + ", " + getValue() + "]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpBolusType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpBolusType.java new file mode 100644 index 0000000000..f06c349cb3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpBolusType.java @@ -0,0 +1,134 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + +import java.util.HashMap; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: Pump Tool (support for Pump devices) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: PumpBolusType + * Description: Pump Bolus Types + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum PumpBolusType //implements CodeEnumWithTranslation +{ + None(0, "NONE"), // + Normal(1, "BOLUS_STANDARD"), // + Audio(2, "BOLUS_AUDIO"), // + Extended(3, "BOLUS_SQUARE", "AMOUNT_SQUARE=%s;DURATION=%s"), // + Multiwave(4, "BOLUS_MULTIWAVE", "AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s"); + + static String[] descriptions; + //static HashMap translationMapping = new HashMap(); + static HashMap codeMapping = new HashMap(); + private static boolean translated; + + static { + for(PumpBolusType pbt : values()) { + codeMapping.put(pbt.code, pbt); + } + } + + + // public static void translateKeywords(I18nControlAbstract ic) + // { + // if (translated) + // return; + // + // for (PumpBolusType pbt : values()) + // { + // pbt.setTranslation(ic.getMessage(pbt.i18nKey)); + // translationMapping.put(pbt.getTranslation(), pbt); + // } + // + // String[] bolusDescriptions = { ic.getMessage("SELECT_BOLUS_TYPE"), // + // ic.getMessage("BOLUS_STANDARD"), // + // ic.getMessage("BOLUS_AUDIO"), // + // ic.getMessage("BOLUS_SQUARE"), // + // ic.getMessage("BOLUS_MULTIWAVE"), }; + // + // descriptions = bolusDescriptions; + // + // translated = true; + // } + + int code; + String i18nKey; + String translation; + String valueTemplate; + + + PumpBolusType(int code, String i18nKey) { + this.code = code; + this.i18nKey = i18nKey; + } + + + PumpBolusType(int code, String i18nKey, String valueTemplate) { + this.code = code; + this.i18nKey = i18nKey; + this.valueTemplate = valueTemplate; + } + + + public String getTranslation() { + return translation; + } + + + public void setTranslation(String translation) { + this.translation = translation; + } + + + public int getCode() { + return code; + } + + + public String getI18nKey() { + return i18nKey; + } + + + public String getName() { + return this.name(); + } + + + public static PumpBolusType getByCode(int code) { + if (codeMapping.containsKey(code)) { + return codeMapping.get(code); + } else { + return PumpBolusType.None; + } + } + + + /** + * Get Descriptions (array) + * + * @return array of strings with description + */ + public static String[] getDescriptions() { + return descriptions; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpSettingDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpSettingDTO.java new file mode 100644 index 0000000000..a52abb2aaa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpSettingDTO.java @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpConfigurationGroup; + +/** + * Created by andy on 6/6/18. + */ + +public class PumpSettingDTO { + + public String key; + public String value; + + PumpConfigurationGroup configurationGroup; + + + public PumpSettingDTO(String key, String value, PumpConfigurationGroup configurationGroup) { + this.key = key; + this.value = value; + this.configurationGroup = configurationGroup; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpTimeStampedRecord.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpTimeStampedRecord.java new file mode 100644 index 0000000000..63bb17f4dd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/PumpTimeStampedRecord.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + +import org.joda.time.LocalDateTime; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; + +/** + * Created by andy on 6/2/18. + */ + +public class PumpTimeStampedRecord { + + protected LocalDateTime localDateTime; + protected int decimalPrecission = 2; + + + public void setLocalDateTime(LocalDateTime ATechDate) { + this.localDateTime = ATechDate; + } + + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + + public String getFormattedDecimal(double value) { + return StringUtil.getFormatedValueUS(value, this.decimalPrecission); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/TemporaryBasalRateDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/TemporaryBasalRateDTO.java new file mode 100644 index 0000000000..bd6d8d94a3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/data/dto/TemporaryBasalRateDTO.java @@ -0,0 +1,115 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto; + +import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: Pump Tool (support for Pump devices) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + *

+ * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: BolusDTO + * Description: Bolus DTO + *

+ * Author: Andy {andy@atech-software.com} + */ + +public class TemporaryBasalRateDTO extends PumpTimeStampedRecord { + + private Float amount; + private TBRUnit unit = TBRUnit.Percent; // percent, U + private Integer duration; // min + //private ATechDate aTechDate; + + + public TemporaryBasalRateDTO() { + //this.decimalPrecission = 2; + } + + + public Integer getDuration() { + return duration; + } + + + public void setDuration(Integer duration) { + this.duration = duration; + } + + + private String getDurationString() { + int minutes = this.duration; + + int h = minutes / 60; + + minutes -= (h * 60); + + return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2); + } + + + public String getValue() { + float val = amount; + String sign = ""; + + if (val < 0) { + sign = "-"; + val *= -1; + } + + return String.format("TBR_VALUE=%s%s;TBR_UNIT=%s;DURATION=%s", sign, getFormattedDecimal(val), getUnit().getDescription(), getDurationString()); + } + + + public Float getAmount() { + return amount; + } + + + public void setAmount(Float amount) { + this.amount = amount; + } + + + public TBRUnit getUnit() { + return unit; + } + + + public void setUnit(TBRUnit unit) { + this.unit = unit; + } + + + public enum TBRUnit { + Percent("%"), // + Unit("U"); + + String unit; + + + TBRUnit(String unit) { + this.unit = unit; + } + + + public String getDescription() { + return unit; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/BatteryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/BatteryType.java new file mode 100644 index 0000000000..2f13792735 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/BatteryType.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +/** + * Created by andy on 6/4/18. + */ + +public enum BatteryType { + + Alkaline(1.20f, 1.47f), // + Lithium(1.32f, 1.58f); + + public float lowVoltage; + public float highVoltage; + + + BatteryType(float lowVoltage, float highVoltage) { + this.lowVoltage = lowVoltage; + this.highVoltage = highVoltage; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java new file mode 100755 index 0000000000..9a0bf46b4c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java @@ -0,0 +1,436 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageBody; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpAckMessageBody; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.UnknownMessageBody; + + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Author: Andy {andy@atech-software.com} + */ + + +// FIXME: AAPS - a lot of this can be removed. Do cleanup. + +// Lot of stuff in here is legacy stuff for CareLink(1). We should remove it in +// future. +public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeInterface +{ + InvalidCommand(0, "Invalid Command", null, null, null), // + + // Pump Responses (9) + CommandACK(0x06, "ACK - Acknowledge", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + CommandNAK(0x15, "NAK - Not Acknowledged", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + // All (8) + PushAck(91, "Push ACK", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(2)), // + + PushEsc(91, "Push Esc", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), // + + PushButton(0x5b, "Push Button", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 91 + + RFPowerOn(93, "RF Power On", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1, 10)), // + + RFPowerOff(93, "RF Power Off", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(0, 0)), // + + SetSuspend(77, "Set Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), // + + CancelSuspend(77, "Cancel Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(0)), // + + PumpState(131, "Pump State", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + ReadPumpErrorStatus(117, "Pump Error Status", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + // 511 (InitCommand = 2, Config 7, Data = 1(+3) + DetectBolus(75, "Detect Bolus", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray(0, 0, 0)), // + + ReadTemporaryBasal_511(120, "Read Temporary Basal", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters), // + + RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + FirmwareVersion(116, "Firmware Version", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + PumpId(113, "Pump Id", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // init + + RealTimeClock(112, "Real Time Clock", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 7), // 0x70 + + GetBatteryStatus(0x72, "Get Battery Status", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + // GetBattery((byte) 0x72), // + + GetRemainingInsulin(0x73, "Read Remaining Insulin", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115 + + Settings_511(127, "Settings", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters), // + + HistoryData_511(128, "History data", MinimedTargetType.PumpData, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.SubCommands, 1024, 32, 0), // 0x80 + + Profile_STD_511(122, "Profile Standard", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 8), // FIXME_ + + Profile_A_511(123, "Profile A", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 9), // FIXME_ + + Profile_B_511(124, "Profile B", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 10), // FIXME_ + + SetBolus(0x42, "Set Bolus", MinimedTargetType.PumpSetData, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 66 + + + // 512 + ReadTemporaryBasal(0x98, "Read Temporary Basal", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 5), // 152 + + SetTemporaryBasal(76, "Set Temp Basal Rate (bolus detection only)", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, getByteArray(0, 0, 0)), + // util.getCommand(MinimedCommand.SET_TEMPORARY_BASAL).allowedRetries + // = 0; + + // 512 Config + PumpModel(141, "Pump Model", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 5), // 0x8D + + BGTargets_512(140, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712, MinimedCommandParameterType.NoParameters), // + + BGUnits(137, "BG Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + Language(134, "Language", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + Settings_512(145, "Settings", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712, MinimedCommandParameterType.NoParameters), // + + BGAlarmClocks(142, "BG Alarm Clocks", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + BGAlarmEnable(151, "BG Alarm Enable", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + BGReminderEnable(144, "BG Reminder Enable", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + ReadInsulinSensitivities(0x8b, "Read Insulin Sensitivities", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // 139 + + // 512 Data + GetHistoryData(128, "History data", MinimedTargetType.PumpData, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.SubCommands, 1024, 36, 0), // 0x80 + // new MinimedCommandHistoryData(36) + + GetBasalProfileSTD(146, "Get Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8, 7), // 146 FIXME + + GetBasalProfileA(147, "Get Profile A", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 9), // 147 FIXME + + GetBasalProfileB(148, "Get Profile B", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 10), // 148 FIXME + + SetBasalProfileSTD(0x6f, "Set Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 111 + + SetBasalProfileA(0x30, "Set Profile A", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 48 + + SetBasalProfileB(0x31, "Set Profile B", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 49 + + BolusWizardSetupStatus(135, "Bolus Wizard Setup Status", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + GetCarbohydrateRatios(0x8a, "Get Carbohydrate Ratios", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // 138 + + CarbohydrateUnits(136, "Carbohydrate Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + // 515 + PumpStatus(206, "Pump Status", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // PumpConfiguration + + Settings(192, "Settings", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // + + BGTargets(159, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // + + MissedBolusReminderEnable(197, "Missed Bolus Reminder Enable", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // + + MissedBolusReminders(198, "Missed Bolus Reminder", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // + + // 522 + CalibrationFactor(156, "Calibration Factor", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), // + + SensorSettings_522(153, "Sensor Settings", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_522_722, MinimedCommandParameterType.NoParameters), // + + GlucoseHistory(154, "Glucose History", MinimedTargetType.CGMSData, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0), // + + ISIGHistory(155, "Isig History", MinimedTargetType.CGMSData_NA, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 2048, 32, 0), // + + // 523 + SensorPredictiveAlerts(209, "Sensor Predictive Alerts", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + SensorRateOfChangeAlerts(212, "Sensor Rate Of Change Alerts", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + SensorDemoAndGraphTimeout(210, "Sensor Demo and Graph Timeout", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + SensorAlarmSilence(211, "Sensor Alarm Silence", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + SensorSettings(207, "Sensor Settings", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + OtherDevicesIds(240, "Other Devices ID", MinimedTargetType.CGMSConfiguration_NA, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + VCntrHistory(213, "Vcntr History", MinimedTargetType.CGMSData_NA, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0), // + + // 553 + // 554 + + // var MESSAGES = { + // READ_TIME : 0x70, + // READ_BATTERY_STATUS: 0x72, + // READ_HISTORY : 0x80, + // READ_CARB_RATIOS : 0x8A, + // READ_INSULIN_SENSITIVITIES: 0x8B, + // READ_MODEL : 0x8D, + // READ_PROFILE_STD : 0x92, + // READ_PROFILE_A : 0x93, + // READ_PROFILE_B : 0x94, + // READ_CBG_HISTORY: 0x9A, + // READ_ISIG_HISTORY: 0x9B, + // READ_CURRENT_PAGE : 0x9D, + // READ_BG_TARGETS : 0x9F, + // READ_SETTINGS : 0xC0, 192 + // READ_CURRENT_CBG_PAGE : 0xCD + // }; + + ; + + public byte commandCode = 0; + private int recordLength = 64; + + MinimedTargetType targetType; + MedtronicDeviceType devices; + + public String commandDescription = ""; + + public byte[] commandParameters = null; + public int commandParametersCount = 0; + + public int maxRecords = 1; + public int command_type = 0; + public int allowedRetries = 2; + public int maxAllowedTime = 2000; + public MinimedCommandParameterType parameterType; + public int minimalBufferSizeToStartReading = 14; + public int expectedLength = 0; + + static Map mapByCode; + + + static { + MedtronicCommandType.RFPowerOn.maxAllowedTime = 17000; + MedtronicCommandType.RFPowerOn.allowedRetries = 0; + MedtronicCommandType.RFPowerOn.recordLength = 0; + MedtronicCommandType.RFPowerOn.minimalBufferSizeToStartReading = 1; + + mapByCode = new HashMap<>(); + + for(MedtronicCommandType medtronicCommandType : values()) { + mapByCode.put(medtronicCommandType.getCommandCode(), medtronicCommandType); + } + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType) { + this(code, description, targetType, devices, parameterType, 64, 1, 0, 0, 0, 0); + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, int expectedLength) { + this(code, description, targetType, devices, parameterType, 64, 1, 0, 0, 0, expectedLength); + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) { + this(code, description, targetType, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, 0); + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType, int expectedLength) { + this(code, description, targetType, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, expectedLength); + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, byte[] cmd_params) { + this(code, description, targetType, devices, parameterType, 0, 1, 0, 0, 11, 0); + + this.commandParameters = cmd_params; + this.commandParametersCount = cmd_params.length; + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, byte[] cmd_params, int expectedLength) { + this(code, description, targetType, devices, parameterType, 0, 1, 0, 0, 11, expectedLength); + + this.commandParameters = cmd_params; + this.commandParametersCount = cmd_params.length; + } + + + MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, // + int addy_len, int cmd_type, int expectedLength + ) { + this.commandCode = (byte) code; + this.commandDescription = description; + this.targetType = targetType; + this.devices = devices; + this.recordLength = recordLength; + this.maxRecords = max_recs; + + this.command_type = cmd_type; + this.commandParametersCount = 0; + this.allowedRetries = 2; + this.parameterType = parameterType; + this.expectedLength = expectedLength; + + if (this.parameterType == MinimedCommandParameterType.SubCommands) { + this.minimalBufferSizeToStartReading = 200; + } + + } + + + private static HashMap getDeviceTypesArray(MedtronicDeviceType... types) { + HashMap hashMap = new HashMap(); + + for(MedtronicDeviceType type : types) { + hashMap.put(type, null); + } + + return hashMap; + } + + + private static byte[] getByteArray(int... data) { + byte[] array = new byte[data.length]; + + for(int i = 0; i < data.length; i++) { + array[i] = (byte) data[i]; + } + + return array; + } + + + private static int[] getIntArray(int... data) { + return data; + } + + + public static MedtronicCommandType getReadTemporaryBasal(MedtronicDeviceType device) { + if (device == MedtronicDeviceType.Medtronic_511) { + return MedtronicCommandType.ReadTemporaryBasal_511; + } else { + return MedtronicCommandType.ReadTemporaryBasal; + } + } + + + public static MedtronicCommandType getDetectBolus(MedtronicDeviceType device) { + if (device == MedtronicDeviceType.Medtronic_511) { + return MedtronicCommandType.DetectBolus; + } else { + return MedtronicCommandType.SetTemporaryBasal; + } + } + + + // public static List getCommands(MedtronicDeviceType device, MinimedTargetType targetType) + // { + // List commands = new ArrayList(); + // + // for (MedtronicCommandType mct : values()) + // { + // + // if ((mct.targetType == targetType) + // && ((MedtronicDeviceType.isSameDevice(device, mct.devices)) || mct.devices == MedtronicDeviceType.All)) + // { + // commands.add(mct); + // } + // } + // + // return commands; + // } + + + public static MedtronicCommandType getByCode(byte code) { + if (mapByCode.containsKey(code)) { + return mapByCode.get(code); + } else { + return MedtronicCommandType.InvalidCommand; + } + } + + + /** + * Get Full Command Description + * + * @return command description + */ + public String getFullCommandDescription() { + return "Command [name=" + this.name() + ", id=" + this.commandCode + ",description=" + this.commandDescription + "] "; + } + + + public boolean canReturnData() { + System.out.println("CanReturnData: ]id=" + this.name() + "max=" + this.maxRecords + "recLen=" + recordLength); + return (this.maxRecords * this.recordLength) > 0; + } + + + public int getRecordLength() { + return recordLength; + } + + + public int getMaxRecords() { + return maxRecords; + } + + + public byte getCommandCode() { + return commandCode; + } + + + public int getCommandParametersCount() { + if (this.commandParameters == null) { + return 0; + } else { + return this.commandParameters.length; + } + } + + + public byte[] getCommandParameters() { + return commandParameters; + } + + + public boolean hasCommandParameters() { + return (getCommandParametersCount() > 0); + } + + + public static MessageBody constructMessageBody(MedtronicCommandType messageType, byte[] bodyData) { + switch (messageType) { + case CommandACK: + return new PumpAckMessageBody(bodyData); + default: + return new UnknownMessageBody(bodyData); + } + } + + + public static MedtronicCommandType getSettings(MedtronicDeviceType medtronicPumpModel) { + if (medtronicPumpModel == MedtronicDeviceType.Medtronic_511) + return MedtronicCommandType.Settings_511; + else if (MedtronicDeviceType.isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712)) + return MedtronicCommandType.Settings_512; + else + return MedtronicCommandType.Settings; + } + + + public enum MinimedCommandParameterType { + NoParameters, // + FixedParameters, // + SubCommands // + } + + + public String toString() { + return name(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicConverterType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicConverterType.java new file mode 100644 index 0000000000..32acbc2935 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicConverterType.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum MedtronicConverterType { + Pump511Converter, // + Pump512Converter, // + Pump515Converter, // + Pump523Converter, // + + CGMS522Converter, // + CGMS523Converter, // + + ; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicDeviceType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicDeviceType.java new file mode 100644 index 0000000000..045a4faadd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicDeviceType.java @@ -0,0 +1,151 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +import java.util.HashMap; +import java.util.Map; + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum MedtronicDeviceType { + Unknown_Device, // + + // Pump + //Medtronic_508_508c(null, null), // + Medtronic_511(MedtronicConverterType.Pump511Converter, null, "511"), // + + Medtronic_512(MedtronicConverterType.Pump512Converter, null, "512"), // + Medtronic_712(MedtronicConverterType.Pump512Converter, null, "712"), // + Medtronic_512_712(Medtronic_512, Medtronic_712), // + + Medtronic_515(MedtronicConverterType.Pump515Converter, null, "515"), // + Medtronic_715(MedtronicConverterType.Pump515Converter, null, "715"), // + Medtronic_515_715(Medtronic_515, Medtronic_715), // + + Medtronic_522(MedtronicConverterType.Pump515Converter, MedtronicConverterType.CGMS522Converter, "522"), // + Medtronic_722(MedtronicConverterType.Pump515Converter, MedtronicConverterType.CGMS522Converter, "722"), // + Medtronic_522_722(Medtronic_522, Medtronic_722), // + + Medtronic_523(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "523"), // + Medtronic_723(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "723"), // + + Medtronic_553_Revel(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "553"), // + Medtronic_753_Revel(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "753"), // + + Medtronic_554_Veo(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "554"), // + Medtronic_754_Veo(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "754"), // + //Minimed_640G(MedtronicConverterType.Pump523Converter, MedtronicConverterType.CGMS523Converter, "640G", null), + + Medtronic_512andHigher(Medtronic_512, Medtronic_712, Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, // + Medtronic_523, Medtronic_723, Medtronic_553_Revel, Medtronic_753_Revel, Medtronic_554_Veo, Medtronic_754_Veo), // + + Medtronic_515andHigher(Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523, Medtronic_723, // + Medtronic_553_Revel, Medtronic_753_Revel, Medtronic_554_Veo, Medtronic_754_Veo), // + Medtronic_522andHigher(Medtronic_522, Medtronic_722, Medtronic_523, Medtronic_723, Medtronic_553_Revel, Medtronic_753_Revel, // + Medtronic_554_Veo, Medtronic_754_Veo), // + Medtronic_523andHigher(Medtronic_523, Medtronic_723, Medtronic_553_Revel, Medtronic_753_Revel, Medtronic_554_Veo, // + Medtronic_754_Veo), // + + Medtronic_553andHigher(Medtronic_553_Revel, Medtronic_753_Revel, Medtronic_554_Veo, Medtronic_754_Veo), // + Medtronic_554andHigher(Medtronic_554_Veo, Medtronic_754_Veo), // + + // CGMS + MedtronicCGMSGold(null, MedtronicConverterType.CGMS522Converter, null), // + + MedtronicGuradianRealTime(null, MedtronicConverterType.CGMS522Converter, null), // + + // + All; + + private String pumpModel; + private boolean isFamily; + private MedtronicDeviceType[] familyMembers = null; + + + MedtronicConverterType pumpConverter; + MedtronicConverterType cgmsConverter; + + //String smallReservoirPump; + //String bigReservoirPump; + + static Map mapByDescription; + + static { + + mapByDescription = new HashMap<>(); + + for(MedtronicDeviceType minimedDeviceType : values()) { + + if (!minimedDeviceType.isFamily) { + mapByDescription.put(minimedDeviceType.pumpModel, minimedDeviceType); + } + } + + } + + + MedtronicDeviceType(MedtronicConverterType pumpConverter, MedtronicConverterType cgmsConverter, String pumpModel) { + this.isFamily = false; + this.pumpConverter = pumpConverter; + this.cgmsConverter = cgmsConverter; + + this.pumpModel = pumpModel; + //this.bigReservoirPump = bigReservoirPump; + } + + + MedtronicDeviceType(MedtronicDeviceType... familyMembers) { + this.familyMembers = familyMembers; + this.isFamily = true; + } + + + public static boolean isSameDevice(MedtronicDeviceType deviceWeCheck, MedtronicDeviceType deviceSources) { + if (deviceSources.isFamily) { + for(MedtronicDeviceType mdt : deviceSources.familyMembers) { + if (mdt == deviceWeCheck) + return true; + } + } else { + return (deviceWeCheck == deviceSources); + } + + return false; + } + + + public boolean isFamily() { + return isFamily; + } + + + public MedtronicDeviceType[] getFamilyMembers() { + return familyMembers; + } + + + public MedtronicConverterType getCGMSConverterType() { + return cgmsConverter; + } + + + public MedtronicConverterType getPumpConverterType() { + return pumpConverter; + } + + + public static MedtronicDeviceType getByDescription(String desc) { + if (mapByDescription.containsKey(desc)) { + return mapByDescription.get(desc); + } else { + return MedtronicDeviceType.Unknown_Device; + } + } + + + public static boolean isLargerFormat(MedtronicDeviceType model) { + return isSameDevice(model, Medtronic_523andHigher); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MinimedTargetType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MinimedTargetType.java new file mode 100644 index 0000000000..dce297bf21 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MinimedTargetType.java @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum MinimedTargetType { + ActionCommand, // + InitCommand, + + PumpConfiguration, // + PumpData, // + PumpSetData, // + PumpConfiguration_NA, // + PumpData_NA, // + + PumpDataAndConfiguration, // + CGMSConfiguration, // + CGMSData, // + + BaseCommand, // + + Pump, // + CGMS, // + + CGMSData_NA, // + CGMSConfiguration_NA; + + + MinimedTargetType() { + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/PumpConfigurationGroup.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/PumpConfigurationGroup.java new file mode 100644 index 0000000000..b2e2c984e0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/PumpConfigurationGroup.java @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.defs; + +/** + * Created by andy on 27.02.15. + */ +public enum PumpConfigurationGroup { + General(1, "GROUP_GENERAL"), // + Device(2, "GROUP_DEVICE"), // + + Insulin(3, "GROUP_INSULIN"), // + + Basal(4, "GROUP_BASAL"), // + Bolus(5, "GROUP_BOLUS"), // + Sound(6, "GROUP_SOUND"), // + + Other(20, "GROUP_OTHER"), // + + UnknownGroup(21, "GROUP_UNKNOWN"), // + + ; // + + int code; + String i18nKey; + String translation; + static boolean translated; + + + PumpConfigurationGroup(int code, String i18nKey) { + this.code = code; + this.i18nKey = i18nKey; + } + + + public String getTranslation() { + return translation; + } + + + public void setTranslation(String translation) { + this.translation = translation; + } + + + public int getCode() { + return code; + } + + + public String getI18nKey() { + return i18nKey; + } + + + public String getName() { + return this.name(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java index e7317fb351..78000033a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.driver; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,14 +44,17 @@ public class MedtronicPumpStatus extends PumpStatus { // fixme + public long getTimeIndex() { return (long) Math.ceil(time.getTime() / 60000d); } + public void setTimeIndex(long timeIndex) { this.timeIndex = timeIndex; } + public long timeIndex; public Date time; @@ -84,10 +88,10 @@ public class MedtronicPumpStatus extends PumpStatus { this.reservoirRemainingUnits = 75d; this.batteryRemaining = 75; - if (this.medtronicPumpMap == null) - createMedtronicPumpMap(); + if (this.medtronicPumpMap == null) createMedtronicPumpMap(); } + private void createMedtronicPumpMap() { medtronicPumpMap = new HashMap<>(); @@ -113,8 +117,7 @@ public class MedtronicPumpStatus extends PumpStatus { try { // FIXME don't reload information several times - if (this.medtronicPumpMap == null) - createMedtronicPumpMap(); + if (this.medtronicPumpMap == null) createMedtronicPumpMap(); this.errorDescription = null; @@ -157,10 +160,8 @@ public class MedtronicPumpStatus extends PumpStatus { RileyLinkUtil.setPumpStatus(this); - if (pumpTypePart.startsWith("7")) - this.reservoirFullUnits = "300"; - else - this.reservoirFullUnits = "180"; + if (pumpTypePart.startsWith("7")) this.reservoirFullUnits = "300"; + else this.reservoirFullUnits = "180"; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicNewStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicNewStatus.java index 727f758884..1489529995 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicNewStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicNewStatus.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.events; import info.nightscout.androidaps.events.Event; /** - * Created by mike on 08.07.2016. + * Created by andy on 04.06.2018. */ public class EventMedtronicNewStatus extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicRileyLinkStatusChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicRileyLinkStatusChange.java new file mode 100644 index 0000000000..4b8683c966 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/events/EventMedtronicRileyLinkStatusChange.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.events; + +import info.nightscout.androidaps.events.Event; + +/** + * Created by andy on 04.06.2018. + */ +public class EventMedtronicRileyLinkStatusChange extends Event { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/medtronic/defs/MedtronicPumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/medtronic/defs/MedtronicPumpType.java deleted file mode 100644 index 49e3f6dfa7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/medtronic/defs/MedtronicPumpType.java +++ /dev/null @@ -1,144 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpMedtronic.medtronic.defs; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by andy on 4/28/18. - */ - -public enum MedtronicPumpType { - - Unknown("xxx", 0.1f, 0.1f, 200, 35.0d, 0), - Medtronic_512("512", 0.05f, 0.1f, 200, 35.0d, 180), - Medtronic_712("712", 0.05f, 0.1f, 200, 35.0d, 300), - - Medtronic_515("515", 0.05f, 0.1f, 200, 35.0d, 180), - Medtronic_715("715", 0.05f, 0.1f, 200, 35.0d, 300), - Medtronic_522("522", 0.05f, 0.1f, 200, 35.0d, 180), - Medtronic_722("722", 0.05f, 0.1f, 200, 35.0d, 300), - - Medtronic_523("523", 0.1f, 0.1f, 200, 35.0d, 180), - Medtronic_723("723", 0.1f, 0.1f, 200, 35.0d, 300), - Medtronic_554("554", 0.1f, 0.1f, 200, 35.0d, 180), - Medtronic_754("754", 0.1f, 0.1f, 200, 35.0d, 300), - ; - - //0.025 units (for rates between 0.025-0.975 u/h) - //0.05 units (for rates between 1-9.95 u/h) - //0.1 units (for rates of 10 u/h or more); (or 1%) - - -// -// -// Minimed_511(10003, "Minimed 511", "mm_515_715.jpg", "INSTRUCTIONS_MINIMED", MinimedDeviceType.Minimed_511, -// DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, DeviceHandlerType.MinimedPumpHandler, -// DevicePortParameterType.PackedParameters, DeviceConnectionProtocol.Serial_USBBridge, -// DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_512_712(10004, "Minimed 512/712", "mm_515_715.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_512_712, DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, -// DeviceHandlerType.MinimedPumpHandler, DevicePortParameterType.PackedParameters, -// DeviceConnectionProtocol.USB_Hid, DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, -// PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_515_715(10005, "Minimed 515/715", "mm_515_715.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_515_715, DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, -// DeviceHandlerType.MinimedPumpHandler, DevicePortParameterType.PackedParameters, -// DeviceConnectionProtocol.Serial_USBBridge, DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, -// PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_522_722(10006, "Minimed 522/722", "mm_522_722.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_522_722, DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, -// DeviceHandlerType.MinimedPumpHandler, DevicePortParameterType.PackedParameters, -// DeviceConnectionProtocol.Serial_USBBridge, DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, -// PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_523_723(10007, "Minimed 523/723", "mm_522_722.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_523_723, DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, -// DeviceHandlerType.MinimedPumpHandler, DevicePortParameterType.PackedParameters, -// DeviceConnectionProtocol.Serial_USBBridge, DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, -// PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_553_753_Revel(10008, "Minimed 553/753 (Revel)", "mm_554_veo.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_553_753_Revel, DeviceImplementationStatus.Planned, -// DeviceCompanyDefinition.Minimed, DeviceHandlerType.MinimedPumpHandler, -// DevicePortParameterType.PackedParameters, DeviceConnectionProtocol.Serial_USBBridge, -// DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, PumpProfileDefinition.MinimedProfile), // TODO -// -// Minimed_554_754_Veo(10009, "Minimed 554/754 (Veo)", "mm_554_veo.jpg", "INSTRUCTIONS_MINIMED", -// MinimedDeviceType.Minimed_554_754_Veo, DeviceImplementationStatus.Planned, DeviceCompanyDefinition.Minimed, -// DeviceHandlerType.MinimedPumpHandler, DevicePortParameterType.PackedParameters, -// DeviceConnectionProtocol.Serial_USBBridge, DeviceProgressStatus.Special, "", 0.1f, 0.1f, null, -1, 0, -// PumpProfileDefinition.MinimedProfile), // TODO -// - - - - - - private static Map mapByCode; - - private String code; - private int reservoir; - private double basalStep; - private double bolusStep; - private int maxTbrPercent; - private double maxTbrUnit; - - static - { - mapByCode = new HashMap<>(); - - for (MedtronicPumpType medtronicPumpType : values()) { - mapByCode.put(medtronicPumpType.getCode(), medtronicPumpType); - } - } - - MedtronicPumpType(String code, double basalStep, double bolusStep, int maxTbrPercent, double maxTbrUnit, int reservoir) - { - this.code = code; - this.reservoir = reservoir; - this.basalStep = basalStep; - this.bolusStep = bolusStep; - this.maxTbrPercent = maxTbrPercent; - this.maxTbrUnit = maxTbrUnit; - } - - - public static MedtronicPumpType getByCode(String code) { - - if (mapByCode.containsKey(code)) - { - return mapByCode.get(code); - } - else - { - return MedtronicPumpType.Unknown; - } - } - - public String getCode() { - return code; - } - - public int getReservoir() { - return reservoir; - } - - public double getBasalStep() { - return basalStep; - } - - public double getBolusStep() { - return bolusStep; - } - - public int getMaxTbrPercent() { - return maxTbrPercent; - } - - public double getMaxTbrUnit() { - return maxTbrUnit; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java index 8df07b5165..38e3258392 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java @@ -5,15 +5,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.os.Binder; -import android.os.Bundle; import android.os.IBinder; -import com.gxwtech.roundtrip2.RT2Const; -import com.gxwtech.roundtrip2.RoundtripService.Tasks.ServiceTask; -import com.gxwtech.roundtrip2.ServiceData.ServiceNotification; -import com.gxwtech.roundtrip2.ServiceData.ServiceResult; -import com.gxwtech.roundtrip2.ServiceData.ServiceTransport; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,12 +14,22 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.plugins.PumpCommon.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkService; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceNotification; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager; @@ -61,10 +64,10 @@ public class RileyLinkMedtronicService extends RileyLinkService { public RileyLinkMedtronicService() { - super(); + super(MainApp.instance().getApplicationContext()); instance = this; LOG.debug("RileyLinkMedtronicService newly constructed"); - + RileyLinkUtil.setRileyLinkService(this); pumpStatus = (MedtronicPumpStatus) MedtronicPumpPlugin.getPlugin().getPumpStatusData(); } @@ -80,15 +83,15 @@ public class RileyLinkMedtronicService extends RileyLinkService { public void addPumpSpecificIntents(IntentFilter intentFilter) { - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_fetchHistory); - intentFilter.addAction(RT2Const.IPC.MSG_PUMP_fetchSavedHistory); + intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_fetchHistory); + intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_fetchSavedHistory); } public void handlePumpSpecificIntents(Intent intent) { String action = intent.getAction(); - if (action.equals(RT2Const.IPC.MSG_PUMP_fetchHistory)) { + if (action.equals(RileyLinkConst.IPC.MSG_PUMP_fetchHistory)) { // mHistoryPages = medtronicCommunicationManager.getAllHistoryPages(); // final boolean savePages = true; @@ -135,7 +138,7 @@ public class RileyLinkMedtronicService extends RileyLinkService { // msg.setData(bundle); // //rileyLinkIPCConnection.sendMessage(msg, null/*broadcast*/); // LOG.debug("sendMessage: sent Full history report"); - } else if (RT2Const.IPC.MSG_PUMP_fetchSavedHistory.equals(action)) { + } else if (RileyLinkConst.IPC.MSG_PUMP_fetchSavedHistory.equals(action)) { LOG.info("Fetching saved history"); // FileInputStream inputStream; // ArrayList storedHistoryPages = new ArrayList<>(); @@ -210,16 +213,40 @@ public class RileyLinkMedtronicService extends RileyLinkService { } + @Override + protected void determineRileyLinkTargetFrequency() { + boolean hasUSFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency, MainApp.gs(R.string.medtronic_pump_frequency_us)).equals(MainApp.gs(R.string.medtronic_pump_frequency_us)); + + if (hasUSFrequency) + this.rileyLinkTargetFrequency = RileyLinkTargetFrequency.Medtronic_US; + else + this.rileyLinkTargetFrequency = RileyLinkTargetFrequency.Medtronic_WorldWide; + } + + /** * If you have customized RileyLinkServiceData you need to override this */ public void initRileyLinkServiceData() { + rileyLinkServiceData = new RileyLinkServiceData(RileyLinkTargetDevice.MedtronicPump); + RileyLinkUtil.setRileyLinkServiceData(rileyLinkServiceData); + setPumpIDString(SP.getString(MedtronicConst.Prefs.PumpSerial, "000000")); + // get most recently used RileyLink address + rileyLinkServiceData.rileylinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, ""); + + rileyLinkBLE = new RileyLinkBLE(this.context); // or this + rfspy = new RFSpy(rileyLinkBLE); + rfspy.startReader(); + + RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); + + // init rileyLinkCommunicationManager - pumpCommunicationManager = new MedtronicCommunicationManager(context, rfspy, false, rileyLinkServiceData.pumpIDBytes); + pumpCommunicationManager = new MedtronicCommunicationManager(context, rfspy, rileyLinkTargetFrequency); medtronicCommunicationManager = (MedtronicCommunicationManager) pumpCommunicationManager; @@ -229,6 +256,9 @@ public class RileyLinkMedtronicService extends RileyLinkService { } + public MedtronicCommunicationManager getMedtronicCommunicationManager() { + return this.medtronicCommunicationManager; + } /* private functions */ @@ -300,86 +330,87 @@ public class RileyLinkMedtronicService extends RileyLinkService { public void handleIncomingServiceTransport(Intent intent) { - Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); - - ServiceTransport serviceTransport = new ServiceTransport(bundle); - - if (serviceTransport.getServiceCommand().isPumpCommand()) { - switch (serviceTransport.getOriginalCommandName()) { - case "ReadPumpClock": - //ServiceTaskExecutor.startTask(new ReadPumpClockTask(serviceTransport)); - break; - case "FetchPumpHistory": - //ServiceTaskExecutor.startTask(new FetchPumpHistoryTask(serviceTransport)); - break; - case "RetrieveHistoryPage": - //ServiceTask task = new RetrieveHistoryPageTask(serviceTransport); - //ServiceTaskExecutor.startTask(task); - break; - case "ReadISFProfile": - //ServiceTaskExecutor.startTask(new ReadISFProfileTask(serviceTransport)); - /* - ISFTable table = pumpCommunicationManager.getPumpISFProfile(); - ServiceResult result = new ServiceResult(); - if (table.isValid()) { - // convert from ISFTable to ISFProfile - Bundle map = result.getMap(); - map.putIntArray("times", table.getTimes()); - map.putFloatArray("rates", table.getRates()); - map.putString("ValidDate", TimeFormat.standardFormatter().print(table.getValidDate())); - result.setMap(map); - result.setResultOK(); - } - sendServiceTransportResponse(serviceTransport,result); - */ - break; - case "ReadBolusWizardCarbProfile": - //ServiceTaskExecutor.startTask(new ReadBolusWizardCarbProfileTask()); - break; - case "UpdatePumpStatus": - //ServiceTaskExecutor.startTask(new UpdatePumpStatusTask()); - break; - case "WakeAndTune": - //sServiceTaskExecutor.startTask(new WakeAndTuneTask()); - default: - LOG.error("Failed to handle pump command: " + serviceTransport.getOriginalCommandName()); - break; - } - } else { - switch (serviceTransport.getOriginalCommandName()) { - case "SetPumpID": - // This one is a command to RileyLinkMedtronicService, not to the MedtronicCommunicationManager - String pumpID = serviceTransport.getServiceCommand().getMap().getString("pumpID", ""); - ServiceResult result = new ServiceResult(); - if ((pumpID != null) && (pumpID.length() == 6)) { - setPumpIDString(pumpID); - result.setResultOK(); - } else { - LOG.error("handleIncomingServiceTransport: SetPumpID bundle missing 'pumpID' value"); - result.setResultError(-1, "Invalid parameter (missing pumpID)"); - } - sendServiceTransportResponse(serviceTransport, result); - break; - case "UseThisRileylink": - // If we are not connected, connect using the given address. - // If we are connected and the addresses differ, disconnect, connect to new. - // If we are connected and the addresses are the same, ignore. - String deviceAddress = serviceTransport.getServiceCommand().getMap().getString("rlAddress", ""); - if ("".equals(deviceAddress)) { - LOG.error("handleIPCMessage: null RL address passed"); - } else { - reconfigureRileylink(deviceAddress); - } - break; - default: - LOG.error("handleIncomingServiceTransport: Failed to handle service command '" + serviceTransport.getOriginalCommandName() + "'"); - break; - } - } +// Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); +// +// ServiceTransport serviceTransport = new ServiceTransport(bundle); +// +// if (serviceTransport.getServiceCommand().isPumpCommand()) { +// switch (serviceTransport.getOriginalCommandName()) { +// case "ReadPumpClock": +// ServiceTaskExecutor.startTask(new ReadPumpClockTask(serviceTransport)); +// break; +// case "FetchPumpHistory": +// ServiceTaskExecutor.startTask(new FetchPumpHistoryTask(serviceTransport)); +// break; +// case "RetrieveHistoryPage": +// ServiceTask task = new RetrieveHistoryPageTask(serviceTransport); +// ServiceTaskExecutor.startTask(task); +// break; +// case "ReadISFProfile": +// ServiceTaskExecutor.startTask(new ReadISFProfileTask(serviceTransport)); +// /* +// ISFTable table = pumpCommunicationManager.getPumpISFProfile(); +// ServiceResult result = new ServiceResult(); +// if (table.isValid()) { +// // convert from ISFTable to ISFProfile +// Bundle map = result.getMap(); +// map.putIntArray("times", table.getTimes()); +// map.putFloatArray("rates", table.getRates()); +// map.putString("ValidDate", TimeFormat.standardFormatter().print(table.getValidDate())); +// result.setMap(map); +// result.setResultOK(); +// } +// sendServiceTransportResponse(serviceTransport,result); +// */ +// break; +// case "ReadBolusWizardCarbProfile": +// ServiceTaskExecutor.startTask(new ReadBolusWizardCarbProfileTask()); +// break; +// case "UpdatePumpStatus": +// ServiceTaskExecutor.startTask(new UpdatePumpStatusTask()); +// break; +// case "WakeAndTune": +// ServiceTaskExecutor.startTask(new WakeAndTuneTask()); +// default: +// LOG.error("Failed to handle pump command: " + serviceTransport.getOriginalCommandName()); +// break; +// } +// } else { +// switch (serviceTransport.getOriginalCommandName()) { +// case "SetPumpID": +// // This one is a command to RileyLinkMedtronicService, not to the MedtronicCommunicationManager +// String pumpID = serviceTransport.getServiceCommand().getMap().getString("pumpID", ""); +// ServiceResult result = new ServiceResult(); +// if ((pumpID != null) && (pumpID.length() == 6)) { +// setPumpIDString(pumpID); +// result.setResultOK(); +// } else { +// LOG.error("handleIncomingServiceTransport: SetPumpID bundle missing 'pumpID' value"); +// result.setResultError(-1, "Invalid parameter (missing pumpID)"); +// } +// sendServiceTransportResponse(serviceTransport, result); +// break; +// case "UseThisRileylink": +// // If we are not connected, connect using the given address. +// // If we are connected and the addresses differ, disconnect, connect to new. +// // If we are connected and the addresses are the same, ignore. +// String deviceAddress = serviceTransport.getServiceCommand().getMap().getString("rlAddress", ""); +// if ("".equals(deviceAddress)) { +// LOG.error("handleIPCMessage: null RL address passed"); +// } else { +// reconfigureRileylink(deviceAddress); +// } +// break; +// default: +// LOG.error("handleIncomingServiceTransport: Failed to handle service command '" + serviceTransport.getOriginalCommandName() + "'"); +// break; +// } +// } } public void announceProgress(int progressPercent) { + /* if (currentTask != null) { ServiceNotification note = new ServiceNotification(RT2Const.IPC.MSG_note_TaskProgress); note.getMap().putInt("progress", progressPercent); @@ -388,7 +419,7 @@ public class RileyLinkMedtronicService extends RileyLinkService { //rileyLinkIPCConnection.sendNotification(note, senderHashcode); } else { LOG.error("announceProgress: No current task"); - } + }*/ } @@ -412,6 +443,9 @@ public class RileyLinkMedtronicService extends RileyLinkService { // PumpInterface + public boolean isInitialized() { + return RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState); + } public boolean isSuspended() { return false; @@ -422,6 +456,32 @@ public class RileyLinkMedtronicService extends RileyLinkService { } + public boolean isConnected() { + return RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState); + } + + + public boolean isConnecting() { + return !RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState); + } + + + public void connect(String reason) { + //bluetoothInit(); // this starts chain-loading connection + } + + + public void disconnect(String reason) { + + } + + + public void stopConnecting() { + + } + + + // FIXME to do 1st command public void getPumpStatus() { } @@ -472,6 +532,15 @@ public class RileyLinkMedtronicService extends RileyLinkService { return null; } + public MedtronicCommunicationManager getPumpManager() { + return this.medtronicCommunicationManager; + } + + // FIXME remove + public void sendNotification(ServiceNotification serviceNotification, Object o) { + LOG.warn("Send Notification has no implementation."); + } + public class LocalBinder extends Binder { public RileyLinkMedtronicService getServiceInstance() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/data/MedtronicPumpResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/data/MedtronicPumpResult.java new file mode 100644 index 0000000000..1c922d886d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/data/MedtronicPumpResult.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.service.data; + +import android.os.Bundle; + +import org.joda.time.LocalDateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; + +/** + * Created by geoff on 6/25/16. + */ +public class MedtronicPumpResult extends ServiceResult { + //private static final String TAG = "ReadPumpClockResult"; + //Map resultMap = new HashMap<>(); + private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpResult.class); + + + public MedtronicPumpResult(MedtronicCommandType commandType) { + map.putString("ServiceMessageType", commandType.name()); + } + + + @Override + public void init() { + } + + + public void addParameter(String parameter, String value) { + map.putString(parameter, value); + } + + + public void addParameter(String parameter, Float value) { + map.putFloat(parameter, value); + } + + + public void setError() { + map.putBoolean("Error", true); + } + + +// public void addParameter(String parameter, String value) +// { +// map.put(parameter, value); +// } + + +// public void setTime(LocalDateTime pumpTime) { +// Bundle map = getMap(); +// DateTimeFormatter fmt = DateTimeFormat.forStyle("FF"); +// map.putString("PumpTime", fmt.print(pumpTime)); +// setMap(map); +// } + + + public void addParameter(String key, LocalDateTime time) { + DateTimeFormatter fmt = DateTimeFormat.forStyle("FF"); + map.putString(key, fmt.print(time)); + } + + + public LocalDateTime getTimeParameter(String key) { + LocalDateTime rval = new LocalDateTime(1900, 1, 1, 1, 1); + Bundle map = getMap(); + if (map != null) { + String timeString = map.getString(key); + if (timeString != null) { + DateTimeFormatter fmt = DateTimeFormat.forStyle("FF"); + try { + rval = fmt.parseLocalDateTime(timeString); + } catch (IllegalArgumentException e) { + LOG.error("getTime: failed to parse time from '" + timeString + "'"); + } + } + } + return rval; + } + + + public Float getFloatParameter(String key) { + return map.getFloat(key, 0.0f); + } + + + // This can be overridden by subclasses -- essentially it allows + // casting from the base class to the subclass. + public void initFromServiceResult(ServiceResult serviceResult) { + setMap(serviceResult.getMap()); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/tasks/MedtronicPumpTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/tasks/MedtronicPumpTask.java new file mode 100644 index 0000000000..ccf0867dce --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/tasks/MedtronicPumpTask.java @@ -0,0 +1,86 @@ +package info.nightscout.androidaps.plugins.PumpMedtronic.service.tasks; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.PumpTask; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService; +import info.nightscout.androidaps.plugins.PumpMedtronic.service.data.MedtronicPumpResult; + +/** + * Created by geoff on 7/9/16. + */ +public class MedtronicPumpTask extends PumpTask { + + private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpTask.class); + + MedtronicCommandType commandType; + Object[] parameters; + + + public MedtronicPumpTask(MedtronicCommandType commandType, Object... parameters) { + this.commandType = commandType; + this.parameters = parameters; + } + + + public MedtronicPumpTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + + MedtronicCommunicationManager communicationManager = RileyLinkMedtronicService.getCommunicationManager(); + MedtronicPumpResult medtronicPumpResult = new MedtronicPumpResult(commandType); + + switch (commandType) { + + case GetRemainingInsulin: + Float remainingInsulin = communicationManager.getRemainingInsulin(); + if (remainingInsulin == null) { + medtronicPumpResult.setError(); + } else { + medtronicPumpResult.addParameter("RemainingInsulin", remainingInsulin); + } + + + case PumpModel: { + MedtronicDeviceType pumpModel = communicationManager.getPumpModel(); + + if (pumpModel == MedtronicDeviceType.Unknown_Device) { + medtronicPumpResult.setError(); + } else { + medtronicPumpResult.addParameter("PumpModel", pumpModel.name()); + } + } + break; + + case RealTimeClock: { + LocalDateTime pumpResponse = communicationManager.getPumpTime(); + if (pumpResponse != null) { + LOG.info("ReadPumpClock: " + pumpResponse.toString("HH:mm:ss")); + medtronicPumpResult.addParameter("PumpTime", pumpResponse); + } else { + LOG.warn("handleServiceCommand(" + mTransport.getOriginalCommandName() + ") pumpResponse is null"); + medtronicPumpResult.setError(); + } + } + break; + + + default: + LOG.error("Type {} is NOT supported."); + break; + + } + + getServiceTransport().setServiceResult(medtronicPumpResult); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java index 9e0ad32e69..330f60c3e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java @@ -6,7 +6,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.util; public class MedtronicConst { - public static final String Prefix = "AAPS.Medtronic."; + static final String Prefix = "AAPS.Medtronic."; public class Prefs { @@ -18,9 +18,11 @@ public class MedtronicConst { public static final String MaxBolus = PrefPrefix + "max_bolus"; public static final String MaxBasal = PrefPrefix + "max_basal"; - public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodReceiverCommunicationTime"; + public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime"; public static final String LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency"; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicUtil.java index 469258e054..6f97d1e494 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicUtil.java @@ -1,15 +1,30 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.util; import org.joda.time.LocalTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.List; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; +import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; +import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType; + /** * Created by andy on 5/9/18. */ public class MedtronicUtil { + private static final Logger LOG = LoggerFactory.getLogger(MedtronicUtil.class); + private static MedtronicDeviceType deviceType; + private static boolean lowLevelDebug = true; + public static LocalTime getTimeFrom30MinInterval(int interval) { if (interval % 2 == 0) { @@ -20,6 +35,11 @@ public class MedtronicUtil { } + public static int getIntervalFromMinutes(int minutes) { + return minutes / 30; + } + + public static int makeUnsignedShort(int b2, int b1) { int k = (b2 & 0xff) << 8 | b1 & 0xff; return k; @@ -38,15 +58,17 @@ public class MedtronicUtil { } + public static byte[] createByteArray(byte... data) { return data; } + public static byte[] createByteArray(List data) { byte[] array = new byte[data.size()]; - for (int i = 0; i < data.size(); i++) { + for(int i = 0; i < data.size(); i++) { array[i] = data.get(i); } @@ -69,17 +91,39 @@ public class MedtronicUtil { return getBasalStrokes(amount, false); } + public static byte[] getBasalStrokes(double amount, boolean returnFixedSize) { return getStrokes(amount, 40, returnFixedSize); } + + public static int getBasalStrokesInt(double amount) { + return getStrokesInt(amount, 40); + } + + public static byte[] getBolusStrokes(double amount) { return getStrokes(amount, 10, false); } + public static byte[] createCommandBody(byte[] input) { + + return ByteUtil.concat((byte) input.length, input); + } + + public static byte[] getStrokes(double amount, int strokesPerUnit, boolean returnFixedSize) { + int strokes = getStrokesInt(amount, strokesPerUnit); + + return getByteArrayFromUnsignedShort(strokes, false); + + } + + + public static int getStrokesInt(double amount, int strokesPerUnit) { + int length = 1; int scrollRate = 1; @@ -97,9 +141,84 @@ public class MedtronicUtil { strokes *= scrollRate; - return getByteArrayFromUnsignedShort(strokes, false); + return strokes; } + static int ENVELOPE_SIZE = 4; // 0xA7 S1 S2 S3 CMD PARAM_COUNT [PARAMS] + + static int CRC_SIZE = 1; + + + public static byte[] buildCommandPayload(MessageType commandType, byte[] parameters) { + return buildCommandPayload(commandType.getValue(), parameters); + } + + + public static byte[] buildCommandPayload(MedtronicCommandType commandType, byte[] parameters) { + return buildCommandPayload((byte) commandType.commandCode, parameters); + } + + + public static byte[] buildCommandPayload(byte commandType, byte[] parameters) { + // A7 31 65 51 C0 00 52 + + byte commandLength = (byte) (parameters == null ? 2 : 2 + parameters.length); + + ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + commandLength); // + CRC_SIZE + sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN); + + byte[] serialNumberBCD = RileyLinkUtil.getRileyLinkServiceData().pumpIDBytes; + + sendPayloadBuffer.put((byte) 0xA7); + sendPayloadBuffer.put(serialNumberBCD[0]); + sendPayloadBuffer.put(serialNumberBCD[1]); + sendPayloadBuffer.put(serialNumberBCD[2]); + + sendPayloadBuffer.put(commandType); + + if (parameters == null) { + sendPayloadBuffer.put((byte) 0x00); + } else { + sendPayloadBuffer.put((byte) parameters.length); // size + + for(byte val : parameters) { + sendPayloadBuffer.put(val); + } + } + + byte[] payload = sendPayloadBuffer.array(); + + LOG.info(HexDump.toHexStringDisplayable(payload)); + + //int crc = computeCRC8WithPolynomial(payload, 0, payload.length - 1); + + //LOG.info("crc: " + crc); + + //sendPayloadBuffer.put((byte) crc); + + return sendPayloadBuffer.array(); + } + + + // FIXME + public static MedtronicDeviceType getDeviceType() { + return deviceType; + } + + + public static void setDeviceType(MedtronicDeviceType deviceType) { + MedtronicUtil.deviceType = deviceType; + } + + + public static boolean isLowLevelDebug() { + return lowLevelDebug; + } + + + public static void setLowLevelDebug(boolean lowLevelDebug) { + MedtronicUtil.lowLevelDebug = lowLevelDebug; + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 006138d50d..d9f336735e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1055,6 +1055,10 @@ Operation not supported by pump. Operation not YET supported by pump. + Location Is Not Enabled + For Bluetooth discovery to work on newer devices, location must be enabled. AAPS does not track your location and it can be disabled after pairing is successful. + Enable + No Medtronic