From 8e466be92cb66f531bac6f3bce14b818b30a1325 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 8 Jun 2021 23:27:14 +0200 Subject: [PATCH 01/19] Diaconn support --- app/build.gradle | 1 + .../activities/MyPreferenceFragment.kt | 3 + .../dependencyInjection/AppComponent.kt | 4 +- .../dependencyInjection/PluginsModule.kt | 7 + .../general/actions/ActionsFragment.kt | 7 +- .../profile/local/LocalProfileFragment.kt | 2 +- .../queue/commands/CommandLoadEvents.kt | 8 + .../queue/commands/CommandLoadHistory.kt | 8 + .../queue/commands/CommandSetUserSettings.kt | 7 + .../androidaps/activities/TDDStatsActivity.kt | 2 +- .../androidaps/interfaces/Diaconn.kt | 8 + .../plugins/common/ManufacturerType.kt | 3 +- .../pump/common/defs/PumpCapability.kt | 1 + .../plugins/pump/common/defs/PumpType.kt | 19 +- .../database/embedments/InterfaceIDs.kt | 1 + diaconn/build.gradle | 30 + diaconn/consumer-rules.pro | 0 diaconn/proguard-rules.pro | 21 + .../1.json | 92 + diaconn/src/main/AndroidManifest.xml | 22 + .../androidaps/diaconn/DiaconnG8Fragment.kt | 197 + .../androidaps/diaconn/DiaconnG8Plugin.kt | 583 ++ .../androidaps/diaconn/DiaconnG8Pump.kt | 333 + .../activities/DiaconnG8BLEScanActivity.kt | 184 + .../activities/DiaconnG8HistoryActivity.kt | 257 + .../DiaconnG8UserOptionsActivity.kt | 192 + .../androidaps/diaconn/common/RecordTypes.kt | 11 + .../database/DiaconnHistoryDatabase.kt | 32 + .../diaconn/database/DiaconnHistoryRecord.kt | 19 + .../database/DiaconnHistoryRecordDao.kt | 17 + .../diaconn/di/DiaconnG8ActivitiesModule.kt | 17 + .../androidaps/diaconn/di/DiaconnG8Module.kt | 12 + .../diaconn/di/DiaconnG8PacketModule.kt | 81 + .../diaconn/di/DiaconnG8ServiceModule.kt | 11 + .../diaconn/di/DiaconnHistoryModule.kt | 21 + .../events/EventDiaconnG8DeviceChange.kt | 5 + .../diaconn/events/EventDiaconnG8NewStatus.kt | 5 + .../diaconn/packet/AppCancelSettingPacket.kt | 32 + .../packet/AppCancelSettingResponsePacket.kt | 44 + .../diaconn/packet/AppConfirmSettingPacket.kt | 39 + .../packet/AppConfirmSettingResponsePacket.kt | 43 + .../diaconn/packet/BasalLimitInquirePacket.kt | 30 + .../packet/BasalLimitInquireResponsePacket.kt | 44 + .../diaconn/packet/BasalPauseReportPacket.kt | 37 + .../diaconn/packet/BasalPauseSettingPacket.kt | 32 + .../packet/BasalPauseSettingResponsePacket.kt | 48 + .../diaconn/packet/BasalSettingPacket.kt | 54 + .../packet/BasalSettingReportPacket.kt | 40 + .../packet/BasalSettingResponsePacket.kt | 46 + .../packet/BatteryWarningReportPacket.kt | 44 + .../diaconn/packet/BigLogInquirePacket.kt | 35 + .../packet/BigLogInquireResponsePacket.kt | 774 +++ .../packet/BigMainInfoInquirePacket.kt | 33 + .../BigMainInfoInquireResponsePacket.kt | 359 + .../diaconn/packet/BolusSpeedInquirePacket.kt | 27 + .../packet/BolusSpeedInquireResponsePacket.kt | 49 + .../diaconn/packet/BolusSpeedSettingPacket.kt | 32 + .../packet/BolusSpeedSettingReportPacket.kt | 40 + .../packet/BolusSpeedSettingResponsePacket.kt | 47 + .../diaconn/packet/ConfirmReportPacket.kt | 38 + .../diaconn/packet/DiaconnG8Packet.java | 300 + .../DiaconnG8ResponseMessageHashTable.kt | 52 + ...iaconnG8SettingResponseMessageHashTable.kt | 36 + .../packet/DisplayTimeInquirePacket.kt | 30 + .../DisplayTimeInquireResponsePacket.kt | 45 + .../packet/DisplayTimeoutSettingPacket.kt | 32 + .../DisplayTimeoutSettingResponsePacket.kt | 46 + .../packet/IncarnationInquirePacket.kt | 29 + .../IncarnationInquireResponsePacket.kt | 50 + .../packet/InjectionBasalReportPacket.kt | 37 + .../packet/InjectionBasalSettingPacket.kt | 31 + .../InjectionBasalSettingResponsePacket.kt | 47 + .../packet/InjectionBlockReportPacket.kt | 45 + .../packet/InjectionCancelSettingPacket.kt | 32 + .../InjectionCancelSettingResponsePacket.kt | 46 + ...njectionExtendedBolusResultReportPacket.kt | 59 + .../InjectionExtendedBolusSettingPacket.kt | 35 + ...ctionExtendedBolusSettingResponsePacket.kt | 46 + .../packet/InjectionMealSettingPacket.kt | 33 + .../InjectionMealSettingResponsePacket.kt | 46 + .../packet/InjectionSnackInquirePacket.kt | 26 + .../InjectionSnackInquireResponsePacket.kt | 51 + .../InjectionSnackResultReportPacket.kt | 60 + .../packet/InjectionSnackSettingPacket.kt | 31 + .../InjectionSnackSettingResponsePacket.kt | 46 + .../diaconn/packet/InsulinLackReportPacket.kt | 44 + .../diaconn/packet/LanguageInquirePacket.kt | 30 + .../packet/LanguageInquireResponsePacket.kt | 44 + .../diaconn/packet/LanguageSettingPacket.kt | 32 + .../packet/LanguageSettingResponsePacket.kt | 47 + .../diaconn/packet/LogStatusInquirePacket.kt | 28 + .../packet/LogStatusInquireResponsePacket.kt | 49 + .../diaconn/packet/RejectReportPacket.kt | 41 + .../diaconn/packet/SneckLimitInquirePacket.kt | 30 + .../packet/SneckLimitInquireResponsePacket.kt | 47 + .../diaconn/packet/SoundInquirePacket.kt | 30 + .../packet/SoundInquireResponsePacket.kt | 47 + .../diaconn/packet/SoundSettingPacket.kt | 34 + .../packet/SoundSettingResponsePacket.kt | 47 + .../diaconn/packet/TempBasalInquirePacket.kt | 29 + .../packet/TempBasalInquireResponsePacket.kt | 60 + .../diaconn/packet/TempBasalReportPacket.kt | 58 + .../diaconn/packet/TempBasalSettingPacket.kt | 44 + .../packet/TempBasalSettingResponsePacket.kt | 47 + .../diaconn/packet/TimeInquirePacket.kt | 30 + .../packet/TimeInquireResponsePacket.kt | 41 + .../diaconn/packet/TimeReportPacket.kt | 49 + .../diaconn/packet/TimeSettingPacket.kt | 43 + .../packet/TimeSettingResponsePacket.kt | 47 + .../diaconn/pumplog/LOG_ALARM_BATTERY.kt | 53 + .../diaconn/pumplog/LOG_ALARM_BLOCK.kt | 59 + .../diaconn/pumplog/LOG_ALARM_SHORTAGE.kt | 56 + .../pumplog/LOG_CHANGE_INJECTOR_SUCCESS.kt | 53 + .../pumplog/LOG_CHANGE_NEEDLE_SUCCESS.kt | 53 + .../pumplog/LOG_CHANGE_TUBE_SUCCESS.kt | 53 + .../diaconn/pumplog/LOG_INJECTION_1DAY.kt | 53 + .../pumplog/LOG_INJECTION_1DAY_BASAL.kt | 49 + .../pumplog/LOG_INJECTION_1HOUR_BASAL.kt | 61 + .../pumplog/LOG_INJECTION_DUAL_NORMAL.kt | 60 + .../diaconn/pumplog/LOG_INJECT_DUAL_FAIL.kt | 64 + .../pumplog/LOG_INJECT_DUAL_SUCCESS.kt | 60 + .../diaconn/pumplog/LOG_INJECT_MEAL_FAIL.kt | 64 + .../pumplog/LOG_INJECT_MEAL_SUCCESS.kt | 64 + .../diaconn/pumplog/LOG_INJECT_NORMAL_FAIL.kt | 64 + .../pumplog/LOG_INJECT_NORMAL_SUCCESS.kt | 60 + .../diaconn/pumplog/LOG_INJECT_SQUARE_FAIL.kt | 61 + .../pumplog/LOG_INJECT_SQUARE_SUCCESS.kt | 57 + .../diaconn/pumplog/LOG_RESET_SYS_V3.kt | 56 + .../diaconn/pumplog/LOG_SET_DUAL_INJECTION.kt | 60 + .../pumplog/LOG_SET_SQUARE_INJECTION.kt | 57 + .../diaconn/pumplog/LOG_SUSPEND_RELEASE_V2.kt | 71 + .../diaconn/pumplog/LOG_SUSPEND_V2.kt | 63 + .../diaconn/pumplog/LOG_TB_START_V3.kt | 61 + .../diaconn/pumplog/LOG_TB_STOP_V3.kt | 64 + .../diaconn/pumplog/PumplogUtil.java | 157 + .../diaconn/service/BLECommonService.kt | 367 + .../diaconn/service/DiaconnG8Service.kt | 641 ++ .../src/main/res/drawable/ic_diaconn_g8.xml | 6100 +++++++++++++++++ .../layout/diaconn_g8_blescanner_activity.xml | 51 + .../res/layout/diaconn_g8_blescanner_item.xml | 27 + .../main/res/layout/diaconn_g8_fragment.xml | 714 ++ .../layout/diaconn_g8_history_activity.xml | 94 + .../res/layout/diaconn_g8_history_item.xml | 90 + .../diaconn_g8_user_options_activity.xml | 336 + .../src/main/res/values-ko-rKR/strings.xml | 143 + diaconn/src/main/res/values/arrays.xml | 48 + diaconn/src/main/res/values/colors.xml | 10 + diaconn/src/main/res/values/ids.xml | 12 + diaconn/src/main/res/values/strings.xml | 166 + diaconn/src/main/res/values/themes.xml | 16 + diaconn/src/main/res/xml/pref_diaconn.xml | 50 + settings.gradle | 1 + 152 files changed, 16972 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/info/nightscout/androidaps/interfaces/Diaconn.kt create mode 100644 diaconn/build.gradle create mode 100644 diaconn/consumer-rules.pro create mode 100644 diaconn/proguard-rules.pro create mode 100644 diaconn/schemas/info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase/1.json create mode 100644 diaconn/src/main/AndroidManifest.xml create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Fragment.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Plugin.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Pump.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8HistoryActivity.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8UserOptionsActivity.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/common/RecordTypes.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryDatabase.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecord.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecordDao.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ActivitiesModule.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8Module.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8PacketModule.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ServiceModule.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnHistoryModule.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8DeviceChange.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8NewStatus.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BatteryWarningReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/ConfirmReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8Packet.java create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8ResponseMessageHashTable.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8SettingResponseMessageHashTable.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBlockReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusResultReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackResultReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InsulinLackReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/RejectReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquirePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquireResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeReportPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingPacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingResponsePacket.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BATTERY.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BLOCK.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_SHORTAGE.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_INJECTOR_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_NEEDLE_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_TUBE_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY_BASAL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1HOUR_BASAL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_DUAL_NORMAL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_FAIL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_FAIL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_FAIL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_FAIL.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_SUCCESS.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_RESET_SYS_V3.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_DUAL_INJECTION.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_SQUARE_INJECTION.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_RELEASE_V2.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_V2.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_START_V3.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_STOP_V3.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/PumplogUtil.java create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt create mode 100644 diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/DiaconnG8Service.kt create mode 100644 diaconn/src/main/res/drawable/ic_diaconn_g8.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_blescanner_activity.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_blescanner_item.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_fragment.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_history_activity.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_history_item.xml create mode 100644 diaconn/src/main/res/layout/diaconn_g8_user_options_activity.xml create mode 100644 diaconn/src/main/res/values-ko-rKR/strings.xml create mode 100644 diaconn/src/main/res/values/arrays.xml create mode 100644 diaconn/src/main/res/values/colors.xml create mode 100644 diaconn/src/main/res/values/ids.xml create mode 100644 diaconn/src/main/res/values/strings.xml create mode 100644 diaconn/src/main/res/values/themes.xml create mode 100644 diaconn/src/main/res/xml/pref_diaconn.xml diff --git a/app/build.gradle b/app/build.gradle index 85354209ff..21658892cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -192,6 +192,7 @@ dependencies { implementation project(':omnipod-common') implementation project(':omnipod-eros') implementation project(':omnipod-dash') + implementation project(':diaconn') implementation fileTree(include: ['*.jar'], dir: 'libs') diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt index e7ea847509..4c253c55f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt @@ -14,6 +14,7 @@ import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danars.DanaRSPlugin +import info.nightscout.androidaps.diaconn.DiaconnG8Plugin import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.events.EventRebuildTabs @@ -99,6 +100,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang @Inject lateinit var passwordCheck: PasswordCheck @Inject lateinit var nsSettingStatus: NSSettingsStatus @Inject lateinit var openHumansUploader: OpenHumansUploader + @Inject lateinit var diaconnG8Plugin: DiaconnG8Plugin override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) @@ -173,6 +175,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang addPreferencesFromResourceIfEnabled(localInsightPlugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(comboPlugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS) + addPreferencesFromResourceIfEnabled(diaconnG8Plugin, rootKey, config.PUMPDRIVERS) addPreferencesFromResource(R.xml.pref_pump, rootKey, config.PUMPDRIVERS) addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey) addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey) diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt index 5b74972932..5432082ada 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt @@ -13,6 +13,7 @@ import info.nightscout.androidaps.danar.di.DanaRModule import info.nightscout.androidaps.danars.di.DanaRSModule import info.nightscout.androidaps.database.DatabaseModule import info.nightscout.androidaps.di.CoreModule +import info.nightscout.androidaps.diaconn.di.DiaconnG8Module import info.nightscout.androidaps.insight.di.InsightDatabaseModule import info.nightscout.androidaps.insight.di.InsightModule import info.nightscout.androidaps.plugins.pump.common.di.PumpCommonModule @@ -56,7 +57,8 @@ import javax.inject.Singleton InsightModule::class, InsightDatabaseModule::class, WorkersModule::class, - OHUploaderModule::class + OHUploaderModule::class, + DiaconnG8Module::class ] ) interface AppComponent : AndroidInjector { diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt index 40bce88096..7b467893d3 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt @@ -8,6 +8,7 @@ import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.danar.DanaRPlugin import info.nightscout.androidaps.danars.DanaRSPlugin +import info.nightscout.androidaps.diaconn.DiaconnG8Plugin import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin @@ -158,6 +159,12 @@ abstract class PluginsModule { // @IntKey(155) // abstract fun bindOmnipodPumpPlugin(plugin: OmnipodErosPumpPlugin): PluginBase + @Binds + @PumpDriver + @IntoMap + @IntKey(155) + abstract fun bindDiaconnG8Plugin(plugin: DiaconnG8Plugin): PluginBase + @Binds @NotNSClient @IntoMap diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt index 8ffbd696ee..60fc700dcf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.kt @@ -29,6 +29,7 @@ import info.nightscout.androidaps.extensions.toStringMedium import info.nightscout.androidaps.extensions.toStringShort import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.activities.HistoryBrowseActivity +import info.nightscout.androidaps.diaconn.DiaconnG8Plugin import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.Config @@ -304,7 +305,11 @@ class ActionsFragment : DaggerFragment() { val activeBgSource = activePlugin.activeBgSource historyBrowser?.visibility = (profile != null).toVisibility() fill?.visibility = (pump.pumpDescription.isRefillingCapable && pump.isInitialized() && !pump.isSuspended()).toVisibility() - pumpBatteryChange?.visibility = (pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)).toVisibility() + if(pump is DiaconnG8Plugin) { + pumpBatteryChange?.visibility = (pump.pumpDescription.isBatteryReplaceable && !pump.isBatteryChangeLoggingEnabled()).toVisibility() + } else { + pumpBatteryChange?.visibility = (pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)).toVisibility() + } tempTarget?.visibility = (profile != null && config.APS).toVisibility() tddStats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 0b11136ed1..1d2eb8f84e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -129,7 +129,7 @@ class LocalProfileFragment : DaggerFragment() { binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, binding.save, textWatch) binding.dia.tag = "LP_DIA" TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic, "IC", resourceHelper.gs(R.string.ic_label), currentProfile.ic, null, hardLimits.minIC(), hardLimits.maxIC(), 0.1, DecimalFormat("0.0"), save) - basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", resourceHelper.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, 10.0, 0.01, DecimalFormat("0.00"), save) + basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", resourceHelper.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), save) if (units == Constants.MGDL) { TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf, "ISF", resourceHelper.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save) TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), 1.0, DecimalFormat("0"), save) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.kt b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.kt index f959eff033..58a0570eaf 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands import dagger.android.HasAndroidInjector import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.Dana +import info.nightscout.androidaps.interfaces.Diaconn import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.queue.Callback import javax.inject.Inject @@ -22,6 +23,13 @@ class CommandLoadEvents( aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") callback?.result(r)?.run() } + + if (pump is Diaconn) { + val diaconnPump = pump as Diaconn + val r = diaconnPump.loadHistory() + aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") + callback?.result(r)?.run() + } } override fun status(): String = "LOAD EVENTS" diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.kt b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.kt index 431b4fe12e..3ff9c133c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands import dagger.android.HasAndroidInjector import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.Dana +import info.nightscout.androidaps.interfaces.Diaconn import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.queue.Callback import javax.inject.Inject @@ -23,6 +24,13 @@ class CommandLoadHistory( aapsLogger.debug(LTag.PUMPQUEUE, "Result success: " + r.success + " enacted: " + r.enacted) callback?.result(r)?.run() } + + if (pump is Diaconn) { + val diaconnG8Pump = pump as Diaconn + val r = diaconnG8Pump.loadHistory() + aapsLogger.debug(LTag.PUMPQUEUE, "Result success: " + r.success + " enacted: " + r.enacted) + callback?.result(r)?.run() + } } override fun status(): String = "LOAD HISTORY $type" diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.kt b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.kt index abefe7e00e..7460529e67 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.queue.commands import dagger.android.HasAndroidInjector import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.Dana +import info.nightscout.androidaps.interfaces.Diaconn import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.queue.Callback import javax.inject.Inject @@ -21,6 +22,12 @@ class CommandSetUserSettings( aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") callback?.result(r)?.run() } + + if (pump is Diaconn) { + val r = pump.setUserOptions() + aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") + callback?.result(r)?.run() + } } override fun status(): String = "SET USER SETTINGS" diff --git a/core/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.kt b/core/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.kt index 1015274a08..58b939b2cb 100644 --- a/core/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.kt +++ b/core/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.kt @@ -425,7 +425,7 @@ class TDDStatsActivity : NoSplashAppCompatActivity() { private fun isOldData(historyList: List): Boolean { val type = activePlugin.activePump.pumpDescription.pumpType - val startsYesterday = type == PumpType.DANA_R || type == PumpType.DANA_RS || type == PumpType.DANA_RV2 || type == PumpType.DANA_R_KOREAN || type == PumpType.ACCU_CHEK_INSIGHT_VIRTUAL + val startsYesterday = type == PumpType.DANA_R || type == PumpType.DANA_RS || type == PumpType.DANA_RV2 || type == PumpType.DANA_R_KOREAN || type == PumpType.ACCU_CHEK_INSIGHT_VIRTUAL || type == PumpType.DIACONN_G8 val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault()) return historyList.size < 3 || df.format(Date(historyList[0].timestamp)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0)) } diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/Diaconn.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/Diaconn.kt new file mode 100644 index 0000000000..be3bfa1b87 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/Diaconn.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.interfaces + +import info.nightscout.androidaps.data.PumpEnactResult + +interface Diaconn { + fun loadHistory(): PumpEnactResult // for history browser + fun setUserOptions(): PumpEnactResult // pump etc settings +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.kt b/core/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.kt index 47b977e5d8..a7ac2b5596 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.kt @@ -9,5 +9,6 @@ enum class ManufacturerType(val description: String) { Animas("Animas"), Cellnovo("Cellnovo"), Roche("Roche"), - Ypsomed("Ypsomed"); + Ypsomed("Ypsomed"), + G2e("G2e"); } \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpCapability.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpCapability.kt index b8e74bb0a6..1ceac452df 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpCapability.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpCapability.kt @@ -23,6 +23,7 @@ enum class PumpCapability { MedtronicCapabilities(arrayOf(Bolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD)), OmnipodCapabilities(arrayOf(Bolus, TempBasal, BasalProfileSet, BasalRate30min)), YpsomedCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad)), // BasalRates (separately grouped) + DiaconnCapabilities(arrayOf(Bolus, ExtendedBolus, TempBasal, BasalProfileSet, Refill, ReplaceBattery, TDD, ManualTDDLoad)), // BasalRate_Duration15minAllowed, BasalRate_Duration30minAllowed, BasalRate_Duration15and30minAllowed(arrayOf(BasalRate_Duration15minAllowed, BasalRate_Duration30minAllowed)), diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt index 387386f927..88d268b6f1 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt @@ -284,7 +284,23 @@ enum class PumpType { model = "USER", tbrSettings = DoseSettings(1.0, 15, 24 * 60, 0.0, 500.0), extendedBolusSettings = DoseSettings(0.1, 15, 12 * 60, 0.1), - pumpCapability = PumpCapability.MDI); + pumpCapability = PumpCapability.MDI), + + //Diaconn Pump + DIACONN_G8(description = "DiaconnG8", + manufacturer = ManufacturerType.G2e, + model = "Diaconn G8", + bolusSize = 0.01, + specialBolusSize = null, + extendedBolusSettings = DoseSettings(0.05, 10, 5 * 60, 0.05), + pumpTempBasalType = PumpTempBasalType.Absolute, + tbrSettings = DoseSettings(0.01, 30, 24 * 60, 0.0, 6.0), + specialBasalDurations = PumpCapability.BasalRate_Duration30minAllowed, + baseBasalMinValue = 0.05, + baseBasalMaxValue = 3.0, + baseBasalStep = 0.01, + baseBasalSpecialSteps = null, + pumpCapability = PumpCapability.DanaWithHistoryCapabilities); val description: String var manufacturer: ManufacturerType? = null @@ -444,5 +460,6 @@ enum class PumpType { YPSOPUMP -> InterfaceIDs.PumpType.YPSOPUMP MDI -> InterfaceIDs.PumpType.MDI USER -> InterfaceIDs.PumpType.USER + DIACONN_G8 -> InterfaceIDs.PumpType.DIACONN_G8 } } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt b/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt index beb7eb5184..b06098f4ee 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt @@ -43,6 +43,7 @@ data class InterfaceIDs( TANDEM_T_SLIM_X2, YPSOPUMP, MDI, + DIACONN_G8, USER; companion object { diff --git a/diaconn/build.gradle b/diaconn/build.gradle new file mode 100644 index 0000000000..6194f079e3 --- /dev/null +++ b/diaconn/build.gradle @@ -0,0 +1,30 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'com.hiya.jacoco-android' + +apply from: "${project.rootDir}/gradle/android_dependencies.gradle" +apply from: "${project.rootDir}/gradle/android_module_dependencies.gradle" +apply from: "${project.rootDir}/gradle/test_dependencies.gradle" + +android { + defaultConfig { + versionCode 1 + versionName "1.0" + kapt { + arguments { + arg("room.incremental", "true") + arg("room.schemaLocation", "$projectDir/schemas") + } + } + } +} + +dependencies { + implementation project(':core') + + api "androidx.room:room-ktx:$room_version" + api "androidx.room:room-runtime:$room_version" + api "androidx.room:room-rxjava2:$room_version" + kapt "androidx.room:room-compiler:$room_version" +} \ No newline at end of file diff --git a/diaconn/consumer-rules.pro b/diaconn/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/diaconn/proguard-rules.pro b/diaconn/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/diaconn/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/diaconn/schemas/info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase/1.json b/diaconn/schemas/info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase/1.json new file mode 100644 index 0000000000..b6e405a524 --- /dev/null +++ b/diaconn/schemas/info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase/1.json @@ -0,0 +1,92 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "698b023da2f9efdc0351236c43eb20b6", + "entities": [ + { + "tableName": "diaconnHistory", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`timestamp` INTEGER NOT NULL, `code` INTEGER NOT NULL, `value` REAL NOT NULL, `bolusType` TEXT NOT NULL, `stringValue` TEXT NOT NULL, `duration` INTEGER NOT NULL, `dailyBasal` REAL NOT NULL, `dailyBolus` REAL NOT NULL, `alarm` TEXT NOT NULL, PRIMARY KEY(`timestamp`))", + "fields": [ + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "code", + "columnName": "code", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "bolusType", + "columnName": "bolusType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "stringValue", + "columnName": "stringValue", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "duration", + "columnName": "duration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dailyBasal", + "columnName": "dailyBasal", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "dailyBolus", + "columnName": "dailyBolus", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "alarm", + "columnName": "alarm", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "timestamp" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_diaconnHistory_code_timestamp", + "unique": false, + "columnNames": [ + "code", + "timestamp" + ], + "createSql": "CREATE INDEX IF NOT EXISTS `index_diaconnHistory_code_timestamp` ON `${TABLE_NAME}` (`code`, `timestamp`)" + } + ], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '698b023da2f9efdc0351236c43eb20b6')" + ] + } +} \ No newline at end of file diff --git a/diaconn/src/main/AndroidManifest.xml b/diaconn/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..3ddb6c3a37 --- /dev/null +++ b/diaconn/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Fragment.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Fragment.kt new file mode 100644 index 0000000000..3e7e9a2e01 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Fragment.kt @@ -0,0 +1,197 @@ +package info.nightscout.androidaps.diaconn + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import dagger.android.support.DaggerFragment +import info.nightscout.androidaps.activities.TDDStatsActivity +import info.nightscout.androidaps.diaconn.databinding.DiaconnG8FragmentBinding +import info.nightscout.androidaps.diaconn.events.EventDiaconnG8NewStatus +import info.nightscout.androidaps.events.EventExtendedBolusChange +import info.nightscout.androidaps.events.EventInitializationChanged +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.events.EventTempBasalChange +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.Pump +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.queue.events.EventQueueChanged +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.WarnColors +import io.reactivex.rxkotlin.plusAssign +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import javax.inject.Inject + +class DiaconnG8Fragment : DaggerFragment() { + + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var sp: SP + @Inject lateinit var warnColors: WarnColors + @Inject lateinit var dateUtil: DateUtil + + private var disposable: CompositeDisposable = CompositeDisposable() + + private val loopHandler = Handler() + private lateinit var refreshLoop: Runnable + + private var _binding: DiaconnG8FragmentBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + init { + refreshLoop = Runnable { + activity?.runOnUiThread { updateGUI() } + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View { + _binding = DiaconnG8FragmentBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.diaconnG8Pumpstatus.setBackgroundColor(resourceHelper.gc(R.color.colorInitializingBorder)) + binding.history.setOnClickListener { startActivity(Intent(context, info.nightscout.androidaps.diaconn.activities.DiaconnG8HistoryActivity::class.java)) } + binding.stats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) } + binding.userOptions.setOnClickListener { startActivity(Intent(context, info.nightscout.androidaps.diaconn.activities.DiaconnG8UserOptionsActivity::class.java)) } + binding.btconnection.setOnClickListener { + aapsLogger.debug(LTag.PUMP, "Clicked connect to pump") + diaconnG8Pump.lastConnection = 0 + commandQueue.readStatus("Clicked connect to pump", null) + } + } + + @Synchronized + override fun onResume() { + super.onResume() + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + disposable += rxBus + .toObservable(EventInitializationChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventDiaconnG8NewStatus::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventTempBasalChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventQueueChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventPumpStatusChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + when (it.status) { + EventPumpStatusChanged.Status.CONNECTING -> + @Suppress("SetTextI18n") + binding.btconnection.text = "{fa-bluetooth-b spin} ${it.secondsElapsed}s" + EventPumpStatusChanged.Status.CONNECTED -> + @Suppress("SetTextI18n") + binding.btconnection.text = "{fa-bluetooth}" + EventPumpStatusChanged.Status.DISCONNECTED -> + @Suppress("SetTextI18n") + binding.btconnection.text = "{fa-bluetooth-b}" + else -> {} + } + if (it.getStatus(resourceHelper) != "") { + binding.diaconnG8Pumpstatus.text = it.getStatus(resourceHelper) + binding.diaconnG8Pumpstatuslayout.visibility = View.VISIBLE + } else { + binding.diaconnG8Pumpstatuslayout.visibility = View.GONE + } + }, fabricPrivacy::logException) + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + loopHandler.removeCallbacks(refreshLoop) + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + @SuppressLint("SetTextI18n") + @Synchronized + fun updateGUI() { + if (_binding == null) return + val pump = diaconnG8Pump + val plugin: Pump = activePlugin.activePump + if (pump.lastConnection != 0L) { + val agoMsec = System.currentTimeMillis() - pump.lastConnection + val agoMin = (agoMsec.toDouble() / 60.0 / 1000.0).toInt() + binding.lastconnection.text = dateUtil.timeString(pump.lastConnection) + " (" + resourceHelper.gs(R.string.minago, agoMin) + ")" + warnColors.setColor(binding.lastconnection, agoMin.toDouble(), 16.0, 31.0) + } + if (pump.lastBolusTime != 0L) { + val agoMsec = System.currentTimeMillis() - pump.lastBolusTime + val agoHours = agoMsec.toDouble() / 60.0 / 60.0 / 1000.0 + if (agoHours < 6) + // max 6h back + binding.lastbolus.text = dateUtil.timeString(pump.lastBolusTime) + " " + dateUtil.sinceString(pump.lastBolusTime, resourceHelper) + " " + resourceHelper.gs(R.string.formatinsulinunits, pump.lastBolusAmount) + else + binding.lastbolus.text = "" + } + + binding.dailyunits.text = resourceHelper.gs(R.string.reservoirvalue, (pump.todayBaseAmount + pump.todaySnackAmount + pump.todayMealAmount), ((pump.maxBasal.toInt() * 24) + pump.maxBolusePerDay.toInt())) + warnColors.setColor(binding.dailyunits, pump.baseInjAmount, pump.baseAmount * 0.75, pump.baseAmount * 0.9) + binding.basabasalrate.text = pump.baseInjAmount.toString() +" / "+ resourceHelper.gs(R.string.pump_basebasalrate, plugin.baseBasalRate) + + binding.tempbasal.text = diaconnG8Pump.temporaryBasalToString() + binding.extendedbolus.text = diaconnG8Pump.extendedBolusToString() + binding.reservoir.text = resourceHelper.gs(R.string.reservoirvalue, pump.systemRemainInsulin, 307) + warnColors.setColorInverse(binding.reservoir, pump.systemRemainInsulin , 50.0, 20.0) + binding.battery.text = "{fa-battery-" + pump.systemRemainBattery / 25 + "}" + " ("+ pump.systemRemainBattery + " %)" + warnColors.setColorInverse(binding.battery, pump.systemRemainBattery.toDouble(), 51.0, 26.0) + //binding.tdd.text = "basal: " +pump.todayBaseAmount + "/ bolus: "+ (pump.todaySnackAmount + pump.todayMealAmount) + binding.firmware.text = resourceHelper.gs(R.string.diaconn_g8_pump) + "\nVersion: " + pump.majorVersion.toString() + "." + pump.minorVersion.toString() + "\nCountry: "+pump.country.toString() + "\nProductType: "+ pump.productType.toString() + "\nManufacture: " + pump.makeYear + "." + pump.makeMonth + "." + pump.makeDay + binding.basalstep.text = pump.basalStep.toString() + binding.bolusstep.text = pump.bolusStep.toString() + binding.serialNumber.text = pump.serialNo.toString() + val status = commandQueue.spannedStatus() + if (status.toString() == "") { + binding.queue.visibility = View.GONE + } else { + binding.queue.visibility = View.VISIBLE + binding.queue.text = status + } + + binding.userOptions.visibility = View.VISIBLE + } +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Plugin.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Plugin.kt new file mode 100644 index 0000000000..098b3cca9b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Plugin.kt @@ -0,0 +1,583 @@ +package info.nightscout.androidaps.diaconn + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.IBinder +import android.text.format.DateFormat +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.PumpEnactResult +import info.nightscout.androidaps.diaconn.events.EventDiaconnG8DeviceChange +import info.nightscout.androidaps.diaconn.service.DiaconnG8Service +import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.events.EventConfigBuilderChange +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.plannedRemainingMinutes +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.common.ManufacturerType +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.utils.* +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import org.json.JSONException +import org.json.JSONObject +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.math.abs +import kotlin.math.max + +@Singleton +class DiaconnG8Plugin @Inject constructor( + injector: HasAndroidInjector, + aapsLogger: AAPSLogger, + private val rxBus: RxBusWrapper, + private val context: Context, + resourceHelper: ResourceHelper, + private val constraintChecker: ConstraintChecker, + private val profileFunction: ProfileFunction, + private val sp: SP, + commandQueue: CommandQueueProvider, + private val diaconnG8Pump: DiaconnG8Pump, + private val pumpSync: PumpSync, + private val detailedBolusInfoStorage: DetailedBolusInfoStorage, + private val temporaryBasalStorage: TemporaryBasalStorage, + private val fabricPrivacy: FabricPrivacy, + private val dateUtil: DateUtil +) : PumpPluginBase(PluginDescription() + .mainType(PluginType.PUMP) + .fragmentClass(DiaconnG8Fragment::class.java.name) + .pluginIcon(R.drawable.ic_diaconn_g8) + .pluginName(R.string.diaconn_g8_pump) + .shortName(R.string.diaconn_g8_pump_shortname) + .preferencesId(R.xml.pref_diaconn) + .description(R.string.description_pump_diaconn_g8), + injector, aapsLogger, resourceHelper, commandQueue +), Pump, Diaconn, Constraints { + + private val disposable = CompositeDisposable() + private var diaconnG8Service: DiaconnG8Service? = null + private var mDeviceAddress = "" + var mDeviceName = "" + override val pumpDescription = PumpDescription(PumpType.DIACONN_G8) + + override fun onStart() { + super.onStart() + val intent = Intent(context, DiaconnG8Service::class.java) + context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE) + disposable.add(rxBus + .toObservable(EventAppExit::class.java) + .observeOn(Schedulers.io()) + .subscribe({ context.unbindService(mConnection) }) { fabricPrivacy.logException(it) } + ) + disposable.add(rxBus + .toObservable(EventConfigBuilderChange::class.java) + .observeOn(Schedulers.io()) + .subscribe { diaconnG8Pump.reset() } + ) + disposable.add(rxBus + .toObservable(EventDiaconnG8DeviceChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ changePump() }) { fabricPrivacy.logException(it) } + ) + changePump() // load device name + } + + override fun onStop() { + context.unbindService(mConnection) + disposable.clear() + super.onStop() + } + + private val mConnection: ServiceConnection = object : ServiceConnection { + override fun onServiceDisconnected(name: ComponentName) { + aapsLogger.debug(LTag.PUMP, "Service is disconnected") + diaconnG8Service = null + } + + override fun onServiceConnected(name: ComponentName, service: IBinder) { + aapsLogger.debug(LTag.PUMP, "Service is connected") + val mLocalBinder = service as DiaconnG8Service.LocalBinder + diaconnG8Service = mLocalBinder.serviceInstance + } + } + + fun changePump() { + mDeviceAddress = sp.getString(R.string.key_diaconn_g8_address, "") + mDeviceName = sp.getString(R.string.key_diaconn_g8_name, "") + diaconnG8Pump.reset() + commandQueue.readStatus("DeviceChanged", null) + } + + override fun connect(reason: String) { + aapsLogger.debug(LTag.PUMP, "Diaconn G8 connect from: $reason") + if(diaconnG8Service != null && mDeviceAddress != "" && mDeviceName != "") { + val success = diaconnG8Service?.connect(reason, mDeviceAddress) ?: false + if(!success) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.ble_not_supported)) + } + } + + override fun isConnected(): Boolean = diaconnG8Service?.isConnected ?: false + override fun isConnecting(): Boolean = diaconnG8Service?.isConnecting ?: false + override fun isHandshakeInProgress(): Boolean = false + + + override fun disconnect(reason: String) { + aapsLogger.debug(LTag.PUMP, "Diaconn G8 disconnect from: $reason") + diaconnG8Service?.disconnect(reason) + } + + override fun stopConnecting() { + diaconnG8Service?.stopConnecting() + } + + override fun getPumpStatus(reason: String) { + diaconnG8Service?.readPumpStatus() + pumpDescription.basalStep = diaconnG8Pump.basalStep + pumpDescription.bolusStep = diaconnG8Pump.bolusStep + pumpDescription.basalMaximumRate = diaconnG8Pump.maxBasalPerHours + } + + // Diaconn Pump Interface + override fun loadHistory(): PumpEnactResult { + return diaconnG8Service?.loadHistory() ?: PumpEnactResult(injector).success(false) + } + + override fun setUserOptions(): PumpEnactResult { + return diaconnG8Service?.setUserSettings() ?: PumpEnactResult(injector).success(false) + } + + // Constraints interface + override fun applyBasalConstraints(absoluteRate: Constraint, profile: Profile): Constraint { + absoluteRate.setIfSmaller(aapsLogger, diaconnG8Pump.maxBasal, resourceHelper.gs(R.string.limitingbasalratio, diaconnG8Pump.maxBasal, resourceHelper.gs(R.string.pumplimit)), this) + return absoluteRate + } + + override fun applyBasalPercentConstraints(percentRate: Constraint, profile: Profile): Constraint { + percentRate.setIfGreater(aapsLogger, 0, resourceHelper.gs(R.string.limitingpercentrate, 0, resourceHelper.gs(R.string.itmustbepositivevalue)), this) + percentRate.setIfSmaller(aapsLogger, pumpDescription.maxTempPercent, resourceHelper.gs(R.string.limitingpercentrate, pumpDescription.maxTempPercent, resourceHelper.gs(R.string.pumplimit)), this) + return percentRate + } + + override fun applyBolusConstraints(insulin: Constraint): Constraint { + insulin.setIfSmaller(aapsLogger, diaconnG8Pump.maxBolus, resourceHelper.gs(R.string.limitingbolus, diaconnG8Pump.maxBolus, resourceHelper.gs(R.string.pumplimit)), this) + return insulin + } + + override fun applyExtendedBolusConstraints(insulin: Constraint): Constraint { + return applyBolusConstraints(insulin) + } + + // Pump interface + override fun isInitialized(): Boolean = + diaconnG8Pump.lastConnection > 0 && diaconnG8Pump.maxBasal > 0 + + override fun isSuspended(): Boolean = + diaconnG8Pump.basePauseStatus == 1 + + override fun isBusy(): Boolean = + diaconnG8Service?.isConnected ?: false || diaconnG8Service?.isConnecting ?: false + + override fun setNewBasalProfile(profile: Profile): PumpEnactResult { + val result = PumpEnactResult(injector) + if (!isInitialized()) { + val notification = Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT) + rxBus.send(EventNewNotification(notification)) + result.comment = resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet) + return result + } else { + rxBus.send(EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)) + } + return if (diaconnG8Service?.updateBasalsInPump(profile) != true) { + val notification = Notification(Notification.FAILED_UPDATE_PROFILE, resourceHelper.gs(R.string.failedupdatebasalprofile), Notification.URGENT) + rxBus.send(EventNewNotification(notification)) + result.comment = resourceHelper.gs(R.string.failedupdatebasalprofile) + result + } else { + rxBus.send(EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)) + rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) + val notification = Notification(Notification.PROFILE_SET_OK, resourceHelper.gs(R.string.profile_set_ok), Notification.INFO, 60) + rxBus.send(EventNewNotification(notification)) + result.success = true + result.enacted = true + result.comment = "OK" + result + } + } + + override fun isThisProfileSet(profile: Profile): Boolean { + if (!isInitialized()) return true // TODO: not sure what's better. so far TRUE to prevent too many SMS + if (diaconnG8Pump.pumpProfiles == null) return true // TODO: not sure what's better. so far TRUE to prevent too many SMS + val basalValues = 24 + val basalIncrement = 60 * 60 + for (h in 0 until basalValues) { + val pumpValue = diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][h] + val profileValue = profile.getBasalTimeFromMidnight(h * basalIncrement) + if (abs(pumpValue - profileValue) > pumpDescription.basalStep) { + aapsLogger.debug(LTag.PUMP, "Diff found. Hour: $h Pump: $pumpValue Profile: $profileValue") + return false + } + } + return true + } + + override fun lastDataTime(): Long = diaconnG8Pump.lastConnection + + override val baseBasalRate: Double + get() = diaconnG8Pump.baseAmount + override val reservoirLevel: Double + get() = diaconnG8Pump.systemRemainInsulin + override val batteryLevel: Int + get() = diaconnG8Pump.systemRemainBattery + + + @Synchronized + override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { + detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(Constraint(detailedBolusInfo.insulin)).value() + return if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + val carbs = detailedBolusInfo.carbs + detailedBolusInfo.carbs = 0.0 + var carbTimeStamp = detailedBolusInfo.carbsTimestamp ?: detailedBolusInfo.timestamp + if (carbTimeStamp == detailedBolusInfo.timestamp) carbTimeStamp -= T.mins(1).msecs() // better set 1 min back to prevents clash with insulin + detailedBolusInfoStorage.add(detailedBolusInfo) // will be picked up on reading history + val t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB) + var connectionOK = false + if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = diaconnG8Service?.bolus(detailedBolusInfo.insulin, carbs.toInt(), carbTimeStamp, t) + ?: false + val result = PumpEnactResult(injector) + result.success = connectionOK + result.bolusDelivered = t.insulin + result.carbsDelivered = detailedBolusInfo.carbs + + if(result.success) result.enacted = true + if (!result.success) { + setErrorMsg(diaconnG8Pump.bolusStartErrorCode, result) + } else result.comment = resourceHelper.gs(R.string.ok) + aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered) + result + } else { + val result = PumpEnactResult(injector) + result.success = false + result.bolusDelivered = 0.0 + result.carbsDelivered = 0.0 + result.comment = resourceHelper.gs(R.string.invalidinput) + aapsLogger.error("deliverTreatment: Invalid input") + result + } + } + + override fun stopBolusDelivering() { + diaconnG8Service?.bolusStop() + } + + // This is called from APS + @Synchronized + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult { + val result = PumpEnactResult(injector) + var absoluteAfterConstrain = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value() + val doTempOff = baseBasalRate - absoluteAfterConstrain == 0.0 + val doLowTemp = absoluteAfterConstrain < baseBasalRate + val doHighTemp = absoluteAfterConstrain > baseBasalRate + if (doTempOff) { + // If temp in progress + if (diaconnG8Pump.isTempBasalInProgress) { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)") + return cancelTempBasal(false) + } + result.success = true + result.enacted = false + result.absolute = baseBasalRate + result.isPercent = false + result.isTempCancel = true + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK") + return result + } + + if (doLowTemp || doHighTemp) { + // Check if some temp is already in progress + if(absoluteAfterConstrain > 6.0) absoluteAfterConstrain = 6.0 // pumpLimit + //val activeTemp = activePluginProvider.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis()) + if (diaconnG8Pump.isTempBasalInProgress) { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running") + // Correct basal already set ? + if (diaconnG8Pump.tempBasalAbsoluteRate == absoluteAfterConstrain && diaconnG8Pump.tempBasalRemainingMin > 4) { + if (!enforceNew) { + result.success = true + result.absolute = absoluteAfterConstrain + result.enacted = false + result.duration = diaconnG8Pump.tempBasalRemainingMin + result.isPercent = false + result.isTempCancel = false + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)") + return result + } + } + } + temporaryBasalStorage.add(PumpSync.PumpState.TemporaryBasal(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), absoluteRate, true, tbrType, 0L, 0L)) + // Convert duration from minutes to hours + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $absoluteAfterConstrain% for $durationInMinutes mins (doLowTemp || doHighTemp)") + val connectionOK: Boolean = if (durationInMinutes == 15 || durationInMinutes == 30) { + diaconnG8Service?.tempBasalShortDuration(absoluteAfterConstrain, durationInMinutes) ?: false + } else { + val durationInHours = max(durationInMinutes / 60, 1) + diaconnG8Service?.tempBasal(absoluteAfterConstrain, durationInHours) ?: false + } + + if (connectionOK && diaconnG8Pump.isTempBasalInProgress && diaconnG8Pump.tempBasalAbsoluteRate == absoluteAfterConstrain) { + result.enacted = true + result.success = true + result.comment = resourceHelper.gs(R.string.ok) + result.isTempCancel = false + result.duration = diaconnG8Pump.tempBasalRemainingMin + result.absolute = diaconnG8Pump.tempBasalAbsoluteRate + result.isPercent = false + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: OK") + return result + } + } + + result.enacted = false + result.success = false + result.comment = resourceHelper.gs(R.string.tempbasaldeliveryerror) + aapsLogger.error("setTempBasalAbsolute: Failed to set temp basal") + return result + } + + @Synchronized + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult { + return if (percent == 0) { + setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType) + } else { + var absoluteValue = profile.getBasal() * (percent / 100.0) + absoluteValue = pumpDescription.pumpType.determineCorrectBasalSize(absoluteValue) + aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [DiaconnG8Plugin] - You are trying to use setTempBasalPercent with percent other then 0% ($percent). This will start setTempBasalAbsolute, with calculated value ($absoluteValue). Result might not be 100% correct.") + setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType) + } + + } + + @Synchronized + override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult { + var insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value() + // needs to be rounded + //val durationInHalfHours = max(durationInMinutes / 30, 1) + insulinAfterConstraint = Round.roundTo(insulinAfterConstraint, pumpDescription.extendedBolusStep) + val result = PumpEnactResult(injector) + + if (diaconnG8Pump.isExtendedInProgress && abs(diaconnG8Pump.extendedBolusAmount - insulinAfterConstraint) < pumpDescription.extendedBolusStep) { + result.enacted = false + result.success = true + result.comment = resourceHelper.gs(R.string.ok) + result.duration = diaconnG8Pump.extendedBolusRemainingMinutes + result.absolute = diaconnG8Pump.extendedBolusAbsoluteRate + result.isPercent = false + result.isTempCancel = false + aapsLogger.debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + diaconnG8Pump.extendedBolusAmount + " Asked: " + insulinAfterConstraint) + return result + } + val connectionOK = diaconnG8Service?.extendedBolus(insulinAfterConstraint, durationInMinutes) + ?: false + + if (connectionOK) { + result.enacted = true + result.success = true + result.comment = resourceHelper.gs(R.string.ok) + result.isTempCancel = false + result.duration = diaconnG8Pump.extendedBolusRemainingMinutes + result.absolute = diaconnG8Pump.extendedBolusAbsoluteRate + result.bolusDelivered = diaconnG8Pump.extendedBolusAmount + result.isPercent = false + aapsLogger.debug(LTag.PUMP, "setExtendedBolus: OK") + return result + } + + result.enacted = false + result.success = false + setErrorMsg(diaconnG8Pump.bolusStartErrorCode, result) + aapsLogger.error("setExtendedBolus: Failed to extended bolus") + return result + } + + @Synchronized + override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { + val result = PumpEnactResult(injector) + if (diaconnG8Pump.isTempBasalInProgress) { + diaconnG8Service?.tempBasalStop() + result.success = !diaconnG8Pump.isTempBasalInProgress + result.enacted = true + result.isTempCancel = true + } else { + result.success = true + result.enacted = false + result.isTempCancel = true + result.comment = resourceHelper.gs(R.string.ok) + aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK") + } + return result + } + + @Synchronized override fun cancelExtendedBolus(): PumpEnactResult { + val result = PumpEnactResult(injector) + if (diaconnG8Pump.isExtendedInProgress) { + diaconnG8Service?.extendedBolusStop() + result.success = !diaconnG8Pump.isExtendedInProgress + result.enacted = true + } else { + result.success = true + result.enacted = false + result.comment = resourceHelper.gs(R.string.ok) + aapsLogger.debug(LTag.PUMP, "cancelExtendedBolus: OK") + } + return result + } + + override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject { + val now = System.currentTimeMillis() + if (diaconnG8Pump.lastConnection + 60 * 60 * 1000L < System.currentTimeMillis()) { + return JSONObject() + } + val pumpJson = JSONObject() + val battery = JSONObject() + val status = JSONObject() + val extended = JSONObject() + try { + battery.put("percent", diaconnG8Pump.systemRemainBattery) + status.put("status", if (diaconnG8Pump.pumpSuspended) "suspended" else "normal") + status.put("timestamp", dateUtil.toISOString(diaconnG8Pump.lastConnection)) + extended.put("Version", version) + if (diaconnG8Pump.lastBolusTime != 0L) { + extended.put("LastBolus", dateUtil.dateAndTimeString(diaconnG8Pump.lastBolusTime)) + extended.put("LastBolusAmount", diaconnG8Pump.lastBolusAmount) + } + val tb = pumpSync.expectedPumpState().temporaryBasal + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.convertedToAbsolute(now, profile)) + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.timestamp)) + extended.put("TempBasalRemaining", tb.plannedRemainingMinutes) + } + val eb = pumpSync.expectedPumpState().extendedBolus + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.rate) + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.timestamp)) + extended.put("ExtendedBolusRemaining", eb.plannedRemainingMinutes) + } + extended.put("BaseBasalRate", baseBasalRate) + try { + extended.put("ActiveProfile", profileFunction.getProfileName()) + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + } + pumpJson.put("battery", battery) + pumpJson.put("status", status) + pumpJson.put("extended", extended) + pumpJson.put("reservoir", diaconnG8Pump.systemRemainInsulin.toInt()) + pumpJson.put("clock", dateUtil.toISOString(now)) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + return pumpJson + } + + override fun manufacturer(): ManufacturerType { + return ManufacturerType.G2e + } + + override fun model(): PumpType { + return PumpType.DIACONN_G8 + } + + override fun serialNumber(): String { + return diaconnG8Pump.serialNo.toString() + } + + override fun shortStatus(veryShort: Boolean): String { + var ret = "" + if (diaconnG8Pump.lastConnection != 0L) { + val agoMillis = System.currentTimeMillis() - diaconnG8Pump.lastConnection + val agoMin = (agoMillis / 60.0 / 1000.0).toInt() + ret += "LastConn: $agoMin minago\n" + } + if (diaconnG8Pump.lastBolusTime != 0L) + ret += "LastBolus: ${DecimalFormatter.to2Decimal(diaconnG8Pump.lastBolusAmount)}U @${DateFormat.format("HH:mm", diaconnG8Pump.lastBolusTime)}" + + if (diaconnG8Pump.isTempBasalInProgress) + ret += "Temp: ${diaconnG8Pump.temporaryBasalToString()}" + + if (diaconnG8Pump.isExtendedInProgress) + ret += "Extended: ${diaconnG8Pump.extendedBolusToString()}\n" + + if (!veryShort) { + ret += "TDD: ${DecimalFormatter.to0Decimal(diaconnG8Pump.dailyTotalUnits)} / ${diaconnG8Pump.maxDailyTotalUnits} U" + } + ret += "Reserv: ${DecimalFormatter.to0Decimal(diaconnG8Pump.systemRemainInsulin)} U" + ret += "Batt: ${diaconnG8Pump.systemRemainBattery}" + return ret + } + override val isFakingTempsByExtendedBoluses: Boolean = false + override fun loadTDDs(): PumpEnactResult = loadHistory() + override fun getCustomActions(): List? = null + override fun executeCustomAction(customActionType: CustomActionType) {} + override fun canHandleDST(): Boolean = false + + fun isBatteryChangeLoggingEnabled():Boolean { + return sp.getBoolean(R.string.key_diaconn_g8_logbatterychange, false) + } + + fun isInsulinChangeLoggingEnabled():Boolean { + return sp.getBoolean(R.string.key_diaconn_g8_loginsulinchange, false) + } + + @Synchronized + fun setErrorMsg(errorCode: Int, result: PumpEnactResult) { + when (errorCode) { + 1 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_1) + 2 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_2) + 3 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_3) + 4 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_4) + 6 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_6) + 7 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_7) + 8 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_8) + 9 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_9) + 10 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_10) + 11 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_11) + 12 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_12) + 13 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_13) + 14 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_14) + 15 -> result.comment = resourceHelper.gs(R.string.diaconn_g8_errorcode_15) + else -> result.comment = "not defined Error code: $errorCode" + } + } + + override fun preprocessPreferences(preferenceFragment: PreferenceFragmentCompat) { + + val bolusSpeedPreference: Preference? = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_diaconn_g8_bolusspeed)) + bolusSpeedPreference?.setOnPreferenceChangeListener { _, newValue -> + val intBolusSpeed = newValue.toString().toInt() + + diaconnG8Pump.bolusSpeed = intBolusSpeed + diaconnG8Pump.speed = intBolusSpeed + diaconnG8Pump.setUserOptionType = DiaconnG8Pump.BOLUS_SPEED + sp.putBoolean("diaconn_g8_isbolusspeedsync", false) + + true + } + } + +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Pump.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Pump.kt new file mode 100644 index 0000000000..7c89920fc8 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/DiaconnG8Pump.kt @@ -0,0 +1,333 @@ +package info.nightscout.androidaps.diaconn + + +import info.nightscout.androidaps.interfaces.Profile +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.T +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt + +@Singleton +class DiaconnG8Pump @Inject constructor( + private val aapsLogger: AAPSLogger, + private val dateUtil: DateUtil +) { + + var maxBolusePerDay: Double = 0.0 + var pumpIncarnationNum: Int = 65536 + var isPumpVersionGe2_63: Boolean = false // is pumpVersion higher then 2.63 + var insulinWarningGrade: Int =0 + var insulinWarningProcess: Int =0 + var insulinWarningRemain: Int =0 + var batteryWaningGrade: Int = 0 + var batteryWaningProcess: Int = 0 + var batteryWaningRemain: Int = 0 + var injectionBlockType: Int =0 + var injectionBlockRemainAmount: Double = 0.0 + var injectionBlockProcess: Int = 0 + var injectionBlockGrade: Int = 0 + var lastConnection: Long = 0 + var lastSettingsRead: Long = 0 + + // time + private var pumpTime: Long = 0 + + fun setPumpTime(value: Long) { + pumpTime = value + } + fun getPumpTime() = pumpTime + + // Status + var pumpSuspended = false + var dailyTotalUnits = 0.0 + var maxDailyTotalUnits = 0 + var bolusStep = 0.01 + var basalStep = 0.01 + var iob = 0.0 + + + var bolusBlocked = false + var lastBolusTime: Long = 0 + var lastBolusAmount = 0.0 + var extendedBolusMinutes = 0 + var extendedBolusSoFarInMinutes = 0 + var extendedBolusDeliveredSoFar = 0.0 + + /* + * TEMP BASALS + */ + var isTempBasalInProgress = false + var tempBasalPercent = 0 + var tempBasalStart: Long = 0 + var tempBasalAbsoluteRate: Double = 0.0 + var tempBasalDuration: Long = 0 + + val tempBasalRemainingMin: Int + get() = max(tbElapsedTime, 0) + + fun temporaryBasalToString(): String { + if (!isTempBasalInProgress) return "" + return tempBasalAbsoluteRate.toString() + "U @" + + dateUtil.timeString(tempBasalStart) + + " " + tbElapsedTime + "/" + T.msecs(tempBasalDuration).mins() + "'" + } + + fun fromTemporaryBasal(tbr: PumpSync.PumpState.TemporaryBasal?) { + if (tbr == null) { + tempBasalStart = 0 + tempBasalDuration = 0 + tempBasalAbsoluteRate = 0.0 + } else { + tempBasalStart = tbr.timestamp + tempBasalDuration = tbr.duration + tempBasalAbsoluteRate = tbr.rate + } + } + + /* + * EXTENDED BOLUSES + */ + var extendedBolusStart: Long = 0 + var extendedBolusDuration: Long = 0 + var extendedBolusAmount = 0.0 + var isExtendedInProgress:Boolean = false + var extendedBolusPassedMinutes = 0 + var extendedBolusRemainingMinutes = 0 + var extendedBolusAbsoluteRate = 0.0 + + fun extendedBolusToString(): String { + if (!isExtendedInProgress) return "" + return "E "+ DecimalFormatter.to2Decimal(extendedBolusDeliveredSoFar) +"/" + DecimalFormatter.to2Decimal(extendedBolusAbsoluteRate) + "U/h @" + + dateUtil.timeString(extendedBolusStart) + + " " + extendedBolusPassedMinutes + "/" + extendedBolusMinutes + "'" + } + + fun fromExtendedBolus(eb: PumpSync.PumpState.ExtendedBolus?) { + if (eb == null) { + extendedBolusStart = 0 + extendedBolusDuration = 0 + extendedBolusAmount = 0.0 + } else { + extendedBolusStart = eb.timestamp + extendedBolusDuration = eb.duration + extendedBolusAmount = eb.amount + } + } + // Profile + var units = 0 + var activeProfile = 0 + var pumpProfiles: Array>? = null + + //Limits + var maxBolus = 0.0 + var maxBasal = 0.0 + + // User settings + var setUserOptionType = 0 // ALARM:0, LCD:1, LANG:2, BOLUS_SPEED:3 + var beepAndAlarm = 0 + var alarmIntesity = 0 + var lcdOnTimeSec = 0 + var selectedLanguage = 0 + var bolusSpeed = 0 + + + // Bolus settings + var bolusStartErrorCode: Int = 0 // last start bolus erroCode + var historyDoneReceived: Boolean = false // true when last history message is received + var bolusingTreatment: EventOverviewBolusProgress.Treatment? = null // actually delivered treatment + var bolusAmountToBeDelivered = 0.0 // amount to be delivered + var bolusProgressLastTimeStamp: Long = 0 // timestamp of last bolus progress message + var bolusStopped = false // bolus finished + var bolusStopForced = false // bolus forced to stop by user + var bolusDone = false // success end + + fun buildDiaconnG8ProfileRecord(nsProfile: Profile): Array { + val record = Array(24) { 0.0 } + for (hour in 0..23) { + //Some values get truncated to the next lower one. + // -> round them to two decimals and make sure we are a small delta larger (that will get truncated) + val value = (100.0 * nsProfile.getBasalTimeFromMidnight((hour * 60 * 60))).roundToInt() / 100.0 + 0.00001 + aapsLogger.debug(LTag.PUMP, "NS basal value for $hour:00 is $value") + record[hour] = value + //aapsLogger.debug(LTag.PUMP, "NS basal value * 100 for $hour:00 is $value") + } + return record + } + + fun reset() { + aapsLogger.debug(LTag.PUMP, "Diaconn G8 Pump reset") + lastConnection = 0 + lastSettingsRead = 0 + } + + // G8 pump + var result:Int = 0 // 조회결과 + + // 1. pump setting info + var systemRemainInsulin = 0.0 // 인슐린 잔량 + var systemRemainBattery = 0 // 배터리 잔량(0~100%) + var systemBasePattern = 0 // 기저주입 패턴(0=없음, 1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2) + var systemTbStatus = 0 // 임시기저 상태(1=임시기저 중, 2=임시기저 해제) + var systemInjectionMealStatus = 0 // 식사주입 상태(1=주입중, 2=주입상태아님) + var systemInjectionSnackStatus = 0 // 일반간식 주입 상태(1=주입중, 2=주입상태아님) + var systemInjectionSquareStatue = 0 // 스퀘어회식 주입 상태(1=주입중, 2=주입상태아님) + var systemInjectionDualStatus = 0 // 더블회식 주입 상태(1=주입중, 2=주입상태아님) + + // 2. basal injection suspend status (1:stop, 2:release) + var basePauseStatus = 0 // 상태(1=정지,2=해제) + + // 3. Pump time + var year = 0 // 년 (18~99) + var month = 0 // 월 (1~12) + var day = 0 // 일 (1~31) + var hour = 0 // 시 (0~23) + var minute = 0 // 분 (0~59) + var second = 0 // 초 (0~59) + + + // 4. pump system info + var country = 0 // 생산국(K, C), ASCII + var productType = 0 // 제품종류(A ~ Z), ASCII + var makeYear = 0 // 제조년 + var makeMonth = 0 // 제조월 + var makeDay = 0 // 제조일 + var lotNo = 0 // LOT NO + var serialNo = 0 // SERIAL NO + var majorVersion = 0 // Major 버전 + var minorVersion = 0 // Minor 버전 + + // 5. pump log status + var pumpLastLogNum = 0 // 마지막 저장 로그 번호(0~9999) + var pumpWrappingCount = 0 // wrapping 카운트(0~255) + var apslastLogNum = 0 // 앱에서 처리한 마지막 로그 번호. + var apsWrappingCount = 0 // 앱에서 처리한 마지막 로그 번호. + var isProgressPumpLogSync = false // 로그 동기화 진행 여부 + + // 6. bolus speed status. + var speed = 0 // 주입 속도(1 ~ 8) + var maxBasalPerHours = 0.0 + + // 7. Tempbasal status + var tbStatus = 0 // 임시기저 상태 + var tbTime = 0 // 임시기저 시간 + var tbInjectRateRatio = 0 // 임시기저 주입량/률 1000(0.00U)~1600(6.00U), 50000(0%)~50200(200%), 50000이상이면 주입률로 판정 + var tbElapsedTime = 0 // 임시기저 경과 시간(0~1425분) + var tbInjectAbsoluteValue = 0.0 // 임시기저 주입량/률 1000(0.00U)~1600(6.00U) + + // 8. Basal status + var baseStatus = 0 // 주입상태 + var baseHour = 0 // 현재주입시간(0~23) + var baseAmount = 0.0 // 주입설정량(량*100, 23.25->2325, 15.2->1520) + var baseInjAmount = 0.0 // 현재주입량(량*100, 23.25->2325, 15.2->1520) + + + // 9. meal bolus status + var mealKind = 0 // 주입종류(1=아침,2=점심,3=저녁) + var mealStartTime = 0 // 식사주입 시작시간(time_t) + var mealStatus = 0 // 주입상태(1=주입중,2=주입상태아님) + var mealAmount = 0.0 // 주입설정량(량*100, 23.25->2325, 15.2->1520) + var mealInjAmount = 0.0 // 현재주입량(량*100, 23.25->2325, 15.2->1520) + var mealSpeed = 0 // 주입속도(1~8) + + + // 10. snack bolus status + var snackStatus = 0 // 주입상태(1=주입중,2=주입상태아님) + var snackAmount = 0.0 // 주입설정량(량*100, 23.25->2325, 15.2->1520) + var snackInjAmount = 0.0 // 현재주입량(량*100, 23.25->2325, 15.2->1520) + var snackSpeed = 0 // 주입속도(1~8) + + + // 11. square(extended) bolus status + var squareStatus = 0 // 주입상태 + var squareTime = 0 // 설정 주입시간(10~300분) + var squareInjTime = 0 // 경과 주입시간(10~300분) + var squareAmount = 0.0 // 주입 설정량 + var squareInjAmount = 0.0 // 현재 주입량 + + + // 12. daul bolus status + var dualStatus = 0 // 주입상태 + var dualAmount = 0.0 // 일반주입 설정량 + var dualInjAmount = 0.0 // 일반주입량 + var dualSquareTime = 0 // 스퀘어주입 설정시간(10~300분) + var dualInjSquareTime = 0 // 스퀘어주입 경과시간(10~300분) + var dualSquareAmount = 0.0 // 스퀘어주입 설정량 + var dualInjSquareAmount = 0.0 // 스퀘어주입량 + + + // 13. last injection status + var recentKind1 = 0 // 최근-1 주입 종류(1=식사, 2=일반간식, 3=스퀘어회식, 4=더블회식) + var recentTime1 = 0 // 최근-1 주입 시간 + var recentAmount1 = 0.0 // 최근-1 주입량 + var recentKind2 = 0 // 최근-2 주입 종류(1=식사, 2=일반간식, 3=스퀘어회식, 4=더블회식) + var recentTime2 = 0 // 최근-2 주입 시간 + var recentAmount2 = 0.0 // 최근-2 주입량 + + + // 14. daily injection status + var todayBaseAmount = 0.0 // 기저주입 총량 + var todayMealAmount = 0.0 // 식사주입 총량 + var todaySnackAmount = 0.0 // 회식주입 총량 + + + // 15. meat setting status + var morningHour = 0 // 아침 개시 시간(0~23) + var morningAmount = 0.0 // 아침 식전량 + var lunchHour = 0 // 점심 개시 시간(0~23) + var lunchAmount = 0.0 // 점심 식전량 + var dinnerHour = 0 // 저녁 개시 시간(0~23) + var dinnerAmount = 0.0 // 저녁 식전량 + + + // 16. basal injection status at this hour + var currentBasePattern = 0 // 패턴 종류 (1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2) + var currentBaseHour = 0 // 현재주입시간(0~23) + var currentBaseTbBeforeAmount = 0.0 // 해당시간의 임시기저 계산 전 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + var currentBaseTbAfterAmount = 0.0 // 해당시간의 임시기저 계산 후 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + + + // 17. saved basal pattern status + var baseAmount1 = 0.00// 주입량 1(량*100, 23.25->2325, 15.2->1520) + var baseAmount2 = 0.0// 주입량 2(량*100, 23.25->2325, 15.2->1520) + var baseAmount3 = 0.0 // 주입량 3(량*100, 23.25->2325, 15.2->1520) + var baseAmount4 = 0.0 // 주입량 4(량*100, 23.25->2325, 15.2->1520) + var baseAmount5 = 0.0 // 주입량 5(량*100, 23.25->2325, 15.2->1520) + var baseAmount6 = 0.0 // 주입량 6(량*100, 23.25->2325, 15.2->1520) + var baseAmount7 = 0.0 // 주입량 7(량*100, 23.25->2325, 15.2->1520) + var baseAmount8 = 0.0 // 주입량 8(량*100, 23.25->2325, 15.2->1520) + var baseAmount9 = 0.0 // 주입량 9(량*100, 23.25->2325, 15.2->1520) + var baseAmount10 = 0.0 // 주입량 10(량*100, 23.25->2325, 15.2->1520) + var baseAmount11 = 0.0 // 주입량 11(량*100, 23.25->2325, 15.2->1520) + var baseAmount12 = 0.0 // 주입량 12(량*100, 23.25->2325, 15.2->1520) + var baseAmount13 = 0.0 // 주입량 13(량*100, 23.25->2325, 15.2->1520) + var baseAmount14 = 0.0 // 주입량 14(량*100, 23.25->2325, 15.2->1520) + var baseAmount15 = 0.0 // 주입량 15(량*100, 23.25->2325, 15.2->1520) + var baseAmount16 = 0.0 // 주입량 16(량*100, 23.25->2325, 15.2->1520) + var baseAmount17 = 0.0 // 주입량 17(량*100, 23.25->2325, 15.2->1520) + var baseAmount18 = 0.0 // 주입량 18(량*100, 23.25->2325, 15.2->1520) + var baseAmount19 = 0.0 // 주입량 19(량*100, 23.25->2325, 15.2->1520) + var baseAmount20 = 0.0 // 주입량 20(량*100, 23.25->2325, 15.2->1520) + var baseAmount21 = 0.0 // 주입량 21(량*100, 23.25->2325, 15.2->1520) + var baseAmount22 = 0.0 // 주입량 22(량*100, 23.25->2325, 15.2->1520) + var baseAmount23 = 0.0 // 주입량 23(량*100, 23.25->2325, 15.2->1520) + var baseAmount24 = 0.0 // 주입량 24(량*100, 23.25->2325, 15.2->1520) + + var otpNumber = 0 + + companion object { + // User settings + const val ALARM = 0 + const val LCD = 1 + const val LANG = 2 + const val BOLUS_SPEED = 3 + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt new file mode 100644 index 0000000000..df908e0bca --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt @@ -0,0 +1,184 @@ +package info.nightscout.androidaps.diaconn.activities + +import android.annotation.SuppressLint +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothDevice +import android.bluetooth.le.BluetoothLeScanner +import android.bluetooth.le.ScanCallback +import android.bluetooth.le.ScanFilter +import android.bluetooth.le.ScanResult +import android.bluetooth.le.ScanSettings +import android.content.pm.ActivityInfo +import android.os.Bundle +import android.os.Handler +import android.os.ParcelUuid +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.TextView +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.diaconn.events.EventDiaconnG8DeviceChange +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.databinding.DiaconnG8BlescannerActivityBinding +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck +import info.nightscout.androidaps.utils.sharedPreferences.SP +import java.util.* +import javax.inject.Inject + +class DiaconnG8BLEScanActivity : NoSplashAppCompatActivity() { + + @Inject lateinit var sp: SP + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var blePreCheck: BlePreCheck + + private var listAdapter: ListAdapter? = null + private val devices = ArrayList() + private var bluetoothLeScanner: BluetoothLeScanner? = null + private val serviceUUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e") // BLE GATT Service UUID + + private lateinit var binding: DiaconnG8BlescannerActivityBinding + + @SuppressLint("SourceLockedOrientationActivity") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DiaconnG8BlescannerActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + + blePreCheck.prerequisitesCheck(this) + + listAdapter = ListAdapter() + binding.blescannerListview.emptyView = binding.blescannerNodevice + binding.blescannerListview.adapter = listAdapter + listAdapter?.notifyDataSetChanged() + } + + override fun onResume() { + super.onResume() + + BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter -> + if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable() + bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner + startScan() + } + } + + override fun onPause() { + super.onPause() + stopScan() + } + + private fun startScan() = + try { + val filters: MutableList = ArrayList() + val scan_filter = ScanFilter.Builder() + .setServiceUuid(ParcelUuid(serviceUUID)) + .build() + filters.add(scan_filter) + + val settings = ScanSettings.Builder() + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) + .build() + + bluetoothLeScanner?.startScan(filters, settings, mBleScanCallback) + } catch (e: IllegalStateException) { + } // ignore BT not on + + private fun stopScan() = + try { + bluetoothLeScanner?.stopScan(mBleScanCallback) + } catch (e: IllegalStateException) { + } // ignore BT not on + + private fun addBleDevice(device: BluetoothDevice?) { + if (device == null || device.name == null || device.name == "") { + return + } + val item = BluetoothDeviceItem(device) + if (devices.contains(item)) { + return + } + devices.add(item) + Handler().post { listAdapter!!.notifyDataSetChanged() } + } + + private val mBleScanCallback: ScanCallback = object : ScanCallback() { + override fun onScanResult(callbackType: Int, result: ScanResult) { + addBleDevice(result.device) + } + } + + internal inner class ListAdapter : BaseAdapter() { + + override fun getCount(): Int = devices.size + override fun getItem(i: Int): BluetoothDeviceItem = devices[i] + override fun getItemId(i: Int): Long = 0 + + override fun getView(i: Int, convertView: View?, parent: ViewGroup?): View { + var v = convertView + val holder: ViewHolder + if (v == null) { + v = View.inflate(applicationContext, R.layout.diaconn_g8_blescanner_item, null) + holder = ViewHolder(v) + v.tag = holder + } else { + // reuse view if already exists + holder = v.tag as ViewHolder + } + val item = getItem(i) + holder.setData(item) + return v!! + } + + private inner class ViewHolder(v: View) : View.OnClickListener { + + private lateinit var item: BluetoothDeviceItem + private val name: TextView = v.findViewById(R.id.ble_name) + private val address: TextView = v.findViewById(R.id.ble_address) + + init { + v.setOnClickListener(this@ViewHolder) + } + + override fun onClick(v: View) { + sp.putString(R.string.key_diaconn_g8_address, item.device.address) + sp.putString(R.string.key_diaconn_g8_name, name.text.toString()) + item.device.createBond() + rxBus.send(EventDiaconnG8DeviceChange()) + finish() + } + + fun setData(data: BluetoothDeviceItem) { + var tTitle = data.device.name + if (tTitle == null || tTitle == "") { + tTitle = "(unknown)" + } + name.text = tTitle + address.text = data.device.address + item = data + } + + } + } + + // + inner class BluetoothDeviceItem internal constructor(val device: BluetoothDevice) { + override fun equals(other: Any?): Boolean { + if (other !is BluetoothDeviceItem) { + return false + } + return stringEquals(device.address, other.device.address) + } + + private fun stringEquals(arg1: String, arg2: String): Boolean { + return try { + arg1 == arg2 + } catch (e: Exception) { + false + } + } + + override fun hashCode(): Int = device.hashCode() + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8HistoryActivity.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8HistoryActivity.kt new file mode 100644 index 0000000000..06ec319cb4 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8HistoryActivity.kt @@ -0,0 +1,257 @@ +package info.nightscout.androidaps.diaconn.activities + +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.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.common.RecordTypes +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryRecord +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryRecordDao +import info.nightscout.androidaps.diaconn.databinding.DiaconnG8HistoryActivityBinding +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.rx.AapsSchedulers + + +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign +import java.util.* +import javax.inject.Inject + +class DiaconnG8HistoryActivity : NoSplashAppCompatActivity() { + + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var diaconnHistoryRecordDao: DiaconnHistoryRecordDao + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var aapsSchedulers: AapsSchedulers + + private val disposable = CompositeDisposable() + + private var showingType = RecordTypes.RECORD_TYPE_ALARM + private var historyList: List = ArrayList() + + class TypeList internal constructor(var type: Byte, var name: String) { + + override fun toString(): String = name + } + + private lateinit var binding: DiaconnG8HistoryActivityBinding + + override fun onResume() { + super.onResume() + disposable += rxBus + .toObservable(EventPumpStatusChanged::class.java) + .observeOn(aapsSchedulers.main) + .subscribe({ binding.status.text = it.getStatus(resourceHelper) }) { fabricPrivacy.logException(it) } + swapAdapter(showingType) + } + + override fun onPause() { + super.onPause() + disposable.clear() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DiaconnG8HistoryActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.recyclerview.setHasFixedSize(true) + binding.recyclerview.layoutManager = LinearLayoutManager(this) + binding.recyclerview.adapter = RecyclerViewAdapter(historyList) + binding.status.visibility = View.GONE + + // Types + val typeList = ArrayList() + typeList.add(TypeList(RecordTypes.RECORD_TYPE_ALARM, resourceHelper.gs(R.string.diaconn_g8_history_alarm))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_BASALHOUR, resourceHelper.gs(R.string.diaconn_g8_history_basalhours))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_BOLUS, resourceHelper.gs(R.string.diaconn_g8_history_bolus))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_TB, resourceHelper.gs(R.string.diaconn_g8_history_tempbasal))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_DAILY, resourceHelper.gs(R.string.diaconn_g8_history_dailyinsulin))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_REFILL, resourceHelper.gs(R.string.diaconn_g8_history_refill))) + typeList.add(TypeList(RecordTypes.RECORD_TYPE_SUSPEND, resourceHelper.gs(R.string.diaconn_g8_history_suspend))) + binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, typeList) + + binding.reload.setOnClickListener { + val selected = binding.spinner.selectedItem as TypeList? + ?: return@setOnClickListener + runOnUiThread { + binding.reload.visibility = View.GONE + binding.status.visibility = View.VISIBLE + } + clearCardView() + commandQueue.loadHistory(selected.type, object : Callback() { + override fun run() { + swapAdapter(selected.type) + runOnUiThread { + binding.reload.visibility = View.VISIBLE + binding.status.visibility = View.GONE + } + } + }) + } + binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + val selected = typeList[position] + swapAdapter(selected.type) + showingType = selected.type + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + clearCardView() + } + } + } + + inner class RecyclerViewAdapter internal constructor(private var historyList: List) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): HistoryViewHolder = + HistoryViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.diaconn_g8_history_item, viewGroup, false)) + + override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { + val record = historyList[position] + holder.time.text = dateUtil.dateAndTimeString(record.timestamp) + holder.value.text = DecimalFormatter.to2Decimal(record.value) + holder.stringValue.text = record.stringValue + holder.bolusType.text = record.bolusType + holder.duration.text = DecimalFormatter.to0Decimal(record.duration.toDouble()) + holder.alarm.text = record.alarm + when (showingType) { + RecordTypes.RECORD_TYPE_ALARM -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.VISIBLE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.GONE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.VISIBLE + } + + RecordTypes.RECORD_TYPE_BOLUS -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.VISIBLE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.VISIBLE + holder.duration.visibility = View.VISIBLE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.GONE + } + + RecordTypes.RECORD_TYPE_DAILY -> { + holder.dailyBasal.text = resourceHelper.gs(R.string.formatinsulinunits, record.dailyBasal) + holder.dailyBolus.text = resourceHelper.gs(R.string.formatinsulinunits, record.dailyBolus) + holder.dailyTotal.text = resourceHelper.gs(R.string.formatinsulinunits, record.dailyBolus + record.dailyBasal) + holder.time.text = dateUtil.dateString(record.timestamp) + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.GONE + holder.stringValue.visibility = View.GONE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.GONE + holder.dailyBasal.visibility = View.VISIBLE + holder.dailyBolus.visibility = View.VISIBLE + holder.dailyTotal.visibility = View.VISIBLE + holder.alarm.visibility = View.GONE + } + + RecordTypes.RECORD_TYPE_BASALHOUR -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.VISIBLE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.GONE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.GONE + } + RecordTypes.RECORD_TYPE_REFILL -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.VISIBLE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.GONE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.GONE + } + + RecordTypes.RECORD_TYPE_TB -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.VISIBLE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.VISIBLE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.GONE + } + + RecordTypes.RECORD_TYPE_SUSPEND -> { + holder.time.visibility = View.VISIBLE + holder.value.visibility = View.GONE + holder.stringValue.visibility = View.VISIBLE + holder.bolusType.visibility = View.GONE + holder.duration.visibility = View.GONE + holder.dailyBasal.visibility = View.GONE + holder.dailyBolus.visibility = View.GONE + holder.dailyTotal.visibility = View.GONE + holder.alarm.visibility = View.GONE + } + } + } + + override fun getItemCount(): Int { + return historyList.size + } + + inner class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + var time: TextView = itemView.findViewById(R.id.diaconn_g8_history_time) + var value: TextView = itemView.findViewById(R.id.diaconn_g8_history_value) + var bolusType: TextView = itemView.findViewById(R.id.diaconn_g8_history_bolustype) + var stringValue: TextView = itemView.findViewById(R.id.diaconn_g8_history_stringvalue) + var duration: TextView = itemView.findViewById(R.id.diaconn_g8_history_duration) + var dailyBasal: TextView = itemView.findViewById(R.id.diaconn_g8_history_dailybasal) + var dailyBolus: TextView = itemView.findViewById(R.id.diaconn_g8_history_dailybolus) + var dailyTotal: TextView = itemView.findViewById(R.id.diaconn_g8_history_dailytotal) + var alarm: TextView = itemView.findViewById(R.id.diaconn_g8_history_alarm) + } + } + + private fun swapAdapter(type: Byte) { + disposable += diaconnHistoryRecordDao + .allFromByType(dateUtil.now() - T.months(1).msecs(), type) + .subscribeOn(aapsSchedulers.io) + .observeOn(aapsSchedulers.main) + .subscribe { historyList -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(historyList), false) } + } + + private fun clearCardView() = binding.recyclerview.swapAdapter(RecyclerViewAdapter(ArrayList()), false) +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8UserOptionsActivity.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8UserOptionsActivity.kt new file mode 100644 index 0000000000..4ec3c4b3a2 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8UserOptionsActivity.kt @@ -0,0 +1,192 @@ +package info.nightscout.androidaps.diaconn.activities + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import info.nightscout.androidaps.activities.ErrorHelperActivity +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity + + +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.databinding.DiaconnG8UserOptionsActivityBinding + +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.ToastUtils +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import java.text.DecimalFormat +import javax.inject.Inject + +class DiaconnG8UserOptionsActivity : NoSplashAppCompatActivity() { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var context: Context + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var sp: SP + + private val disposable = CompositeDisposable() + + private lateinit var binding: DiaconnG8UserOptionsActivityBinding + + @Synchronized + override fun onResume() { + super.onResume() + } + + @Synchronized + override fun onPause() { + disposable.clear() + super.onPause() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DiaconnG8UserOptionsActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.saveAlarm.setOnClickListener { onSaveAlarmClick() } + binding.saveLcdOnTime.setOnClickListener { onSavelcdOnTimeClick() } + binding.saveLang.setOnClickListener { onSaveLangClick() } + + binding.saveBolusSpeed.setOnClickListener { onSaveBolusSpeedClick() } + + val spBolusSpeed = sp.getString("g8_bolusspeed", "5") + + binding.bolusSpeed.setParams(spBolusSpeed.toDouble(), 1.0, 8.0, 1.0, DecimalFormat("1"), true, binding.saveBolusSpeed) + + aapsLogger.debug(LTag.PUMP, + "UserOptionsLoaded:" + (System.currentTimeMillis() - diaconnG8Pump.lastConnection) / 1000 + " s ago" + + "\nbeepAndAlarm:" + diaconnG8Pump.beepAndAlarm + + "\nalarmIntesity:" + diaconnG8Pump.alarmIntesity + + "\nlanguage:" + diaconnG8Pump.selectedLanguage + + "\nlcdOnTimeSec:" + diaconnG8Pump.lcdOnTimeSec) + + fillSoundCategory() + fillSoundSubCategory() + + binding.beepAndAlarm.setSelection(diaconnG8Pump.beepAndAlarm - 1) + binding.alarmIntesity.setSelection(diaconnG8Pump.alarmIntesity - 1) + + binding.beepAndAlarm.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + binding.alarmIntesity.visibility = if("silent" == binding.beepAndAlarm.getItemAtPosition(position).toString()) View.GONE else View.VISIBLE + } + override fun onNothingSelected(parent: AdapterView<*>?) {} + } + + when (diaconnG8Pump.lcdOnTimeSec) { + 1 -> binding.pumpscreentimeout10.isChecked = true + 2 -> binding.pumpscreentimeout20.isChecked = true + 3 -> binding.pumpscreentimeout30.isChecked = true + } + + when (diaconnG8Pump.selectedLanguage) { + 1 -> binding.pumplangChiness.isChecked = true + 2 -> binding.pumplangKorean.isChecked = true + 3 -> binding.pumplangEnglish.isChecked = true + } + } + + private fun onSaveAlarmClick() { + + diaconnG8Pump.setUserOptionType = DiaconnG8Pump.ALARM + + diaconnG8Pump.beepAndAlarm = binding.beepAndAlarm.selectedItemPosition + 1 + diaconnG8Pump.alarmIntesity = binding.alarmIntesity.selectedItemPosition + 1 + + onSaveClick() + } + + private fun onSavelcdOnTimeClick() { + + diaconnG8Pump.setUserOptionType = DiaconnG8Pump.LCD + + diaconnG8Pump.lcdOnTimeSec = when { + binding.pumpscreentimeout10.isChecked -> 1 + binding.pumpscreentimeout20.isChecked -> 2 + binding.pumpscreentimeout30.isChecked -> 3 + else -> 1 + } + + onSaveClick() + } + + private fun onSaveLangClick() { + + diaconnG8Pump.setUserOptionType = DiaconnG8Pump.LANG + + diaconnG8Pump.selectedLanguage = when { + binding.pumplangChiness.isChecked -> 1 + binding.pumplangKorean.isChecked -> 2 + binding.pumplangEnglish.isChecked -> 3 + else -> 2 + } + + onSaveClick() + } + + private fun onSaveBolusSpeedClick() { + val intSpeed = binding.bolusSpeed.value.toInt() + + diaconnG8Pump.bolusSpeed = intSpeed + diaconnG8Pump.speed = intSpeed + diaconnG8Pump.setUserOptionType = DiaconnG8Pump.BOLUS_SPEED + sp.putString("g8_bolusspeed", intSpeed.toString()) + sp.putBoolean("diaconn_g8_isbolusspeedsync", false) + + ToastUtils.okToast(context, "Save Success!") + } + + private fun onSaveClick() { + commandQueue.setUserOptions(object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(context, ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", resourceHelper.gs(R.string.pumperror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(i) + } + } + }) + finish() + } + + private fun fillSoundCategory() { + val categories = ArrayList() + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_sound)) + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_vibrate)) + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_silent)) + context.let { context -> + val adapterCategories = ArrayAdapter(context, R.layout.spinner_centered, categories) + binding.beepAndAlarm.adapter = adapterCategories + } + } + + private fun fillSoundSubCategory() { + val categories = ArrayList() + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_intensity_low)) + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_intensity_middle)) + categories.add(resourceHelper.gs(R.string.diaconn_g8_pumpalarm_intensity_high)) + context.let { context -> + val adapterCategories = ArrayAdapter(context, R.layout.spinner_centered, categories) + binding.alarmIntesity.adapter = adapterCategories + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/common/RecordTypes.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/common/RecordTypes.kt new file mode 100644 index 0000000000..e4fbc8122d --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/common/RecordTypes.kt @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.diaconn.common + +object RecordTypes { + const val RECORD_TYPE_BOLUS = 0x01.toByte() + const val RECORD_TYPE_DAILY = 0x02.toByte() + const val RECORD_TYPE_ALARM = 0x03.toByte() + const val RECORD_TYPE_REFILL = 0x04.toByte() + const val RECORD_TYPE_SUSPEND = 0x05.toByte() + const val RECORD_TYPE_BASALHOUR = 0x06.toByte() + const val RECORD_TYPE_TB = 0x07.toByte() +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryDatabase.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryDatabase.kt new file mode 100644 index 0000000000..38a082133a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryDatabase.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.database + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +const val TABLE_DIACONN_HISTORY = "diaconnHistory" + +@Database( + entities = [DiaconnHistoryRecord::class], + exportSchema = true, + version = DiaconnHistoryDatabase.VERSION +) +abstract class DiaconnHistoryDatabase : RoomDatabase() { + + abstract fun historyRecordDao(): DiaconnHistoryRecordDao + + companion object { + + const val VERSION = 1 + + fun build(context: Context) = + Room.databaseBuilder( + context.applicationContext, + DiaconnHistoryDatabase::class.java, + "diaconn_database.db" + ) + .fallbackToDestructiveMigration() + .build() + } +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecord.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecord.kt new file mode 100644 index 0000000000..46d7e28e89 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecord.kt @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.diaconn.database + +import androidx.room.Entity +import androidx.room.Index +import androidx.room.PrimaryKey + +@Entity(tableName = TABLE_DIACONN_HISTORY, + indices = [Index("code", "timestamp")]) +data class DiaconnHistoryRecord( + @PrimaryKey var timestamp: Long, + var code: Byte = 0x0F, + var value: Double = 0.0, + var bolusType: String = "None", + var stringValue: String = "", + var duration: Int = 0, + var dailyBasal: Double = 0.0, + var dailyBolus: Double = 0.0, + var alarm: String = "" +) diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecordDao.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecordDao.kt new file mode 100644 index 0000000000..127be05acd --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/database/DiaconnHistoryRecordDao.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.diaconn.database + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.reactivex.Single + +@Dao +abstract class DiaconnHistoryRecordDao { + + @Query("SELECT * from $TABLE_DIACONN_HISTORY WHERE timestamp >= :timestamp AND code = :type") + abstract fun allFromByType(timestamp: Long, type: Byte): Single> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun createOrUpdate(diaconnHistoryRecord: DiaconnHistoryRecord) +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ActivitiesModule.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ActivitiesModule.kt new file mode 100644 index 0000000000..8a39b928a0 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ActivitiesModule.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.diaconn.di + +import dagger.Module +import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Fragment +import info.nightscout.androidaps.diaconn.activities.DiaconnG8BLEScanActivity +import info.nightscout.androidaps.diaconn.activities.DiaconnG8HistoryActivity +import info.nightscout.androidaps.diaconn.activities.DiaconnG8UserOptionsActivity + +@Module +@Suppress("unused") +abstract class DiaconnG8ActivitiesModule { + @ContributesAndroidInjector abstract fun contributesDiaconnG8Fragment(): DiaconnG8Fragment + @ContributesAndroidInjector abstract fun contributesDiaconnG8HistoryActivity(): DiaconnG8HistoryActivity + @ContributesAndroidInjector abstract fun contributesDiaconnG8UserOptionsActivity(): DiaconnG8UserOptionsActivity + @ContributesAndroidInjector abstract fun contributesDiaconnG8BLEScanActivity(): DiaconnG8BLEScanActivity +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8Module.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8Module.kt new file mode 100644 index 0000000000..870d460bf0 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8Module.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.diaconn.di + +import dagger.Module + +@Module(includes = [ + DiaconnG8ActivitiesModule::class, + DiaconnG8ServiceModule::class, + DiaconnG8PacketModule::class, + DiaconnHistoryModule::class +]) + +open class DiaconnG8Module \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8PacketModule.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8PacketModule.kt new file mode 100644 index 0000000000..65e252098a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8PacketModule.kt @@ -0,0 +1,81 @@ +package info.nightscout.androidaps.diaconn.di + +import dagger.Module +import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.diaconn.packet.* + +@Module +@Suppress("unused") +abstract class DiaconnG8PacketModule { + @ContributesAndroidInjector abstract fun contributesDiaconnG8Packet(): DiaconnG8Packet + @ContributesAndroidInjector abstract fun contributesAppCancelSettingPacket(): AppCancelSettingPacket + @ContributesAndroidInjector abstract fun contributesAppCancelSettingResponsePacket(): AppCancelSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesAppConfirmSettingPacket(): AppConfirmSettingPacket + @ContributesAndroidInjector abstract fun contributesAppConfirmSettingResponsePacket(): AppConfirmSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesSneckLimitInquirePacket(): SneckLimitInquirePacket + @ContributesAndroidInjector abstract fun contributesBasalLimitInquirePacket(): BasalLimitInquirePacket + @ContributesAndroidInjector abstract fun contributesSneckLimitInquireResponsePacket(): SneckLimitInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesBasalLimitInquireResponsePacket(): BasalLimitInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesBasalPauseReportPacket(): BasalPauseReportPacket + @ContributesAndroidInjector abstract fun contributesBasalPauseSettingPacket(): BasalPauseSettingPacket + @ContributesAndroidInjector abstract fun contributesBasalPauseSettingResponsePacket(): BasalPauseSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesBasalSettingPacket(): BasalSettingPacket + @ContributesAndroidInjector abstract fun contributesBasalSettingReportPacket(): BasalSettingReportPacket + @ContributesAndroidInjector abstract fun contributesBasalSettingResponsePacket(): BasalSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesBigMainInfoInquirePacket(): BigMainInfoInquirePacket + @ContributesAndroidInjector abstract fun contributesBigMainInfoInquireResponsePacket(): BigMainInfoInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesBigLogInquirePacket(): BigLogInquirePacket + @ContributesAndroidInjector abstract fun contributesBigLogInquireResponsePacket(): BigLogInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesConfirmReportPacket(): ConfirmReportPacket + @ContributesAndroidInjector abstract fun contributesInjectionBasalSettingPacket(): InjectionBasalSettingPacket + @ContributesAndroidInjector abstract fun contributesInjectionBasalSettingResponsePacket(): InjectionBasalSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionSnackResultReportPacket(): InjectionSnackResultReportPacket + @ContributesAndroidInjector abstract fun contributesInjectionSnactSettingPacket(): InjectionSnackSettingPacket + @ContributesAndroidInjector abstract fun contributesInjectionSnackSettingResponsePacket(): InjectionSnackSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionExtendedBolusResultReportPacket(): InjectionExtendedBolusResultReportPacket + @ContributesAndroidInjector abstract fun contributesInjectionExtendedBolusSettingPacket(): InjectionExtendedBolusSettingPacket + @ContributesAndroidInjector abstract fun contributesInjectionExtendedBolusSettingResponsePacket(): InjectionExtendedBolusSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionBasalReportPacket(): InjectionBasalReportPacket + @ContributesAndroidInjector abstract fun contributesInjectionSnackInquirePacket(): InjectionSnackInquirePacket + @ContributesAndroidInjector abstract fun contributesInjectionSnackInquireResponsePacket(): InjectionSnackInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesRejectReportPacket(): RejectReportPacket + @ContributesAndroidInjector abstract fun contributesTempBasalReportPacket(): TempBasalReportPacket + @ContributesAndroidInjector abstract fun contributesTempBasalSettingPacket(): TempBasalSettingPacket + @ContributesAndroidInjector abstract fun contributesTempBasalSettingResponsePacket(): TempBasalSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesTempBasalInquirePacket(): TempBasalInquirePacket + @ContributesAndroidInjector abstract fun contributesTempBasalInquireResponsePacket(): TempBasalInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesTimeInquirePacket(): TimeInquirePacket + @ContributesAndroidInjector abstract fun contributesTimeInquireResponsePacket(): TimeInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesTimeReportPacket(): TimeReportPacket + @ContributesAndroidInjector abstract fun contributesTimeSettingPacket(): TimeSettingPacket + @ContributesAndroidInjector abstract fun contributesTimeSettingResponsePacket(): TimeSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesLogStatusInquirePacket(): LogStatusInquirePacket + @ContributesAndroidInjector abstract fun contributesLogStatusInquireResponsePacket(): LogStatusInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionCancelSettingPacket(): InjectionCancelSettingPacket + @ContributesAndroidInjector abstract fun contributesInjectionCancelSettingResponsePacket(): InjectionCancelSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesSoundSettingPacket(): SoundSettingPacket + @ContributesAndroidInjector abstract fun contributesSoundSettingResponsePacket(): SoundSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesDisplayTimeoutSettingPacket(): DisplayTimeoutSettingPacket + @ContributesAndroidInjector abstract fun contributesDisplayTimeoutSettingResponsePacket(): DisplayTimeoutSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesLanguageSettingPacket(): LanguageSettingPacket + @ContributesAndroidInjector abstract fun contributesLanguageSettingResponsePacket(): LanguageSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionBlockReportPacket(): InjectionBlockReportPacket + @ContributesAndroidInjector abstract fun contributesBatteryWarningReportPacket(): BatteryWarningReportPacket + @ContributesAndroidInjector abstract fun contributesInsulinLackReportPacket(): InsulinLackReportPacket + @ContributesAndroidInjector abstract fun contributesIncarnationInquirePacket(): IncarnationInquirePacket + @ContributesAndroidInjector abstract fun contributesIncarnationInquireResponsePacket(): IncarnationInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesBolusSpeedSettingPacket(): BolusSpeedSettingPacket + @ContributesAndroidInjector abstract fun contributesBolusSpeedSettingResponsePacket(): BolusSpeedSettingResponsePacket + @ContributesAndroidInjector abstract fun contributesInjectionSpeedInquirePacket(): BolusSpeedInquirePacket + @ContributesAndroidInjector abstract fun contributesInjectionSpeedInquireResponsePacket(): BolusSpeedInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesBolusSpeedSettingReportPacket(): BolusSpeedSettingReportPacket + @ContributesAndroidInjector abstract fun contributesSoundInquirePacket(): SoundInquirePacket + @ContributesAndroidInjector abstract fun contributesSoundInquireResponsePacket(): SoundInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesDisplayTimeInquirePacket(): DisplayTimeInquirePacket + @ContributesAndroidInjector abstract fun contributesDisplayTimeInquireResponsePacket(): DisplayTimeInquireResponsePacket + @ContributesAndroidInjector abstract fun contributesLanguageInquirePacket(): LanguageInquirePacket + @ContributesAndroidInjector abstract fun contributesLanguageInquireResponsePacket(): LanguageInquireResponsePacket + + + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ServiceModule.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ServiceModule.kt new file mode 100644 index 0000000000..ecc84e13d7 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnG8ServiceModule.kt @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.diaconn.di + +import dagger.Module +import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.diaconn.service.DiaconnG8Service + +@Module +@Suppress("unused") +abstract class DiaconnG8ServiceModule { + @ContributesAndroidInjector abstract fun contributesDiaconnG8Service(): DiaconnG8Service +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnHistoryModule.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnHistoryModule.kt new file mode 100644 index 0000000000..fed5f0ed58 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/di/DiaconnHistoryModule.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.diaconn.di + +import android.content.Context +import dagger.Module +import dagger.Provides +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryRecordDao +import javax.inject.Singleton + +@Module +class DiaconnHistoryModule { + + @Provides + @Singleton + internal fun provideDatabase(context: Context): DiaconnHistoryDatabase = DiaconnHistoryDatabase.build(context) + + @Provides + @Singleton + internal fun provideHistoryRecordDao(diaconnHistoryDatabase: DiaconnHistoryDatabase): DiaconnHistoryRecordDao = + diaconnHistoryDatabase.historyRecordDao() +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8DeviceChange.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8DeviceChange.kt new file mode 100644 index 0000000000..a4c565ec9d --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8DeviceChange.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.diaconn.events + +import info.nightscout.androidaps.events.Event + +class EventDiaconnG8DeviceChange : Event() \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8NewStatus.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8NewStatus.kt new file mode 100644 index 0000000000..b275db0111 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/events/EventDiaconnG8NewStatus.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.diaconn.events + +import info.nightscout.androidaps.events.Event + +class EventDiaconnG8NewStatus : Event() diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingPacket.kt new file mode 100644 index 0000000000..a3cfaed4ce --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * AppCancelSettingPacket + */ +class AppCancelSettingPacket( + injector: HasAndroidInjector, + private var reqMsgType: Byte, +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x29 + aapsLogger.debug(LTag.PUMPCOMM, "AppCancelSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(reqMsgType) // 명령코드 + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_APP_CANCEL_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingResponsePacket.kt new file mode 100644 index 0000000000..bdba88b35f --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppCancelSettingResponsePacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * AppCancelSettingResponsePacket + */ +class AppCancelSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result =0 + init { + msgType = 0xA9.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "AppCancelSettingResPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "AppCancelSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${result}") + } + + + override fun getFriendlyName(): String { + return "PUMP_APP_CANCEL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingPacket.kt new file mode 100644 index 0000000000..d0805f6a5f --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingPacket.kt @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * AppConfirmSettingPacket + */ +class AppConfirmSettingPacket( + injector: HasAndroidInjector, + private var reqMsgType: Byte, // 명령코드 + private var otp: Int // 응답시 전달받은 opt (random 6 digit numbner) +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x37 + aapsLogger.debug(LTag.PUMPCOMM, "AppConfirmSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + + buffer.put(reqMsgType) // 명령코드 + buffer.putInt(otp) // 응답시 전달받은 opt (random 6digit numbner) + + aapsLogger.debug(LTag.PUMPCOMM, "reqMsgType -> ${reqMsgType}") + aapsLogger.debug(LTag.PUMPCOMM, "otp -> ${otp}") + + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_APP_CONFRIM_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingResponsePacket.kt new file mode 100644 index 0000000000..096516e501 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/AppConfirmSettingResponsePacket.kt @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * AppConfirmSettingResponsePacket + */ +class AppConfirmSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result =0 + init { + msgType = 0xB7.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "AppConfirmSettingReqPacket Response ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "AppConfirmSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${result}") + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + } + + override fun getFriendlyName(): String { + return "PUMP_APP_CONFIRM_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquirePacket.kt new file mode 100644 index 0000000000..36a484cf4a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalLimitInquirePacket + */ +class BasalLimitInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x52.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalLimitInquirePacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_LIMIT_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquireResponsePacket.kt new file mode 100644 index 0000000000..26bb9a78ab --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalLimitInquireResponsePacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalLimitInquireResponsePacket + */ +class BasalLimitInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x92.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalLimitInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BasalLimitInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + diaconnG8Pump.maxBasalPerHours = getShortToInt(bufferData).toDouble() / 100.0 // not include tempbasal limit + diaconnG8Pump.maxBasal = diaconnG8Pump.maxBasalPerHours * 2 // include tempbasal + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "maxBasal --> ${diaconnG8Pump.maxBasal}") + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_LIMIT_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseReportPacket.kt new file mode 100644 index 0000000000..f1aac0371b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseReportPacket.kt @@ -0,0 +1,37 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalPauseReportPacket + */ +class BasalPauseReportPacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var status:Int? = null + + init { + msgType = 0xC3.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalPauseReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BasalPauseReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + status = getByteToInt(bufferData) //(1: pauseed, 2: pause cancel) + aapsLogger.debug(LTag.PUMPCOMM, "status --> ${status}") + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_PAUSE_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingPacket.kt new file mode 100644 index 0000000000..69c88187e9 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * Basal Pause Setting Packet + */ +class BasalPauseSettingPacket( + injector: HasAndroidInjector, + private var status:Int //(1:pause, 2: cancel pause) +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x03 + aapsLogger.debug(LTag.PUMPCOMM, "BasalPauseSettingPacket Init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + buffer.put(status.toByte()) // (1:pause, 2: cancel pause) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_PAUSE_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingResponsePacket.kt new file mode 100644 index 0000000000..649ed7ff5e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalPauseSettingResponsePacket.kt @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalPauseSettingResponsePacket + */ +class BasalPauseSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + + init { + msgType = 0x83.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalPauseSettingResponsePacket Init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BasalPauseSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${result}") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_PAUSE_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingPacket.kt new file mode 100644 index 0000000000..f5ddbbdaa8 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingPacket.kt @@ -0,0 +1,54 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalSettingPacket + */ +class BasalSettingPacket( + injector: HasAndroidInjector, + private var pattern: Int, // pattern(1=basic, 2=life1, 3=life2, 4=life3, 5=dr1, 6=dr2) + private var group: Int, //hour group (1=00~05, 2=06~11, 3=12~17, 4=18~23) + private var amount1: Int, + private var amount2: Int, + private var amount3: Int, + private var amount4: Int, + private var amount5: Int, + private var amount6: Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x0B + aapsLogger.debug(LTag.PUMPCOMM, "Setting new basal rates for profile") + + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = if (group == 4) { + // 마지막 그룹일때 + prefixEncode(msgType, msgSeq, MSG_CON_END) + } else { + // 1, 2, 3 그룹일때 + prefixEncode(msgType, msgSeq, MSG_CON_CONTINUE) + } + buffer.put(pattern.toByte()) // 패턴 종류 (1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2) + buffer.put(group.toByte()) // 그룹 (1=00~05, 2=06~11, 3=12~17, 4=18~23) + buffer.putShort(amount1.toShort()) // 주입량 1 + buffer.putShort(amount2.toShort()) // 주입량 2 + buffer.putShort(amount3.toShort()) // 주입량 3 + buffer.putShort(amount4.toShort()) // 주입량 4 + buffer.putShort(amount5.toShort()) // 주입량 5 + buffer.putShort(amount6.toShort()) // 주입량 6 + + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingReportPacket.kt new file mode 100644 index 0000000000..3f28ffd3e8 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingReportPacket.kt @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalSettingReportPacket + */ +class BasalSettingReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + + init { + msgType = 0xCB.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalSettingReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BasalSettingReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + // no Response + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_SETTING_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingResponsePacket.kt new file mode 100644 index 0000000000..10ee5d139a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BasalSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BasalSettingResponsePacket + */ +class BasalSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + + init { + msgType = 0x8B.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BasalSettingResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BasalSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_BASAL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BatteryWarningReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BatteryWarningReportPacket.kt new file mode 100644 index 0000000000..260a5d7e02 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BatteryWarningReportPacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BatteryWarningReportPacket + */ +class BatteryWarningReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0xD7.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BatteryWarningReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BatteryWarningReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.batteryWaningGrade = getByteToInt(bufferData) + diaconnG8Pump.batteryWaningProcess = getByteToInt(bufferData) + diaconnG8Pump.batteryWaningRemain = getByteToInt(bufferData) + + aapsLogger.debug(LTag.PUMPCOMM, "batteryWaningGrade --> ${diaconnG8Pump.batteryWaningGrade} (1:info, 2: warning , 3: major , 4: critical)") + aapsLogger.debug(LTag.PUMPCOMM, "batteryWaningProcess --> ${diaconnG8Pump.batteryWaningProcess} (1:skip, 2: stop , 3: ignore ) ") + aapsLogger.debug(LTag.PUMPCOMM, "batteryWaningRemain --> ${diaconnG8Pump.batteryWaningRemain} (0~100%) )") + + } + + override fun getFriendlyName(): String { + return "PUMP_BATTERY_WARNING_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquirePacket.kt new file mode 100644 index 0000000000..6a0bc9e4cb --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquirePacket.kt @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + + * BigLogInquirePacket + */ +class BigLogInquirePacket( + injector: HasAndroidInjector, + private val start: Int, + private val end:Int, + private val delay:Int +) : DiaconnG8Packet(injector ) { + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x72 + aapsLogger.debug(LTag.PUMPCOMM, "BigLogInquirePacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.putShort(start.toShort()) + buffer.putShort(end.toShort()) + buffer.put(delay.toByte()) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BIG_LOG_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquireResponsePacket.kt new file mode 100644 index 0000000000..d703cf70e8 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigLogInquireResponsePacket.kt @@ -0,0 +1,774 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.common.RecordTypes +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryRecord +import info.nightscout.androidaps.diaconn.database.DiaconnHistoryRecordDao +import info.nightscout.androidaps.diaconn.pumplog.* +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.apache.commons.lang3.time.DateUtils +import org.joda.time.DateTime +import javax.inject.Inject + +/** + * BigLogInquireResponsePacket + */ +class BigLogInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector) { + + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Inject lateinit var temporaryBasalStorage: TemporaryBasalStorage + @Inject lateinit var sp: SP + @Inject lateinit var pumpSync: PumpSync + @Inject lateinit var diaconnHistoryRecordDao: DiaconnHistoryRecordDao + var result = 0// 조회결과 + private var pumpDesc = PumpDescription(PumpType.DIACONN_G8) + init { + msgType = 0xb2.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BigLogInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BigLogInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) // 데이타 영역 15바이트 버퍼 + val result2 = getByteToInt(bufferData) // 조회결과 1 byte + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + val logLength = getByteToInt(bufferData) // 로그의 갯수. 1byte + + // initalize + val dailyMaxvalInfo = mutableMapOf>() + dailyMaxvalInfo[""] = mutableMapOf() + + // 15 byte를 로그갯수만큼 돌기. + for(i in 0 until logLength) { + val wrapingCount = getByteToInt(bufferData) // 1byte + val logNum = getShortToInt(bufferData) // 2byte + // log Data Parsing + val logdata = byteArrayOf( + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData), + PumplogUtil.getByte(bufferData) + ) + + diaconnG8Pump.apsWrappingCount = wrapingCount + diaconnG8Pump.apslastLogNum = logNum + sp.putInt(resourceHelper.gs(R.string.apslastLogNum), logNum) + sp.putInt(resourceHelper.gs(R.string.apsWrappingCount), wrapingCount) + + // process Log to DB + val logDataToHexString = toNarrowHex(logdata) + val pumplogKind: Byte = PumplogUtil.getKind(logDataToHexString) + var status: String + val diaconnG8HistoryRecord = DiaconnHistoryRecord(0) + when(pumplogKind) { + + LOG_INJECT_MEAL_SUCCESS.LOG_KIND -> { // 8(식사주입성공) + val logItem = LOG_INJECT_MEAL_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(logDateTime, logItem.injectAmount / 100.0) + + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.injectAmount / 100.0, + type = detailedBolusInfo?.bolusType, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT MEALBOLUS (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Bolus: " + logItem.injectAmount / 100.0 + "U ") + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "M" // meal bolus + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logmealsuccess) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "MEALBOLUSSUCCESS" + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_MEAL_FAIL.LOG_KIND -> { + val logItem = LOG_INJECT_MEAL_FAIL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(logDateTime, logItem.injectAmount / 100.0) + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.injectAmount / 100.0, + type = detailedBolusInfo?.bolusType, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT MEALBOLUS (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Bolus: " + logItem.injectAmount / 100.0 + "U ") + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = if ((logItem.injectAmount / 100.0) < 0) 0.0 else (logItem.injectAmount / 100.0) + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "M" // Meal bolus + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logmealfail) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "MEALBOLUSFAIL " + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_NORMAL_SUCCESS.LOG_KIND -> { + val logItem = LOG_INJECT_NORMAL_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(logDateTime, logItem.injectAmount / 100.0) + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.injectAmount / 100.0, + type = detailedBolusInfo?.bolusType, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Bolus: " + logItem.injectAmount / 100.0 + "U ") + + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "B" // bolus + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logsuccess) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "BOLUSSUCCESS" + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_NORMAL_FAIL.LOG_KIND -> { + val logItem = LOG_INJECT_NORMAL_FAIL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + // APS DB process + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(logDateTime, logItem.injectAmount / 100.0) + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.injectAmount / 100.0, + type = detailedBolusInfo?.bolusType, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT BOLUS (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Bolus: " + logItem.injectAmount / 100.0 + "U ") + + + // Diaconn History Process + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = if ((logItem.injectAmount / 100.0) < 0) 0.0 else (logItem.injectAmount / 100.0) + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "B" // bolus + diaconnG8HistoryRecord.stringValue = getReasonName(pumplogKind, logItem.reason) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "BOLUSFAIL " + dateUtil.timeString(logDateTime) + } + + LOG_SET_SQUARE_INJECTION.LOG_KIND -> { + val logItem = LOG_SET_SQUARE_INJECTION.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.setAmount / 100.0, + duration = T.mins((logItem.getInjectTime() * 10).toLong()).msecs(), + isEmulatingTB = false, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTART (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Amount: " + logItem.setAmount / 100.0 + "U Duration: " + logItem.getInjectTime() * 10 + "min") + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.setAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logsquarestart) + diaconnG8HistoryRecord.bolusType = "E" // Extended + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "EXTENDEDBOLUSSTART " + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_SQUARE_SUCCESS.LOG_KIND -> { + val logItem = LOG_INJECT_SQUARE_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logsquaresuccess) + diaconnG8HistoryRecord.bolusType = "E" // Extended + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "EXTENDEDBOLUSEND " + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_SQUARE_FAIL.LOG_KIND -> { + val logItem = LOG_INJECT_SQUARE_FAIL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val newRecord = pumpSync.syncStopExtendedBolusWithPumpId( + timestamp = logDateTime, + endPumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTOP (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Delivered: " + logItem.injectAmount / 100.0 + "U RealDuration: " + logItem.getInjectTime() + "min") + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.stringValue = getReasonName(pumplogKind, logItem.reason) + diaconnG8HistoryRecord.bolusType = "E" + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "EXTENDEDBOLUSFAIL " + dateUtil.timeString(logDateTime) + } + + LOG_SET_DUAL_INJECTION.LOG_KIND -> { + val logItem = LOG_SET_DUAL_INJECTION.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + // dual square 처리. + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.setSquareAmount / 100.0, + duration = T.mins((logItem.getInjectTime() * 10).toLong()).msecs(), + isEmulatingTB = false, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT EXTENDEDSTART (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Amount: " + logItem.setSquareAmount / 100.0 + "U Duration: " + logItem.getInjectTime() * 10 + "min") + + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.setSquareAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() * 10 // (1~30) 1:10min 30:300min + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logdualsquarestart) + diaconnG8HistoryRecord.bolusType = "D" // Extended + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + + status = "DUALEXTENTEDSTART " + dateUtil.timeString(logDateTime) + } + + LOG_INJECTION_DUAL_NORMAL.LOG_KIND -> { + val logItem = LOG_INJECTION_DUAL_NORMAL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(logDateTime, logItem.injectAmount / 100.0) + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = logDateTime, + amount = logItem.injectAmount / 100.0, + type = detailedBolusInfo?.bolusType, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT DUALBOLUS (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Bolus: " + logItem.injectAmount / 100.0 + "U Duration: " + logItem.getInjectTime() + "min") + + //Diaconn History + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "D" // bolus + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logdualnormalsuccess) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "DUALBOLUS" + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_DUAL_SUCCESS.LOG_KIND -> { + val logItem = LOG_INJECT_DUAL_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectSquareAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "D" + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logdualsquaresuccess) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "DUALBOLUS SQUARESUCCESS " + dateUtil.timeString(logDateTime) + } + + LOG_INJECT_DUAL_FAIL.LOG_KIND -> { + val logItem = LOG_INJECT_DUAL_FAIL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BOLUS + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.injectNormAmount / 100.0 + logItem.injectSquareAmount / 100.0 + diaconnG8HistoryRecord.duration = logItem.getInjectTime() + diaconnG8HistoryRecord.bolusType = "D" + diaconnG8HistoryRecord.stringValue = getReasonName(pumplogKind, logItem.reason) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "DUALBOLUS FAIL " + dateUtil.timeString(logDateTime) + } + + LOG_INJECTION_1HOUR_BASAL.LOG_KIND -> { + val logItem = LOG_INJECTION_1HOUR_BASAL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_BASALHOUR + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.beforeAmount / 100.0 + diaconnG8HistoryRecord.stringValue = "TB before: ${logItem.beforeAmount / 100.0} / TB after: ${logItem.afterAmount / 100.0}" + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "1HOUR BASAL " + dateUtil.dateAndTimeString(logDateTime) + } + + LOG_SUSPEND_V2.LOG_KIND -> { + val logItem = LOG_SUSPEND_V2.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_SUSPEND + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_lgosuspend, logItem.getBasalPattern()) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "SUSPEND " + dateUtil.timeString(logDateTime) + } + + LOG_SUSPEND_RELEASE_V2.LOG_KIND -> { + val logItem = LOG_SUSPEND_RELEASE_V2.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_SUSPEND + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_lgorelease, logItem.getBasalPattern()) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "SUSPENDRELEASE " + dateUtil.timeString(logDateTime) + } + + LOG_CHANGE_INJECTOR_SUCCESS.LOG_KIND -> { + val logItem = LOG_CHANGE_INJECTOR_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + if (sp.getBoolean(R.string.key_diaconn_g8_loginsulinchange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = logDateTime, + type = DetailedBolusInfo.EventType.INSULIN_CHANGE, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString() + ) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT INSULINCHANGE(" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Amount: " + logItem.remainAmount / 100.0 + "U") + } + + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_REFILL + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.remainAmount / 100.0 + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_loginjectorprime, logItem.primeAmount / 100.0) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "INSULINCHANGE " + dateUtil.timeString(logDateTime) + } + + LOG_CHANGE_TUBE_SUCCESS.LOG_KIND -> { + val logItem = LOG_CHANGE_TUBE_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + if (sp.getBoolean(R.string.key_diaconn_g8_logtubechange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = logDateTime, + type = DetailedBolusInfo.EventType.NOTE, + note = resourceHelper.gs(R.string.diaconn_g8_logtubeprime, logItem.primeAmount / 100.0), + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString() + ) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT TUBECHANGE(" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Amount: " + logItem.primeAmount / 100.0 + "U") + } + + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_REFILL + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.remainAmount / 100.0 + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logtubeprime, logItem.primeAmount / 100.0) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "TUBECHANGE " + dateUtil.timeString(logDateTime) + } + + LOG_INJECTION_1DAY.LOG_KIND -> { // Daily Bolus Log + val logItem = LOG_INJECTION_1DAY.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_DAILY + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.dailyBolus = logItem.extAmount / 100.0 + logItem.mealAmount / 100.0 + + val recordDateStr = "" + diaconnG8HistoryRecord.timestamp + var recordMap: MutableMap = mutableMapOf("dummy" to 0.0) + + if (dailyMaxvalInfo.containsKey(recordDateStr)) { + recordMap = dailyMaxvalInfo[recordDateStr]!! + } else { + recordMap["bolus"] = 0.0 + recordMap["basal"] = 0.0 + dailyMaxvalInfo[recordDateStr] = recordMap + } + + if (diaconnG8HistoryRecord.dailyBolus > recordMap["bolus"]!!) { + recordMap["bolus"] = diaconnG8HistoryRecord.dailyBolus + } else { + diaconnG8HistoryRecord.dailyBolus = recordMap["bolus"]!! + } + + if (recordMap["basal"]!! > 0.0) { + diaconnG8HistoryRecord.dailyBasal = recordMap["basal"]!! + } + + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + + //If it is a TDD, store it for stats also. + pumpSync.createOrUpdateTotalDailyDose( + timestamp = diaconnG8HistoryRecord.timestamp, + bolusAmount = diaconnG8HistoryRecord.dailyBolus, + basalAmount = diaconnG8HistoryRecord.dailyBasal, + totalAmount = 0.0, + pumpId = null, + pumpType = PumpType.DIACONN_G8, + diaconnG8Pump.serialNo.toString() + ) + + status = "DAILYBOLUS " + dateUtil.timeString(logDateTime) + } + + LOG_INJECTION_1DAY_BASAL.LOG_KIND -> { // Daily Basal Log + val logItem = LOG_INJECTION_1DAY_BASAL.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_DAILY + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.dailyBasal = logItem.amount / 100.0 + + val recordDateStr = "" + diaconnG8HistoryRecord.timestamp + var recordMap: MutableMap = mutableMapOf("dummy" to 0.0) + + if (dailyMaxvalInfo.containsKey(recordDateStr)) { + recordMap = dailyMaxvalInfo[recordDateStr]!! + } else { + recordMap["bolus"] = 0.0 + recordMap["basal"] = 0.0 + dailyMaxvalInfo[recordDateStr] = recordMap + } + + if (diaconnG8HistoryRecord.dailyBasal > recordMap["basal"]!!) { + recordMap["basal"] = diaconnG8HistoryRecord.dailyBasal + } else { + diaconnG8HistoryRecord.dailyBasal = recordMap["basal"]!! + } + + if (recordMap["bolus"]!! > 0.0) { + diaconnG8HistoryRecord.dailyBolus = recordMap["bolus"]!! + } + + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + + //If it is a TDD, store it for stats also. + // pumpSync.createOrUpdateTotalDailyDose( + // timestamp = diaconnG8HistoryRecord.timestamp, + // bolusAmount = diaconnG8HistoryRecord.dailyBolus, + // basalAmount = diaconnG8HistoryRecord.dailyBasal, + // totalAmount = 0.0, + // pumpId = null, + // pumpType = PumpType.DIACONN_G8, + // diaconnG8Pump.serialNo.toString() + // ) + + + status = "DAILYBASAL " + dateUtil.timeString(logDateTime) + } + + LOG_CHANGE_NEEDLE_SUCCESS.LOG_KIND -> { + val logItem = LOG_CHANGE_NEEDLE_SUCCESS.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + if (sp.getBoolean(R.string.key_diaconn_g8_logneedlechange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = logDateTime, + type = DetailedBolusInfo.EventType.CANNULA_CHANGE, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString() + ) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT NEEDLECHANGE(" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Amount: " + logItem.remainAmount / 100.0 + "U") + } + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_REFILL + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.remainAmount / 100.0 + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logneedleprime, logItem.primeAmount / 100.0) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "NEEDLECHANGE " + dateUtil.timeString(logDateTime) + } + + LOG_TB_START_V3.LOG_KIND -> { + val logItem = LOG_TB_START_V3.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + var absoluteRate = 0.0 + if (logItem.getTbInjectRateRatio() >= 50000) { + val tempBasalPercent = logItem.getTbInjectRateRatio() - 50000 + absoluteRate = pumpDesc.pumpType.determineCorrectBasalSize(diaconnG8Pump.baseAmount * (tempBasalPercent / 100.0)) + } + + if (logItem.getTbInjectRateRatio() in 1000..1600) { + absoluteRate = (logItem.getTbInjectRateRatio() - 1000) / 100.0 + } + + val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(logDateTime, absoluteRate) + val newRecord = pumpSync.syncTemporaryBasalWithPumpId( + timestamp = logDateTime, + rate = absoluteRate, + duration = T.mins((logItem.tbTime * 15).toLong()).msecs(), + isAbsolute = true, + type = temporaryBasalInfo?.type, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT TEMPSTART (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " Ratio: " + absoluteRate + "U Duration: " + logItem.tbTime * 15 + "min") + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_TB + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.duration = logItem.tbTime * 15 + diaconnG8HistoryRecord.value = absoluteRate + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logtempstart) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "TEMPSTART " + dateUtil.timeString(logDateTime) + } + + LOG_TB_STOP_V3.LOG_KIND -> { + val logItem = LOG_TB_STOP_V3.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + var absoluteRate = 0.0 + if (logItem.getTbInjectRateRatio() >= 50000) { + val tempBasalPercent = logItem.getTbInjectRateRatio() - 50000 + absoluteRate = diaconnG8Pump.baseAmount * (tempBasalPercent / 100.0) + } + if (logItem.getTbInjectRateRatio() in 1000..1600) { + absoluteRate = (logItem.getTbInjectRateRatio() - 1000) / 100.0 + } + + val newRecord = pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = logDateTime, + endPumpId = dateUtil.now(), + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString()) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT TEMPSTOP (" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")") + + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_TB + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = absoluteRate + diaconnG8HistoryRecord.stringValue = getReasonName(pumplogKind, logItem.reason) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "TEMPSTOP " + dateUtil.timeString(logDateTime) + } + + LOG_ALARM_BATTERY.LOG_KIND -> { // BATTERY SHORTAGE ALARM + val logItem = LOG_ALARM_BATTERY.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_ALARM + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logbatteryshorage) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "BATTERYALARM " + dateUtil.timeString(logDateTime) + } + + LOG_ALARM_BLOCK.LOG_KIND -> { // INJECTION BLOCKED ALARM + val logItem = LOG_ALARM_BLOCK.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_ALARM + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.amount / 100.0 + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_logalarmblock, getReasonName(pumplogKind, logItem.reason)) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "BLOCKALARM " + dateUtil.timeString(logDateTime) + } + + LOG_ALARM_SHORTAGE.LOG_KIND -> { // INSULIN SHORTAGE ALARM + val logItem = LOG_ALARM_SHORTAGE.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_ALARM + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.value = logItem.remain.toDouble() + diaconnG8HistoryRecord.stringValue = resourceHelper.gs(R.string.diaconn_g8_loginsulinshorage) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + status = "SHORTAGEALARM " + dateUtil.timeString(logDateTime) + } + + LOG_RESET_SYS_V3.LOG_KIND -> { + val logItem = LOG_RESET_SYS_V3.parse(logDataToHexString) + aapsLogger.debug(LTag.PUMPCOMM, "$logItem ") + + val logStartDate = DateUtils.parseDate(logItem.dttm, "yyyy-MM-dd HH:mm:ss") + val logDateTime = logStartDate.time + + diaconnG8HistoryRecord.code = RecordTypes.RECORD_TYPE_ALARM + diaconnG8HistoryRecord.timestamp = logDateTime + diaconnG8HistoryRecord.stringValue = getReasonName(pumplogKind, logItem.reason) + diaconnHistoryRecordDao.createOrUpdate(diaconnG8HistoryRecord) + if (logItem.reason == 3.toByte()) { + if (sp.getBoolean(R.string.key_diaconn_g8_logbatterychange, true)) { + val newRecord = pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = logDateTime, + type = DetailedBolusInfo.EventType.PUMP_BATTERY_CHANGE, + pumpId = logDateTime, + pumpType = PumpType.DIACONN_G8, + pumpSerial = diaconnG8Pump.serialNo.toString() + ) + aapsLogger.debug(LTag.PUMPCOMM, (if (newRecord) "**NEW** " else "") + "EVENT BATTERYCHANGE(" + pumplogKind + ") " + dateUtil.dateAndTimeString(logDateTime) + " (" + logDateTime + ")" + " remainAmount: " + logItem.batteryRemain.toInt() + "%") + } + } + status = "RESET " + dateUtil.timeString(logDateTime) + } + + else -> { + status = resourceHelper.gs(R.string.diaconn_g8_logsyncinprogress) + rxBus.send(EventPumpStatusChanged(status)) + continue + } + } + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.processinghistory) + ": " + status)) + } + } + + override fun getFriendlyName(): String { + return "BIG_LOG_INQUIRE_RESPONSE" + } + + private fun getReasonName(logKind: Byte, reason: Byte): String{ + val logInjectNormalFail: Byte = 0x0B + val logInjectSquareFail: Byte = 0x0E + val logInjectDualFail: Byte = 0x11 + val logTBStopV3: Byte = 0x13 + val logResetSysV3: Byte = 0x01 + val logALarmBlock: Byte = 0x29 + + return when (logKind) { + logInjectNormalFail, logInjectSquareFail, logInjectDualFail, logTBStopV3 -> failLog(reason) + logResetSysV3 -> resetLog(reason) + logALarmBlock -> blockLog(reason) + else -> "" + } + } + + private fun failLog(reason: Byte): String { + return when (reason) { + //1=Injection blockage, 2=Battery shortage, 3=Drug shortage, 4=User shutdown, 5=System reset, 6=Other, 7=Emergency shutdown + 0.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasoncomplete) + 1.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasoninjectonblock) + 2.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasonbatteryshortage) + 3.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasoninsulinshortage) + 4.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasonuserstop) + 5.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasonsystemreset) + 6.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasonother) + 7.toByte() -> resourceHelper.gs(R.string.diaconn_g8_reasonemergencystop) + else -> "No Reason" + } + } + + private fun resetLog(reason: Byte): String { + return when (reason.toInt()) { + 1 -> resourceHelper.gs(R.string.diaconn_g8_resetfactoryreset) + 2 -> resourceHelper.gs(R.string.diaconn_g8_resetemergencyoff) + 3 -> resourceHelper.gs(R.string.diaconn_g8_resetbatteryreplacement) + 4 -> resourceHelper.gs(R.string.diaconn_g8_resetaftercalibration) + 5 -> resourceHelper.gs(R.string.diaconn_g8_resetpreshipment) + 9 -> resourceHelper.gs(R.string.diaconn_g8_resetunexpected) + else -> "" + } + } + + private fun blockLog(reason: Byte): String { + return when (reason.toInt()) { + 1 -> resourceHelper.gs(R.string.diacon_g8_blockbasal) + 2 -> resourceHelper.gs(R.string.diacon_g8_blockmealbolus) + 3 -> resourceHelper.gs(R.string.diacon_g8_blocknormalbolus) + 4 -> resourceHelper.gs(R.string.diacon_g8_blocksquarebolus) + 5 -> resourceHelper.gs(R.string.diacon_g8_blockdualbolus) + 6 -> resourceHelper.gs(R.string.diacon_g8_blockreplacetube) + 7 -> resourceHelper.gs(R.string.diacon_g8_blockreplaceneedle) + 8 -> resourceHelper.gs(R.string.diacon_g8_blockreplacesyringe) + else -> "" + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquirePacket.kt new file mode 100644 index 0000000000..ddf9a2f465 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquirePacket.kt @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + + * BigMainInfoInquirePacket + */ +class BigMainInfoInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x73 + aapsLogger.debug(LTag.PUMPCOMM, "BigMainInfoInquirePacket init") + + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BIG_MAIN_INFO_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquireResponsePacket.kt new file mode 100644 index 0000000000..79d9de8c99 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BigMainInfoInquireResponsePacket.kt @@ -0,0 +1,359 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.pumplog.PumplogUtil +import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.joda.time.DateTime +import javax.inject.Inject +import kotlin.math.floor + +/** + * BigMainInfoInquireResponsePacket + */ +class BigMainInfoInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var sp: SP + @Inject lateinit var resourceHelper: ResourceHelper + private var pumpDesc = PumpDescription(PumpType.DIACONN_G8) + + init { + msgType = 0xb3.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BigMainInfoInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BigMainInfoInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) // 결과비트 상위 4비트 제거 + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + // 1. pump system setting info + diaconnG8Pump.systemRemainInsulin = floor(getShortToInt(bufferData) / 100.0) // 인슐린 잔량 + diaconnG8Pump.systemRemainBattery = getByteToInt(bufferData) // 베터리잔량(1~100%) + diaconnG8Pump.systemBasePattern = getByteToInt(bufferData) // 기저주입 패턴(0=없음, 1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2) + diaconnG8Pump.systemTbStatus = getByteToInt(bufferData) // 임시기저 상태(1=임시기저 중, 2=임시기저 해제) + diaconnG8Pump.systemInjectionMealStatus = getByteToInt(bufferData) // 식사주입 상태(1=주입중, 2=주입상태아님) + diaconnG8Pump.systemInjectionSnackStatus = getByteToInt(bufferData) // 일반간식 주입 상태(1=주입중, 2=주입상태아님) + diaconnG8Pump.systemInjectionSquareStatue = getByteToInt(bufferData) // 스퀘어회식 주입 상태(1=주입중, 2=주입상태아님) + diaconnG8Pump.systemInjectionDualStatus = getByteToInt(bufferData) // 더블회식 주입 상태(1=주입중, 2=주입상태아님) + + // 2. basal injection suspend status (1:stop, 2:release) + diaconnG8Pump.basePauseStatus = getByteToInt(bufferData) // 상태(1=정지,2=해제) + + // 3. Pump time + diaconnG8Pump.year = getByteToInt(bufferData) + 2000 // 년 (18~99) + diaconnG8Pump.month = getByteToInt(bufferData) // 월 (1~12) + diaconnG8Pump.day = getByteToInt(bufferData) // 일 (1~31) + diaconnG8Pump.hour = getByteToInt(bufferData) // 시 (0~23) + diaconnG8Pump.minute = getByteToInt(bufferData) // 분 (0~59) + diaconnG8Pump.second = getByteToInt(bufferData) // 초 (0~59) + + //4. pump system info + diaconnG8Pump.country = getByteToInt(bufferData).toChar().toString().toInt() // ASCII + diaconnG8Pump.productType = getByteToInt(bufferData).toChar().toString().toInt() // ASCII + diaconnG8Pump.makeYear = getByteToInt(bufferData) + diaconnG8Pump.makeMonth = getByteToInt(bufferData) + diaconnG8Pump.makeDay = getByteToInt(bufferData) + diaconnG8Pump.lotNo = getByteToInt(bufferData)// LOT NO + diaconnG8Pump.serialNo = getShortToInt(bufferData) + diaconnG8Pump.majorVersion = getByteToInt(bufferData) + diaconnG8Pump.minorVersion = getByteToInt(bufferData) + + sp.putString(resourceHelper.gs(R.string.pumpversion), diaconnG8Pump.majorVersion.toString() + "." + diaconnG8Pump.minorVersion.toString()) + + // 5. pump log status + diaconnG8Pump.pumpLastLogNum = getShortToInt(bufferData) // last saved log no + diaconnG8Pump.pumpWrappingCount = getByteToInt(bufferData) // wrapping count + + // 6. bolus speed status. + diaconnG8Pump.speed = getByteToInt(bufferData) // 식사주입속도 + + // 7. Tempbasal status + diaconnG8Pump.tbStatus = getByteToInt(bufferData) // 임시기저 상태 + diaconnG8Pump.tbTime = getByteToInt(bufferData) // 임시기저시간 + diaconnG8Pump.tbInjectRateRatio = getShortToInt(bufferData) //임시기저 주입량/률 + diaconnG8Pump.tbElapsedTime = getShortToInt(bufferData) // 임시기저 경과시간 + + // 8. Basal status + diaconnG8Pump.baseStatus = getByteToInt(bufferData) // 기저주입 상태 + diaconnG8Pump.baseHour = getByteToInt(bufferData) // 현재 주입시간 + diaconnG8Pump.baseAmount = getShortToInt(bufferData) / 100.0 // 주입설정량 + diaconnG8Pump.baseInjAmount = getShortToInt(bufferData) / 100.0 // 현재 주입량 + + // 9. meal bolus status + diaconnG8Pump.mealKind = getByteToInt(bufferData) //식사주입 종류 + diaconnG8Pump.mealStartTime = getIntToInt(bufferData) // 주입시작시간 + diaconnG8Pump.mealStatus = getByteToInt(bufferData) // 주입상태 + diaconnG8Pump.mealAmount = getShortToInt(bufferData) / 100.0 // 주입설정량 + diaconnG8Pump.mealInjAmount = getShortToInt(bufferData) / 100.0 // 주입량 + diaconnG8Pump.mealSpeed = getByteToInt(bufferData) // 주입속도 + + // 10. snack bolus status + diaconnG8Pump.snackStatus = getByteToInt(bufferData) //주입상태 + diaconnG8Pump.snackAmount = getShortToInt(bufferData) / 100.0 // 주입설정량 + diaconnG8Pump.snackInjAmount = getShortToInt(bufferData) / 100.0 // 현재주입량 + diaconnG8Pump.snackSpeed = getByteToInt(bufferData) //주입속도 + + // 11. square(extended) bolus status + diaconnG8Pump.squareStatus = getByteToInt(bufferData) // 주입상태 + diaconnG8Pump.squareTime = getShortToInt(bufferData) // 설정 주입시간(10~300분) + diaconnG8Pump.squareInjTime = getShortToInt(bufferData) // 경과 주입시간(10~300분) + diaconnG8Pump.squareAmount = getShortToInt(bufferData) / 100.0 // 주입 설정량 + diaconnG8Pump.squareInjAmount = getShortToInt(bufferData) / 100.0 // 현재 주입량 + + // 12. daul bolus status + diaconnG8Pump.dualStatus = getByteToInt(bufferData) // 주입상태 + diaconnG8Pump.dualAmount = getShortToInt(bufferData) / 100.0 // 일반주입 설정량 + diaconnG8Pump.dualInjAmount = getShortToInt(bufferData) / 100.0 // 일반주입량 + diaconnG8Pump.dualSquareTime = getShortToInt(bufferData) // 스퀘어주입 설정시간(10~300분) + diaconnG8Pump.dualInjSquareTime = getShortToInt(bufferData) // 스퀘어주입 경과시간(10~300분) + diaconnG8Pump.dualSquareAmount = getShortToInt(bufferData) / 100.0 // 스퀘어주입 설정량 + diaconnG8Pump.dualInjSquareAmount = getShortToInt(bufferData) / 100.0 // 스퀘어주입량 + + // 13. last injection status + diaconnG8Pump.recentKind1 = getByteToInt(bufferData) // 최근-1 주입 종류(1=식사, 2=일반간식, 3=스퀘어회식, 4=더블회식) + diaconnG8Pump.recentTime1 = getIntToInt(bufferData) // 최근-1 주입 시간 + diaconnG8Pump.recentAmount1 = getShortToInt(bufferData) / 100.0 // 최근-1 주입량 + diaconnG8Pump.recentKind2 = getByteToInt(bufferData) // 최근-2 주입 종류(1=식사, 2=일반간식, 3=스퀘어회식, 4=더블회식) + diaconnG8Pump.recentTime2 = getIntToInt(bufferData) // 최근-2 주입 시간 + diaconnG8Pump.recentAmount2 = getShortToInt(bufferData) / 100.0 // 최근-2 주입량 + + // 14. daily injection status + diaconnG8Pump.todayBaseAmount = getShortToInt(bufferData) / 100.0 // 기저주입 총량 + diaconnG8Pump.todayMealAmount = getShortToInt(bufferData) / 100.0 // 식사주입 총량 + diaconnG8Pump.todaySnackAmount = getShortToInt(bufferData) / 100.0 // 회식주입 총량 + + // 15. meat setting status + diaconnG8Pump.morningHour = getByteToInt(bufferData) // 아침 개시 시간(0~23) + diaconnG8Pump.morningAmount = getShortToInt(bufferData) / 100.0 // 아침 식전량 + diaconnG8Pump.lunchHour = getByteToInt(bufferData) // 점심 개시 시간(0~23) + diaconnG8Pump.lunchAmount = getShortToInt(bufferData) / 100.0 // 점심 식전량 + diaconnG8Pump.dinnerHour = getByteToInt(bufferData) // 저녁 개시 시간(0~23) + diaconnG8Pump.dinnerAmount = getShortToInt(bufferData) / 100.0 // 저녁 식전량 + + // 16. basal injection status at this hour + diaconnG8Pump.currentBasePattern = getByteToInt(bufferData) // 패턴 종류 (1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2) + diaconnG8Pump.currentBaseHour = getByteToInt(bufferData) // 현재주입시간(0~23) + diaconnG8Pump.currentBaseTbBeforeAmount = getShortToInt(bufferData) / 100.0 // 해당시간의 임시기저 계산 전 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + diaconnG8Pump.currentBaseTbAfterAmount = getShortToInt(bufferData)/ 100.0 // 해당시간의 임시기저 계산 후 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + + // 17. saved basal pattern status + diaconnG8Pump.baseAmount1 = getShortToInt(bufferData) / 100.0 // 주입량 1(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount2 = getShortToInt(bufferData) / 100.0 // 주입량 2(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount3 = getShortToInt(bufferData) / 100.0 // 주입량 3(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount4 = getShortToInt(bufferData) / 100.0 // 주입량 4(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount5 = getShortToInt(bufferData) / 100.0 // 주입량 5(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount6 = getShortToInt(bufferData) / 100.0 // 주입량 6(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount7 = getShortToInt(bufferData) / 100.0 // 주입량 7(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount8 = getShortToInt(bufferData) / 100.0 // 주입량 8(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount9 = getShortToInt(bufferData) / 100.0 // 주입량 9(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount10 = getShortToInt(bufferData) / 100.0 // 주입량 10(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount11 = getShortToInt(bufferData) / 100.0 // 주입량 11(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount12 = getShortToInt(bufferData) / 100.0 // 주입량 12(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount13 = getShortToInt(bufferData) / 100.0 // 주입량 13(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount14 = getShortToInt(bufferData) / 100.0 // 주입량 14(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount15 = getShortToInt(bufferData) / 100.0 // 주입량 15(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount16 = getShortToInt(bufferData) / 100.0 // 주입량 16(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount17 = getShortToInt(bufferData) / 100.0 // 주입량 17(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount18 = getShortToInt(bufferData) / 100.0 // 주입량 18(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount19 = getShortToInt(bufferData) / 100.0 // 주입량 19(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount20 = getShortToInt(bufferData) / 100.0 // 주입량 20(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount21 = getShortToInt(bufferData) / 100.0 // 주입량 21(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount22 = getShortToInt(bufferData) / 100.0 // 주입량 22(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount23 = getShortToInt(bufferData) / 100.0 // 주입량 23(량*100, 23.25->2325, 15.2->1520) + diaconnG8Pump.baseAmount24 = getShortToInt(bufferData) / 100.0 // 주입량 24(량*100, 23.25->2325, 15.2->1520) + + // tempbasal setting status + diaconnG8Pump.isTempBasalInProgress = diaconnG8Pump.tbStatus == 1 + aapsLogger.debug(LTag.PUMPCOMM, "isTempBasalInProgress > " + diaconnG8Pump.isTempBasalInProgress) + + // if rate type is percent + if (diaconnG8Pump.tbInjectRateRatio >= 50000) { + diaconnG8Pump.tempBasalPercent = diaconnG8Pump.tbInjectRateRatio - 50000 + + var absoluteValue = diaconnG8Pump.baseAmount * (diaconnG8Pump.tempBasalPercent / 100.0) + absoluteValue = pumpDesc.pumpType.determineCorrectBasalSize(absoluteValue) + diaconnG8Pump.tempBasalAbsoluteRate = absoluteValue + } + + // if rate type is absolute + if(diaconnG8Pump.tbInjectRateRatio in 1000..1600) { + diaconnG8Pump.tbInjectAbsoluteValue = (diaconnG8Pump.tbInjectRateRatio -1000) / 100.0 + diaconnG8Pump.tempBasalAbsoluteRate = diaconnG8Pump.tbInjectAbsoluteValue + } + + // extended bolus status + diaconnG8Pump.isExtendedInProgress = diaconnG8Pump.squareStatus == 1 || diaconnG8Pump.dualStatus == 1 + if(diaconnG8Pump.squareStatus == 1) { //square + diaconnG8Pump.extendedBolusMinutes = diaconnG8Pump.squareTime + diaconnG8Pump.extendedBolusAbsoluteRate = diaconnG8Pump.squareAmount + diaconnG8Pump.extendedBolusPassedMinutes = diaconnG8Pump.squareInjTime + diaconnG8Pump.extendedBolusRemainingMinutes = diaconnG8Pump.squareTime - diaconnG8Pump.squareInjTime + diaconnG8Pump.extendedBolusDeliveredSoFar = diaconnG8Pump.squareInjAmount + } else if (diaconnG8Pump.dualStatus == 1) { //dual + diaconnG8Pump.extendedBolusMinutes = diaconnG8Pump.dualSquareTime + diaconnG8Pump.extendedBolusAbsoluteRate = diaconnG8Pump.dualSquareAmount + diaconnG8Pump.extendedBolusPassedMinutes = diaconnG8Pump.dualInjSquareTime + diaconnG8Pump.extendedBolusRemainingMinutes = diaconnG8Pump.dualSquareTime - diaconnG8Pump.dualInjSquareTime + diaconnG8Pump.extendedBolusDeliveredSoFar = diaconnG8Pump.dualInjSquareAmount + } + + // pump time setting 'yyyy-MM-dd'T'HH:mm:ssZ' “2019-07-04T12:30:30+0530” + val time = DateTime(diaconnG8Pump.year, diaconnG8Pump.month, diaconnG8Pump.day, diaconnG8Pump.hour, diaconnG8Pump.minute, diaconnG8Pump.second) + diaconnG8Pump.setPumpTime(time.millis) + aapsLogger.debug(LTag.PUMPCOMM, "Pump time " + dateUtil.dateAndTimeString(time.millis)) + + // basal pattern from pump + diaconnG8Pump.pumpProfiles = Array(4) { Array(24) { 0.0 } } + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][0] = diaconnG8Pump.baseAmount1 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][1] = diaconnG8Pump.baseAmount2 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][2] = diaconnG8Pump.baseAmount3 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][3] = diaconnG8Pump.baseAmount4 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][4] = diaconnG8Pump.baseAmount5 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][5] = diaconnG8Pump.baseAmount6 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][6] = diaconnG8Pump.baseAmount7 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][7] = diaconnG8Pump.baseAmount8 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][8] = diaconnG8Pump.baseAmount9 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][9] = diaconnG8Pump.baseAmount10 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][10] = diaconnG8Pump.baseAmount11 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][11] = diaconnG8Pump.baseAmount12 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][12] = diaconnG8Pump.baseAmount13 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][13] = diaconnG8Pump.baseAmount14 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][14] = diaconnG8Pump.baseAmount15 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][15] = diaconnG8Pump.baseAmount16 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][16] = diaconnG8Pump.baseAmount17 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][17] = diaconnG8Pump.baseAmount18 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][18] = diaconnG8Pump.baseAmount19 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][19] = diaconnG8Pump.baseAmount20 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][20] = diaconnG8Pump.baseAmount21 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][21] = diaconnG8Pump.baseAmount22 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][22] = diaconnG8Pump.baseAmount23 + diaconnG8Pump.pumpProfiles!![diaconnG8Pump.activeProfile][23] = diaconnG8Pump.baseAmount24 + + //incarnation no 처리 + diaconnG8Pump.isPumpVersionGe2_63 = PumplogUtil.isPumpVersionGe(sp.getString(resourceHelper.gs(R.string.pumpversion), ""),2, 63) + + aapsLogger.debug(LTag.PUMPCOMM, "result > " + diaconnG8Pump.result) + aapsLogger.debug(LTag.PUMPCOMM, "systemRemainInsulin > " + diaconnG8Pump.systemRemainInsulin) + aapsLogger.debug(LTag.PUMPCOMM, "systemRemainBattery > " + diaconnG8Pump.systemRemainBattery) + aapsLogger.debug(LTag.PUMPCOMM, "systemBasePattern > " + diaconnG8Pump.systemBasePattern) + aapsLogger.debug(LTag.PUMPCOMM, "systemTbStatus > " + diaconnG8Pump.systemTbStatus) + aapsLogger.debug(LTag.PUMPCOMM, "systemInjectionMealStatus > " + diaconnG8Pump.systemInjectionMealStatus) + aapsLogger.debug(LTag.PUMPCOMM, "systemInjectionSnackStatus > " + diaconnG8Pump.systemInjectionSnackStatus) + aapsLogger.debug(LTag.PUMPCOMM, "systemInjectionSquareStatue > " + diaconnG8Pump.systemInjectionSquareStatue) + aapsLogger.debug(LTag.PUMPCOMM, "systemInjectionDualStatus > " + diaconnG8Pump.systemInjectionDualStatus) + aapsLogger.debug(LTag.PUMPCOMM, "basePauseStatus > " + diaconnG8Pump.basePauseStatus) + aapsLogger.debug(LTag.PUMPCOMM, "year > " + diaconnG8Pump.year) + aapsLogger.debug(LTag.PUMPCOMM, "month > " + diaconnG8Pump.month) + aapsLogger.debug(LTag.PUMPCOMM, "day > " + diaconnG8Pump.day) + aapsLogger.debug(LTag.PUMPCOMM, "hour > " + diaconnG8Pump.hour) + aapsLogger.debug(LTag.PUMPCOMM, "minute > " + diaconnG8Pump.minute) + aapsLogger.debug(LTag.PUMPCOMM, "second > " + diaconnG8Pump.second) + aapsLogger.debug(LTag.PUMPCOMM, "country > " + diaconnG8Pump.country) + aapsLogger.debug(LTag.PUMPCOMM, "productType > " + diaconnG8Pump.productType) + aapsLogger.debug(LTag.PUMPCOMM, "makeYear > " + diaconnG8Pump.makeYear) + aapsLogger.debug(LTag.PUMPCOMM, "makeMonth > " + diaconnG8Pump.makeMonth) + aapsLogger.debug(LTag.PUMPCOMM, "makeDay > " + diaconnG8Pump.makeDay) + aapsLogger.debug(LTag.PUMPCOMM, "lotNo > " + diaconnG8Pump.lotNo) + aapsLogger.debug(LTag.PUMPCOMM, "serialNo > " + diaconnG8Pump.serialNo) + aapsLogger.debug(LTag.PUMPCOMM, "majorVersion > " + diaconnG8Pump.majorVersion) + aapsLogger.debug(LTag.PUMPCOMM, "minorVersion > " + diaconnG8Pump.minorVersion) + aapsLogger.debug(LTag.PUMPCOMM, "lastNum > " + diaconnG8Pump.pumpLastLogNum) + aapsLogger.debug(LTag.PUMPCOMM, "wrappingCount > " + diaconnG8Pump.pumpWrappingCount) + aapsLogger.debug(LTag.PUMPCOMM, "speed > " + diaconnG8Pump.speed) + aapsLogger.debug(LTag.PUMPCOMM, "tbStatus > " + diaconnG8Pump.tbStatus) + aapsLogger.debug(LTag.PUMPCOMM, "tbTime> " + diaconnG8Pump.tbTime) + aapsLogger.debug(LTag.PUMPCOMM, "tbInjectRateRatio > " + diaconnG8Pump.tbInjectRateRatio) + aapsLogger.debug(LTag.PUMPCOMM, "tbElapsedTime > " + diaconnG8Pump.tbElapsedTime) + aapsLogger.debug(LTag.PUMPCOMM, "baseStatus > " + diaconnG8Pump.baseStatus) + aapsLogger.debug(LTag.PUMPCOMM, "baseHour > " + diaconnG8Pump.baseHour) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount > " + diaconnG8Pump.baseAmount) + aapsLogger.debug(LTag.PUMPCOMM, "baseInjAmount > " + diaconnG8Pump.baseInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "mealKind > " + diaconnG8Pump.mealKind) + aapsLogger.debug(LTag.PUMPCOMM, "mealStartTime > " + diaconnG8Pump.mealStartTime) + aapsLogger.debug(LTag.PUMPCOMM, "mealStatus > " + diaconnG8Pump.mealStatus) + aapsLogger.debug(LTag.PUMPCOMM, "mealAmount > " + diaconnG8Pump.mealAmount) + aapsLogger.debug(LTag.PUMPCOMM, "mealInjAmount > " + diaconnG8Pump.mealInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "mealSpeed > " + diaconnG8Pump.mealSpeed) + aapsLogger.debug(LTag.PUMPCOMM, "snackStatus > " + diaconnG8Pump.snackStatus) + aapsLogger.debug(LTag.PUMPCOMM, "snackAmount > " + diaconnG8Pump.snackAmount) + aapsLogger.debug(LTag.PUMPCOMM, "snackInjAmount > " + diaconnG8Pump.snackInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "snackSpeed > " + diaconnG8Pump.snackSpeed) + aapsLogger.debug(LTag.PUMPCOMM, "squareStatus > " + diaconnG8Pump.squareStatus) + aapsLogger.debug(LTag.PUMPCOMM, "squareTime > " + diaconnG8Pump.squareTime) + aapsLogger.debug(LTag.PUMPCOMM, "squareInjTime > " + diaconnG8Pump.squareInjTime) + aapsLogger.debug(LTag.PUMPCOMM, "squareAmount > " + diaconnG8Pump.squareAmount) + aapsLogger.debug(LTag.PUMPCOMM, "squareInjAmount > " + diaconnG8Pump.squareInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "dualStatus > " + diaconnG8Pump.dualStatus) + aapsLogger.debug(LTag.PUMPCOMM, "dualAmount > " + diaconnG8Pump.dualAmount) + aapsLogger.debug(LTag.PUMPCOMM, "dualInjAmount > " + diaconnG8Pump.dualInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "dualSquareTime > " + diaconnG8Pump.dualSquareTime) + aapsLogger.debug(LTag.PUMPCOMM, "dualInjSquareTime > " + diaconnG8Pump.dualInjSquareTime) + aapsLogger.debug(LTag.PUMPCOMM, "dualSquareAmount > " + diaconnG8Pump.dualSquareAmount) + aapsLogger.debug(LTag.PUMPCOMM, "dualInjSquareAmount> " + diaconnG8Pump.dualInjSquareAmount) + aapsLogger.debug(LTag.PUMPCOMM, "recentKind1 > " + diaconnG8Pump.recentKind1) + aapsLogger.debug(LTag.PUMPCOMM, "recentTime1 > " + diaconnG8Pump.recentTime1) + aapsLogger.debug(LTag.PUMPCOMM, "recentAmount1 > " + diaconnG8Pump.recentAmount1) + aapsLogger.debug(LTag.PUMPCOMM, "recentKind2 > " + diaconnG8Pump.recentKind2) + aapsLogger.debug(LTag.PUMPCOMM, "recentTime2 > " + diaconnG8Pump.recentTime2) + aapsLogger.debug(LTag.PUMPCOMM, "recentAmount2 > " + diaconnG8Pump.recentAmount2) + aapsLogger.debug(LTag.PUMPCOMM, "todayBaseAmount > " + diaconnG8Pump.todayBaseAmount) + aapsLogger.debug(LTag.PUMPCOMM, "todayMealAmount > " + diaconnG8Pump.todayMealAmount) + aapsLogger.debug(LTag.PUMPCOMM, "todaySnackAmount > " + diaconnG8Pump.todaySnackAmount) + aapsLogger.debug(LTag.PUMPCOMM, "morningHour > " + diaconnG8Pump.morningHour) + aapsLogger.debug(LTag.PUMPCOMM, "morningAmount > " + diaconnG8Pump.morningAmount) + aapsLogger.debug(LTag.PUMPCOMM, "lunchHour > " + diaconnG8Pump.lunchHour) + aapsLogger.debug(LTag.PUMPCOMM, "lunchAmount > " + diaconnG8Pump.lunchAmount) + aapsLogger.debug(LTag.PUMPCOMM, "dinnerHour > " + diaconnG8Pump.dinnerHour) + aapsLogger.debug(LTag.PUMPCOMM, "dinnerAmount > " + diaconnG8Pump.dinnerAmount) + aapsLogger.debug(LTag.PUMPCOMM, "currentBasePattern > " + diaconnG8Pump.currentBasePattern) + aapsLogger.debug(LTag.PUMPCOMM, "currentBaseHour > " + diaconnG8Pump.currentBaseHour) + aapsLogger.debug(LTag.PUMPCOMM, "currentBaseTbBeforeAmount > " + diaconnG8Pump.currentBaseTbBeforeAmount) + aapsLogger.debug(LTag.PUMPCOMM, "currentBaseTbAfterAmount > " + diaconnG8Pump.currentBaseTbAfterAmount) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount1 > " + diaconnG8Pump.baseAmount1) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount2 > " + diaconnG8Pump.baseAmount2) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount3 > " + diaconnG8Pump.baseAmount3) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount4 > " + diaconnG8Pump.baseAmount4) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount5 > " + diaconnG8Pump.baseAmount5) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount6 > " + diaconnG8Pump.baseAmount6) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount7 > " + diaconnG8Pump.baseAmount7) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount8 > " + diaconnG8Pump.baseAmount8) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount9 > " + diaconnG8Pump.baseAmount9) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount10 > " + diaconnG8Pump.baseAmount10) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount11 > " + diaconnG8Pump.baseAmount11) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount12 > " + diaconnG8Pump.baseAmount12) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount13 > " + diaconnG8Pump.baseAmount13) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount14 > " + diaconnG8Pump.baseAmount14) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount15 > " + diaconnG8Pump.baseAmount15) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount16 > " + diaconnG8Pump.baseAmount16) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount17 > " + diaconnG8Pump.baseAmount17) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount18 > " + diaconnG8Pump.baseAmount18) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount19 > " + diaconnG8Pump.baseAmount19) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount20 > " + diaconnG8Pump.baseAmount20) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount21 > " + diaconnG8Pump.baseAmount21) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount22 > " + diaconnG8Pump.baseAmount22) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount23 > " + diaconnG8Pump.baseAmount23) + aapsLogger.debug(LTag.PUMPCOMM, "baseAmount24 > " + diaconnG8Pump.baseAmount24) + } + + override fun getFriendlyName(): String { + return "PUMP_BIG_MAIN_INFO_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquirePacket.kt new file mode 100644 index 0000000000..085bc5c294 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquirePacket.kt @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BolusSpeedInquirePacket + */ +class BolusSpeedInquirePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x45.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedInquirePacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + return suffixEncode(prefixEncode(msgType, msgSeq, MSG_CON_END)) + } + + override fun getFriendlyName(): String { + return "PUMP_BOLUS_SPEED_INQUIRE" + + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquireResponsePacket.kt new file mode 100644 index 0000000000..ccf9be256a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedInquireResponsePacket.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Inject + +/** + * BolusSpeedInquireResponsePacket + */ +class BolusSpeedInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var sp: SP + + init { + msgType = 0x85.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectResult = defect(data) + if (defectResult != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result = getByteToInt(bufferData) + + if(!isSuccInquireResponseResult(result)) { + failed = true + return + } + + diaconnG8Pump.speed = getByteToInt(bufferData) //주입속도 + sp.putString("g8_bolusspeed", diaconnG8Pump.speed.toString()) + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "bolusSpeed > " + diaconnG8Pump.speed) + } + + override fun getFriendlyName(): String { + return "PUMP_BOLUS_SPEED_INQUIRE_RESPONSE" + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingPacket.kt new file mode 100644 index 0000000000..ff4005a937 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BolusSpeedSettingPacket + */ +class BolusSpeedSettingPacket( + injector: HasAndroidInjector, + private var type: Int +) : DiaconnG8Packet(injector) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x05 + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(type.toByte()) // 명령코드 + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_BOLUS_SPEED_SETTING_PACKET" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingReportPacket.kt new file mode 100644 index 0000000000..6008c76d12 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingReportPacket.kt @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Inject + +/** + * BolusSpeedSettingReportPacket + */ +class BolusSpeedSettingReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var sp: SP + init { + msgType = 0xC5.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedSettingReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedSettingReportPacket Report Packet Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.speed = getByteToInt(bufferData) // speed result + sp.putBoolean("diaconn_g8_isbolusspeedsync", true) + aapsLogger.debug(LTag.PUMPCOMM, "bolusSpeed --> ${diaconnG8Pump.speed }") + } + + override fun getFriendlyName(): String { + return "PUMP_BOLUS_SPEED_SETTING_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingResponsePacket.kt new file mode 100644 index 0000000000..efc55b2a49 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/BolusSpeedSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * BolusSpeedSettingResponsePacket + */ +class BolusSpeedSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x85.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedSettingResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "BolusSpeedSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_BOLUS_SPEED_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/ConfirmReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/ConfirmReportPacket.kt new file mode 100644 index 0000000000..cb516e30fa --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/ConfirmReportPacket.kt @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * ConfirmReportPacket + */ +class ConfirmReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var reqMsgType:Int? = null + init { + msgType = 0xE8.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "ConfirmReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "ConfirmReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + reqMsgType = getByteToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Pump Report Confirm reqMsgType --> ${reqMsgType}") + } + + override fun getFriendlyName(): String { + return "PUMP_CONFIRM_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8Packet.java b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8Packet.java new file mode 100644 index 0000000000..54bb487fd3 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8Packet.java @@ -0,0 +1,300 @@ +package info.nightscout.androidaps.diaconn.packet; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import javax.inject.Inject; + +import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.utils.DateUtil; + +public class DiaconnG8Packet { + + @Inject AAPSLogger aapsLogger; + @Inject DateUtil dateUtil; + + protected HasAndroidInjector injector; + private boolean received; + public boolean failed; + public byte msgType; + + public static final int MSG_LEN = 20; // 메시지 길이(20바이트 패킷) + public static final int MSG_LEN_BIG = 182; // 메시지 길이(182바이트 대량패킷) + public static final byte SOP = (byte) 0xef; // 패킷 시작 바이트(20바이트 패킷) + public static final byte SOP_BIG = (byte) 0xed; // 대량 패킷 시작 바이트(182바이트 대량패킷) + public static final byte MSG_TYPE_LOC = 1; // 메시지 종류 위치 + public static final byte MSG_SEQ_LOC = 2; // 메시지 시퀀스번호 위치 + public static final byte BT_MSG_DATA_LOC = 4; // 데이터 위치 + public static final byte MSG_PAD = (byte) 0xff; // 메시지 뒷부분 빈공간을 채우는 값 + public static final byte MSG_CON_END = (byte) 0x00; // 패킷 내용 끝 + public static final byte MSG_CON_CONTINUE = (byte) 0x01; // 패킷 내용 계속 + + /** + * CRC 정보 + */ + private static final byte[] crc_table = { + (byte) 0x00, (byte) 0x25, (byte) 0x4A, (byte) 0x6F, (byte) 0x94, (byte) 0xB1, (byte) 0xDE, (byte) 0xFB, + (byte) 0x0D, (byte) 0x28, (byte) 0x47, (byte) 0x62, (byte) 0x99, (byte) 0xBC, (byte) 0xD3, (byte) 0xF6, + (byte) 0x1A, (byte) 0x3F, (byte) 0x50, (byte) 0x75, (byte) 0x8E, (byte) 0xAB, (byte) 0xC4, (byte) 0xE1, + (byte) 0x17, (byte) 0x32, (byte) 0x5D, (byte) 0x78, (byte) 0x83, (byte) 0xA6, (byte) 0xC9, (byte) 0xEC, + (byte) 0x34, (byte) 0x11, (byte) 0x7E, (byte) 0x5B, (byte) 0xA0, (byte) 0x85, (byte) 0xEA, (byte) 0xCF, + (byte) 0x39, (byte) 0x1C, (byte) 0x73, (byte) 0x56, (byte) 0xAD, (byte) 0x88, (byte) 0xE7, (byte) 0xC2, + (byte) 0x2E, (byte) 0x0B, (byte) 0x64, (byte) 0x41, (byte) 0xBA, (byte) 0x9F, (byte) 0xF0, (byte) 0xD5, + (byte) 0x23, (byte) 0x06, (byte) 0x69, (byte) 0x4C, (byte) 0xB7, (byte) 0x92, (byte) 0xFD, (byte) 0xD8, + (byte) 0x68, (byte) 0x4D, (byte) 0x22, (byte) 0x07, (byte) 0xFC, (byte) 0xD9, (byte) 0xB6, (byte) 0x93, + (byte) 0x65, (byte) 0x40, (byte) 0x2F, (byte) 0x0A, (byte) 0xF1, (byte) 0xD4, (byte) 0xBB, (byte) 0x9E, + (byte) 0x72, (byte) 0x57, (byte) 0x38, (byte) 0x1D, (byte) 0xE6, (byte) 0xC3, (byte) 0xAC, (byte) 0x89, + (byte) 0x7F, (byte) 0x5A, (byte) 0x35, (byte) 0x10, (byte) 0xEB, (byte) 0xCE, (byte) 0xA1, (byte) 0x84, + (byte) 0x5C, (byte) 0x79, (byte) 0x16, (byte) 0x33, (byte) 0xC8, (byte) 0xED, (byte) 0x82, (byte) 0xA7, + (byte) 0x51, (byte) 0x74, (byte) 0x1B, (byte) 0x3E, (byte) 0xC5, (byte) 0xE0, (byte) 0x8F, (byte) 0xAA, + (byte) 0x46, (byte) 0x63, (byte) 0x0C, (byte) 0x29, (byte) 0xD2, (byte) 0xF7, (byte) 0x98, (byte) 0xBD, + (byte) 0x4B, (byte) 0x6E, (byte) 0x01, (byte) 0x24, (byte) 0xDF, (byte) 0xFA, (byte) 0x95, (byte) 0xB0, + (byte) 0xD0, (byte) 0xF5, (byte) 0x9A, (byte) 0xBF, (byte) 0x44, (byte) 0x61, (byte) 0x0E, (byte) 0x2B, + (byte) 0xDD, (byte) 0xF8, (byte) 0x97, (byte) 0xB2, (byte) 0x49, (byte) 0x6C, (byte) 0x03, (byte) 0x26, + (byte) 0xCA, (byte) 0xEF, (byte) 0x80, (byte) 0xA5, (byte) 0x5E, (byte) 0x7B, (byte) 0x14, (byte) 0x31, + (byte) 0xC7, (byte) 0xE2, (byte) 0x8D, (byte) 0xA8, (byte) 0x53, (byte) 0x76, (byte) 0x19, (byte) 0x3C, + (byte) 0xE4, (byte) 0xC1, (byte) 0xAE, (byte) 0x8B, (byte) 0x70, (byte) 0x55, (byte) 0x3A, (byte) 0x1F, + (byte) 0xE9, (byte) 0xCC, (byte) 0xA3, (byte) 0x86, (byte) 0x7D, (byte) 0x58, (byte) 0x37, (byte) 0x12, + (byte) 0xFE, (byte) 0xDB, (byte) 0xB4, (byte) 0x91, (byte) 0x6A, (byte) 0x4F, (byte) 0x20, (byte) 0x05, + (byte) 0xF3, (byte) 0xD6, (byte) 0xB9, (byte) 0x9C, (byte) 0x67, (byte) 0x42, (byte) 0x2D, (byte) 0x08, + (byte) 0xB8, (byte) 0x9D, (byte) 0xF2, (byte) 0xD7, (byte) 0x2C, (byte) 0x09, (byte) 0x66, (byte) 0x43, + (byte) 0xB5, (byte) 0x90, (byte) 0xFF, (byte) 0xDA, (byte) 0x21, (byte) 0x04, (byte) 0x6B, (byte) 0x4E, + (byte) 0xA2, (byte) 0x87, (byte) 0xE8, (byte) 0xCD, (byte) 0x36, (byte) 0x13, (byte) 0x7C, (byte) 0x59, + (byte) 0xAF, (byte) 0x8A, (byte) 0xE5, (byte) 0xC0, (byte) 0x3B, (byte) 0x1E, (byte) 0x71, (byte) 0x54, + (byte) 0x8C, (byte) 0xA9, (byte) 0xC6, (byte) 0xE3, (byte) 0x18, (byte) 0x3D, (byte) 0x52, (byte) 0x77, + (byte) 0x81, (byte) 0xA4, (byte) 0xCB, (byte) 0xEE, (byte) 0x15, (byte) 0x30, (byte) 0x5F, (byte) 0x7A, + (byte) 0x96, (byte) 0xB3, (byte) 0xDC, (byte) 0xF9, (byte) 0x02, (byte) 0x27, (byte) 0x48, (byte) 0x6D, + (byte) 0x9B, (byte) 0xBE, (byte) 0xD1, (byte) 0xF4, (byte) 0x0F, (byte) 0x2A, (byte) 0x45, (byte) 0x60 + }; + + public DiaconnG8Packet(HasAndroidInjector injector) { + this.received = false; + this.failed = false; + this.injector = injector; + injector.androidInjector().inject(this); + } + + public boolean success() { + return !failed; + } + public void setReceived() { + received = true; + } + + public boolean isReceived() { + return received; + } + + // 패킷 인코딩 앞부분 + public ByteBuffer prefixEncode(byte msgType, int msgSeq, byte msgConEnd) { + ByteBuffer buffer = ByteBuffer.allocate(MSG_LEN); + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.put(SOP); + buffer.put(msgType); + buffer.put((byte) msgSeq); + buffer.put(msgConEnd); + return buffer; + } + + // 패킷 인코딩 뒷부분 + public byte[] suffixEncode(ByteBuffer buffer) { + int remainSize = MSG_LEN - buffer.position() - 1; + for (int i = 0; i < remainSize; i++) { + buffer.put(MSG_PAD); + } + byte crc = getCRC(buffer.array(), MSG_LEN - 1); + buffer.put(crc); + return buffer.array(); + } + + // 패킷 디코딩 앞부분 + protected static ByteBuffer prefixDecode(byte[] bytes) { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.position(BT_MSG_DATA_LOC); + return buffer; + } + + public int getType(byte[] bytes) { + return (bytes[MSG_TYPE_LOC] & 0xC0) >> 6; + } //상위 2비트 획득 + + public int getCmd(byte[] bytes) { + return bytes[MSG_TYPE_LOC]; + } + + public int getSeq(byte[] bytes) { + return bytes[MSG_SEQ_LOC]; + } + + public static int getByteToInt(ByteBuffer buffer) { + return buffer.get() & 0xff; + } + + public static int getShortToInt(ByteBuffer buffer) { + return buffer.getShort() & 0xffff; + } + + public static int getIntToInt(ByteBuffer buffer) { + return buffer.getInt(); + } + + public static byte[] getBytes(ByteBuffer buffer, int limit) { + ByteBuffer data = ByteBuffer.allocate(MSG_LEN); + int orgPos = buffer.position(); + int orgLimit = buffer.limit(); + buffer.limit(buffer.position() + limit); + data.put(buffer); + buffer.position(orgPos); + buffer.limit(orgLimit); + return data.array(); + } + + // CRC 체크 + static byte getCRC(byte[] data, int length) { + int i = 0; + byte crc = 0; + while (length-- != 0) { + crc = crc_table[(crc ^ data[i]) & 0xFF]; + i++; + } + return crc; + } + + // 패킷 결함 체크 + public static int defect(byte[] bytes) { + int result = 0; + if (bytes[0] != SOP && bytes[0] != SOP_BIG) { + // Start Code Check + result = 98; + } else if ((bytes[0] == SOP && bytes.length != MSG_LEN) || + (bytes[0] == SOP_BIG && bytes.length != MSG_LEN_BIG)) { + // 패킷 길이 체크 + result = 97; + } else if (bytes[bytes.length - 1] != getCRC(bytes, bytes.length - 1)) { + // CRC 체크 + result = 99; + } + return result; + } + + public byte[] encode(int msgSeq) { return new byte[0]; } + + + public static String toHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (final byte b : bytes) + sb.append(String.format("%02x ", b & 0xff)); + return sb.toString(); + } + + public static String toNarrowHex(byte[] packet) { + StringBuilder sb = new StringBuilder(); + for (final byte b : packet) + sb.append(String.format("%02x", b & 0xff)); + return sb.toString(); + } + + public void handleMessage(byte[] data) { } + + public String getFriendlyName() { + return "UNKNOWN_PACKET"; + } + + public Boolean isSuccInquireResponseResult(int result) { + boolean isSuccess = false; + switch (result) { + case 16 : + isSuccess = true; + break; + case 17 : + aapsLogger.error(LTag.PUMPCOMM, "Packet CRC error"); + break; + + case 18 : + aapsLogger.error(LTag.PUMPCOMM, "Parameter error."); + break; + + case 19 : + aapsLogger.error(LTag.PUMPCOMM, "Protocol specification error."); + break; + + default: + aapsLogger.error(LTag.PUMPCOMM, "System error."); + break; + } + return isSuccess; + } + + public Boolean isSuccSettingResponseResult(int result) { + boolean isSuccess = false; + switch (result) { + case 0: + isSuccess = true; + break; + case 1: + aapsLogger.error(LTag.PUMPCOMM, "Packet CRC error"); + break; + + case 2: + aapsLogger.error(LTag.PUMPCOMM, "Parameter error."); + break; + + case 3: + aapsLogger.error(LTag.PUMPCOMM, "Protocol specification error."); + break; + + case 4: + aapsLogger.error(LTag.PUMPCOMM, "Eating timeout, not injectable."); + break; + + case 6: + aapsLogger.error(LTag.PUMPCOMM, "Pump canceled it."); + break; + + case 7: + aapsLogger.error(LTag.PUMPCOMM, "In the midst of other operations, limited app setup capabilities"); + break; + + case 8: + aapsLogger.error(LTag.PUMPCOMM, "During another bolus injection, injection is restricted"); + break; + + case 9: + aapsLogger.error(LTag.PUMPCOMM, "Basal release is required."); + break; + + case 10: + aapsLogger.error(LTag.PUMPCOMM, "Pump canceled due to non-response."); + break; + + case 11: + aapsLogger.error(LTag.PUMPCOMM, "Injection is not possible due to low battery."); + break; + + case 12: + aapsLogger.error(LTag.PUMPCOMM, "Injection is not possible due to low insulin. "); + break; + + case 13: + aapsLogger.error(LTag.PUMPCOMM, "Can't inject due to 1 time limit exceeded."); + break; + + case 14: + aapsLogger.error(LTag.PUMPCOMM, "It cannot be injected due to an excess of injection volume today"); + break; + + case 15: + aapsLogger.error(LTag.PUMPCOMM, "After base setting is completed, base injection can be made."); + break; + + default: + aapsLogger.error(LTag.PUMPCOMM, "It cannot be set to a system error."); + break; + + } + return isSuccess; + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8ResponseMessageHashTable.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8ResponseMessageHashTable.kt new file mode 100644 index 0000000000..84f008d57b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8ResponseMessageHashTable.kt @@ -0,0 +1,52 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DiaconnG8ResponseMessageHashTable @Inject constructor(val injector: HasAndroidInjector) { + var messages: HashMap = HashMap() + + fun put(message: DiaconnG8Packet) { + messages[message.msgType.toInt()] = message + } + + fun findMessage(command: Int): DiaconnG8Packet { + return messages[command] ?: DiaconnG8Packet(injector) + } + + init { + put(BigMainInfoInquireResponsePacket(injector)) + put(BigLogInquireResponsePacket(injector)) + put(InjectionSnackInquireResponsePacket(injector)) + put(SneckLimitInquireResponsePacket(injector)) + put(BasalLimitInquireResponsePacket(injector)) + put(TempBasalInquireResponsePacket(injector)) + put(TimeInquirePacket(injector)) + put(TimeInquireResponsePacket(injector)) + put(TimeReportPacket(injector)) + put(LogStatusInquireResponsePacket(injector)) + put(IncarnationInquireResponsePacket(injector)) + put(BolusSpeedInquireResponsePacket(injector)) + put(SoundInquireResponsePacket(injector)) + put(DisplayTimeInquireResponsePacket(injector)) + put(LanguageInquireResponsePacket(injector)) + + + // Report Packet + put(BasalPauseReportPacket(injector)) + put(BasalSettingReportPacket(injector)) + put(ConfirmReportPacket(injector)) + put(InjectionBasalReportPacket(injector)) + put(RejectReportPacket(injector)) + put(TempBasalReportPacket(injector)) + put(InjectionSnackResultReportPacket(injector)) + put(InjectionExtendedBolusResultReportPacket(injector)) + put(InsulinLackReportPacket(injector)) + put(BatteryWarningReportPacket(injector)) + put(InjectionBlockReportPacket(injector)) + put(BolusSpeedSettingReportPacket(injector)) + } +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8SettingResponseMessageHashTable.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8SettingResponseMessageHashTable.kt new file mode 100644 index 0000000000..cd2d32a293 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DiaconnG8SettingResponseMessageHashTable.kt @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DiaconnG8SettingResponseMessageHashTable @Inject constructor(val injector: HasAndroidInjector) { + var messages: HashMap = HashMap() + + fun put(message: DiaconnG8Packet) { + messages[message.msgType.toInt()] = message + } + + fun findMessage(command: Int): DiaconnG8Packet { + return messages[command] ?: DiaconnG8Packet(injector) + } + + init { + put(AppCancelSettingResponsePacket(injector)) + put(AppConfirmSettingResponsePacket(injector)) + put(BasalPauseSettingResponsePacket(injector)) + put(BasalSettingResponsePacket(injector)) + put(TempBasalSettingResponsePacket(injector)) + put(TimeSettingResponsePacket(injector)) + put(InjectionBasalSettingResponsePacket(injector)) + put(InjectionSnackSettingResponsePacket(injector)) + put(InjectionExtendedBolusSettingResponsePacket(injector)) + put(InjectionCancelSettingResponsePacket(injector)) + put(SoundSettingResponsePacket(injector)) + put(DisplayTimeoutSettingResponsePacket(injector)) + put(LanguageSettingResponsePacket(injector)) + put(BolusSpeedSettingResponsePacket(injector)) + } +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquirePacket.kt new file mode 100644 index 0000000000..9c0692ab45 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * DisplayTimeInquirePacket + */ +class DisplayTimeInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x4E.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeInquirePacket request") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_DISPLAY_TIME_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquireResponsePacket.kt new file mode 100644 index 0000000000..5d1b7df047 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeInquireResponsePacket.kt @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * DisplayTimeInquireResponsePacket + */ +class DisplayTimeInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x8E.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + + diaconnG8Pump.lcdOnTimeSec = getByteToInt(bufferData) + + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "lcdOnTimeSec --> ${diaconnG8Pump.lcdOnTimeSec}") + } + + override fun getFriendlyName(): String { + return "PUMP_DISPLAY_TIME_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingPacket.kt new file mode 100644 index 0000000000..bbd462cc0c --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * DisplayTimeoutSettingPacket + */ +class DisplayTimeoutSettingPacket( + injector: HasAndroidInjector, + private var type: Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x0E + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeoutSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(type.toByte()) // cmd + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_DISPLAY_TIMEOUT_SETTING_PACKET" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingResponsePacket.kt new file mode 100644 index 0000000000..9582da53e5 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/DisplayTimeoutSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * DisplayTimeoutSettingResponsePacket + */ +class DisplayTimeoutSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x8E.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeoutSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "DisplayTimeoutSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_DISPLAY_TIMEOUT_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquirePacket.kt new file mode 100644 index 0000000000..34f99c6ff6 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquirePacket.kt @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + + * IncarnationInquirePacket + */ +class IncarnationInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x7A + aapsLogger.debug(LTag.PUMPCOMM, "IncarnationInquirePacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INCARNATION_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquireResponsePacket.kt new file mode 100644 index 0000000000..55aedbcf05 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/IncarnationInquireResponsePacket.kt @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Inject + +/** + * IncarnationInquireResponsePacket + */ +open class IncarnationInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var sp: SP + @Inject lateinit var resourceHelper: ResourceHelper + + var result = 0 + init { + msgType = 0xBA.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "IncarnationInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "IncarnationInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result)) { + failed = true + return + } + // 5. 로그상태 조회 + diaconnG8Pump.pumpIncarnationNum = getShortToInt(bufferData) // 펌프 Incarnation 번호 + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "pumpIncarnationNum > " + diaconnG8Pump.pumpIncarnationNum) + } + + override fun getFriendlyName(): String { + return "PUMP_INCARNATION_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalReportPacket.kt new file mode 100644 index 0000000000..503c5bacb1 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalReportPacket.kt @@ -0,0 +1,37 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionBasalReportPacket + */ +class InjectionBasalReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0xCC.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.systemBasePattern = getByteToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Pump Report BasalPattern --> ${diaconnG8Pump.systemBasePattern} (1:basic, 2: life1 , 3: life2 , 4: life3 , 5:dr1, 6:dr2) ") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_BASAL_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingPacket.kt new file mode 100644 index 0000000000..4e9cbf546b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingPacket.kt @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionBasalSettingPacket + */ +class InjectionBasalSettingPacket( + injector: HasAndroidInjector, + private val pattern:Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x0C.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalSettingPacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + buffer.put(pattern.toByte()) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_BASAL_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingResponsePacket.kt new file mode 100644 index 0000000000..c9912472ce --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBasalSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionBasalSettingResponsePacket + */ +class InjectionBasalSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x8C.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_BASAL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBlockReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBlockReportPacket.kt new file mode 100644 index 0000000000..0ff1cd6181 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionBlockReportPacket.kt @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionBlockReportPacket + */ +class InjectionBlockReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0xD8.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBlockReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionBasalReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.injectionBlockGrade = getByteToInt(bufferData) + diaconnG8Pump.injectionBlockProcess = getByteToInt(bufferData) + diaconnG8Pump.injectionBlockRemainAmount = getShortToInt(bufferData) / 100.0 + diaconnG8Pump.injectionBlockType = getByteToInt(bufferData) + + aapsLogger.debug(LTag.PUMPCOMM, "injectionBlockGrade --> ${diaconnG8Pump.injectionBlockGrade} (1:info, 2: warning , 3: major , 4: critical)") + aapsLogger.debug(LTag.PUMPCOMM, "injectionBlockProcess --> ${diaconnG8Pump.injectionBlockProcess} (1:skip, 2: stop , 3: ignore ) ") + aapsLogger.debug(LTag.PUMPCOMM, "injectionBlockReaminAmount --> ${diaconnG8Pump.injectionBlockRemainAmount} ") + aapsLogger.debug(LTag.PUMPCOMM, "injectionBlockType --> ${diaconnG8Pump.injectionBlockType} (1:basal, 2: meal , 3: normal , 4: square , 5:dual, 6:tube, 7:needle) ") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_BLOCK_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingPacket.kt new file mode 100644 index 0000000000..bfab75fe6a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionCancelSettingPacket + */ +class InjectionCancelSettingPacket( + injector: HasAndroidInjector, + private var reqMsgType: Byte, // 명령코드 +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x2B + aapsLogger.debug(LTag.PUMPCOMM, "InjectionCancelSettingPacket INIT") + } + + override fun encode(msgSeq:Int): ByteArray { + var buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(reqMsgType) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_CANCEL_SETTING_REQUEST" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingResponsePacket.kt new file mode 100644 index 0000000000..9099e5ba0c --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionCancelSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionCancelSettingResponsePacket + */ +class InjectionCancelSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0xAB.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionCancelSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionCancelSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_CANCEL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusResultReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusResultReportPacket.kt new file mode 100644 index 0000000000..8f196a4713 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusResultReportPacket.kt @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +/** + * InjectionExtendedBolusResultReportPacket + */ +class InjectionExtendedBolusResultReportPacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var resourceHelper: ResourceHelper + + init { + msgType = 0xe5.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionExtendedBolusResultReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionExtendedBolusResultReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + + val result = getByteToInt(bufferData) // 0: success , 1: user stop, 2:fail + val settingMinutes = getShortToInt(bufferData) + val elapsedTime = getShortToInt(bufferData) + val bolusAmountToBeDelivered = getShortToInt(bufferData) / 100.0 + val deliveredBolusAmount = getShortToInt(bufferData) / 100.0 + + diaconnG8Pump.isExtendedInProgress = result == 0 + diaconnG8Pump.extendedBolusMinutes = settingMinutes + diaconnG8Pump.extendedBolusAbsoluteRate = bolusAmountToBeDelivered + diaconnG8Pump.extendedBolusPassedMinutes = elapsedTime + diaconnG8Pump.extendedBolusRemainingMinutes = settingMinutes - elapsedTime + diaconnG8Pump.extendedBolusDeliveredSoFar = deliveredBolusAmount + + aapsLogger.debug(LTag.PUMPCOMM, "Result: $result") + aapsLogger.debug(LTag.PUMPCOMM, "Is extended bolus running: " + diaconnG8Pump.isExtendedInProgress) + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus running: " + diaconnG8Pump.extendedBolusAbsoluteRate + " U/h") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus duration: " + diaconnG8Pump.extendedBolusMinutes + " min") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus so far: " + diaconnG8Pump.extendedBolusSoFarInMinutes + " min") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus remaining minutes: " + diaconnG8Pump.extendedBolusRemainingMinutes + " min") + aapsLogger.debug(LTag.PUMPCOMM, "Extended bolus delivered so far: " + diaconnG8Pump.extendedBolusDeliveredSoFar + " U") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_EXTENDED_BOLUS_RESULT_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingPacket.kt new file mode 100644 index 0000000000..e9f119862a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingPacket.kt @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionExtendedBolusSettingPacket + */ +class InjectionExtendedBolusSettingPacket( + injector: HasAndroidInjector, + private val amount: Int, + private val minutes: Int, + private val bcDttm:Long +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x08.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionExtendedBolusSettingPacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.putShort(minutes.toShort()) + buffer.putShort(amount.toShort()) + buffer.putInt(bcDttm.toInt()) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_EXTENDED_BOLUS_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingResponsePacket.kt new file mode 100644 index 0000000000..a17ecd3bfb --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionExtendedBolusSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionExtendedBolusSettingResponsePacket + */ +class InjectionExtendedBolusSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x88.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionExtendedBolusSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionExtendedBolusSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_EXTENDED_BOLUS_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingPacket.kt new file mode 100644 index 0000000000..ed901b9187 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingPacket.kt @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionMealSettingPacket + */ +class InjectionMealSettingPacket( + injector: HasAndroidInjector, + private val amount:Int, + private val bcDttm:Long +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x06.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionMealSettingPacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + buffer.putShort(amount.toShort()) + buffer.putLong(bcDttm) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_MEAL_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingResponsePacket.kt new file mode 100644 index 0000000000..7e30ef8c3c --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionMealSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionMealSettingResponsePacket + */ +class InjectionMealSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x86.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionMealSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionMealSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_MEAL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquirePacket.kt new file mode 100644 index 0000000000..a9e82f1953 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquirePacket.kt @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionSneckInquirePacket + */ +class InjectionSnackInquirePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x47.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackInquirePacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + return suffixEncode(prefixEncode(msgType, msgSeq, MSG_CON_END)) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_SNACK_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquireResponsePacket.kt new file mode 100644 index 0000000000..4ff2b27c9e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackInquireResponsePacket.kt @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionSnackInquireResponsePacket + */ +class InjectionSnackInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x87.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + + diaconnG8Pump.snackStatus = getByteToInt(bufferData) //주입상태 + diaconnG8Pump.snackAmount = getShortToInt(bufferData) / 100.0 // 주입설정량 + diaconnG8Pump.snackInjAmount = getShortToInt(bufferData) / 100.0 // 현재주입량 + diaconnG8Pump.snackSpeed = getByteToInt(bufferData) //주입속도 + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result2") + aapsLogger.debug(LTag.PUMPCOMM, "snackStatus > " + diaconnG8Pump.snackStatus) + aapsLogger.debug(LTag.PUMPCOMM, "snackAmount > " + diaconnG8Pump.snackAmount) + aapsLogger.debug(LTag.PUMPCOMM, "snackInjAmount > " + diaconnG8Pump.snackInjAmount) + aapsLogger.debug(LTag.PUMPCOMM, "snackSpeed > " + diaconnG8Pump.snackSpeed) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_SNACK_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackResultReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackResultReportPacket.kt new file mode 100644 index 0000000000..a85c35002b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackResultReportPacket.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +/** + * InjectionSnackResultReportPacket + */ +class InjectionSnackResultReportPacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var resourceHelper: ResourceHelper + + init { + msgType = 0xe4.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackResultReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackResultReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result = getByteToInt(bufferData) + val bolusAmountToBeDelivered = getShortToInt(bufferData)/100.0 + val deliveredBolusAmount = getShortToInt(bufferData)/100.0 + + diaconnG8Pump.bolusAmountToBeDelivered = bolusAmountToBeDelivered + diaconnG8Pump.lastBolusAmount = deliveredBolusAmount + diaconnG8Pump.lastBolusTime = dateUtil.now() + diaconnG8Pump.bolusingTreatment?.insulin = deliveredBolusAmount + + if(result == 1) { + diaconnG8Pump.bolusStopped = true // 주입 중 취소 처리! + } + diaconnG8Pump.bolusDone = true // 주입완료 처리! + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "bolusAmountToBeDelivered --> ${diaconnG8Pump.bolusAmountToBeDelivered}") + aapsLogger.debug(LTag.PUMPCOMM, "lastBolusAmount --> ${diaconnG8Pump.lastBolusAmount}") + aapsLogger.debug(LTag.PUMPCOMM, "lastBolusTime --> ${diaconnG8Pump.lastBolusTime}") + aapsLogger.debug(LTag.PUMPCOMM, "diaconnG8Pump.bolusingTreatment?.insulin --> ${diaconnG8Pump.bolusingTreatment?.insulin}") + aapsLogger.debug(LTag.PUMPCOMM, "bolusDone --> ${diaconnG8Pump.bolusDone}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_SNACK_REPORT" + + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingPacket.kt new file mode 100644 index 0000000000..5312aa348e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingPacket.kt @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionSnackSettingPacket + */ +class InjectionSnackSettingPacket( + injector: HasAndroidInjector, + private val amount:Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x07.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackSettingPacket init ") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + buffer.putShort(amount.toShort()) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_SNACK_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingResponsePacket.kt new file mode 100644 index 0000000000..dec3271e47 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InjectionSnackSettingResponsePacket.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InjectionSnackSettingResponsePacket + */ +class InjectionSnackSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x87.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InjectionSnackSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_SNACK_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InsulinLackReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InsulinLackReportPacket.kt new file mode 100644 index 0000000000..8fd6da5981 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/InsulinLackReportPacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * InsulinLackReportPacket + */ +class InsulinLackReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0xD8.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "InsulinLackReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "InsulinLackReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.insulinWarningGrade = getByteToInt(bufferData) + diaconnG8Pump.insulinWarningProcess = getByteToInt(bufferData) + diaconnG8Pump.insulinWarningRemain = getByteToInt(bufferData) + + aapsLogger.debug(LTag.PUMPCOMM, "insulinWarningGrade --> ${diaconnG8Pump.insulinWarningGrade} (1:info, 2: warning , 3: major , 4: critical)") + aapsLogger.debug(LTag.PUMPCOMM, "insulinWarningProcess --> ${diaconnG8Pump.insulinWarningProcess} (1:skip, 2: stop , 3: ignore ) ") + aapsLogger.debug(LTag.PUMPCOMM, "insulinWarningRemain --> ${diaconnG8Pump.insulinWarningRemain} (0~100%) ") + + } + + override fun getFriendlyName(): String { + return "PUMP_INJECTION_LACK_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquirePacket.kt new file mode 100644 index 0000000000..7bca3e499b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LanguageInquirePacket + */ +class LanguageInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x60.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "LanguageInquirePacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_LANGUAGE_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquireResponsePacket.kt new file mode 100644 index 0000000000..6c493ca145 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageInquireResponsePacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LanguageInquireResponsePacket + */ +class LanguageInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0xA0.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "LanguageInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "LanguageInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + diaconnG8Pump.selectedLanguage = getByteToInt(bufferData) + + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "selectedLanguage --> ${diaconnG8Pump.selectedLanguage}") + } + + override fun getFriendlyName(): String { + return "PUMP_LANGUAGE_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingPacket.kt new file mode 100644 index 0000000000..fd0f35f1cc --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingPacket.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LanguageSettingPacket + */ +class LanguageSettingPacket( + injector: HasAndroidInjector, + private var type: Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x20 + aapsLogger.debug(LTag.PUMPCOMM, "LanguageSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(type.toByte()) // 명령코드 + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_LANGUAGE_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingResponsePacket.kt new file mode 100644 index 0000000000..91a29ddae7 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LanguageSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LanguageSettingResponsePacket + */ +class LanguageSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0xA0.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "LanguageSettingResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "LanguageSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_LANGUAGE_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquirePacket.kt new file mode 100644 index 0000000000..21e0431d66 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquirePacket.kt @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LogStatusInquirePacket + */ +class LogStatusInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + init { + msgType = 0x56 + aapsLogger.debug(LTag.PUMPCOMM, "LogStatusInquirePacket INIT") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_OG_STATUS_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquireResponsePacket.kt new file mode 100644 index 0000000000..441afe753e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/LogStatusInquireResponsePacket.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * LogStatusInquireResponsePacket + */ +open class LogStatusInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + var result = 0 + init { + msgType = 0x96.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "LogStatusInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "LogStatusInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result)) { + failed = true + return + } + // 5. 로그상태 조회 + diaconnG8Pump.pumpLastLogNum = getShortToInt(bufferData) // 마지막 저장로그번호 + diaconnG8Pump.pumpWrappingCount = getByteToInt(bufferData) // wrapping 카운트 + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "pumpLastLogNum > " + diaconnG8Pump.pumpLastLogNum) + aapsLogger.debug(LTag.PUMPCOMM, "pumpWrappingCount> " + diaconnG8Pump.pumpWrappingCount) + } + + override fun getFriendlyName(): String { + return "PUMP_LOG_STATUS_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/RejectReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/RejectReportPacket.kt new file mode 100644 index 0000000000..7c8871b0f6 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/RejectReportPacket.kt @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * RejectReportPacket + */ +class RejectReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var reqMsgType:Int? = null + var reason:Int? = null + init { + msgType = 0xE2.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "RejectReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "RejectReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + reqMsgType = getByteToInt(bufferData) + reason = getByteToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "reqMsgType --> $reqMsgType") + aapsLogger.debug(LTag.PUMPCOMM, "Reject Reason --> $reason (6:cancel, 10:timeout) ") + } + + override fun getFriendlyName(): String { + return "PUMP_REJECT_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquirePacket.kt new file mode 100644 index 0000000000..983887eccb --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SneckLimitInquirePacket + */ +class SneckLimitInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x50.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "SneckLimitInquirePacket limit request") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_SNECK_LIMIT_REQUEST" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquireResponsePacket.kt new file mode 100644 index 0000000000..4dccca9ab1 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SneckLimitInquireResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SneckLimitInquireResponsePacket + */ +class SneckLimitInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x90.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "SneckLimitInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "SneckLimitInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + + diaconnG8Pump.maxBolus = getShortToInt(bufferData).toDouble() / 100 + diaconnG8Pump.maxBolusePerDay = getShortToInt(bufferData).toDouble() / 100 + + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "maxBolusePerDay --> ${diaconnG8Pump.maxBolusePerDay}") + aapsLogger.debug(LTag.PUMPCOMM, "maxBolus --> ${diaconnG8Pump.maxBolus}") + } + + override fun getFriendlyName(): String { + return "PUMP_SNACK_LIMIT_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquirePacket.kt new file mode 100644 index 0000000000..790523aff9 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SoundInquirePacket + */ +class SoundInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x4D.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "SoundInquirePacket request") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_SOUND_INQUIRE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquireResponsePacket.kt new file mode 100644 index 0000000000..c42a20e835 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundInquireResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SoundInquireResponsePacket + */ +class SoundInquireResponsePacket(injector: HasAndroidInjector) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x8D.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "SoundInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "SoundInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return + } + + diaconnG8Pump.beepAndAlarm = getByteToInt(bufferData) -1 + diaconnG8Pump.alarmIntesity = getByteToInt(bufferData) -1 + + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> ${diaconnG8Pump.result}") + aapsLogger.debug(LTag.PUMPCOMM, "beepAndAlarm --> ${diaconnG8Pump.beepAndAlarm}") + aapsLogger.debug(LTag.PUMPCOMM, "alarmIntesity --> ${diaconnG8Pump.alarmIntesity}") + } + + override fun getFriendlyName(): String { + return "PUMP_SOUND_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingPacket.kt new file mode 100644 index 0000000000..cadb110435 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingPacket.kt @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SoundSettingPacket + */ +class SoundSettingPacket( + injector: HasAndroidInjector, + private var type: Int, // + private var intensity: Int // +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x0D + aapsLogger.debug(LTag.PUMPCOMM, "SoundSettingPacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + buffer.put(type.toByte()) // 명령코드 + buffer.put(intensity.toByte()) // 명령코드 + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_SOUND_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingResponsePacket.kt new file mode 100644 index 0000000000..474dc3997c --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/SoundSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * SoundSettingResponsePacket + */ +class SoundSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x8D.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "SoundSettingResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "SoundSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_SOUND_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquirePacket.kt new file mode 100644 index 0000000000..db1da7fc5a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquirePacket.kt @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TempBasalInquirePacket + */ +class TempBasalInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x4A + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalInquirePacket Init") + } + + override fun encode(msgSeq:Int): ByteArray { + return suffixEncode(prefixEncode(msgType, msgSeq, MSG_CON_END)) + } + + override fun getFriendlyName(): String { + return "PUMP_TEMP_BASAL_INQUIRE_REQUEST" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquireResponsePacket.kt new file mode 100644 index 0000000000..5f45ab3abd --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalInquireResponsePacket.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TempBasalInquireResponsePacket + */ +open class TempBasalInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + var result = 0 + init { + msgType = 0x8A.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result)) { + failed = true + return + } + + diaconnG8Pump.tbStatus = getByteToInt(bufferData) // 임시기저 상태 + diaconnG8Pump.tbTime = getByteToInt(bufferData) // 임시기저시간 + diaconnG8Pump.tbInjectRateRatio = getShortToInt(bufferData) //임시기저 주입량/률 + diaconnG8Pump.tbElapsedTime = getShortToInt(bufferData) // 임시기저 경과시간 + + diaconnG8Pump.isTempBasalInProgress = diaconnG8Pump.tbStatus == 1 + if (diaconnG8Pump.tbInjectRateRatio >= 50000) { + diaconnG8Pump.tempBasalPercent = diaconnG8Pump.tbInjectRateRatio - 50000 + } + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "tbStatus > " + diaconnG8Pump.tbStatus) + aapsLogger.debug(LTag.PUMPCOMM, "tbTime> " + diaconnG8Pump.tbTime) + aapsLogger.debug(LTag.PUMPCOMM, "tbInjectRateRatio > " + diaconnG8Pump.tbInjectRateRatio) + aapsLogger.debug(LTag.PUMPCOMM, "tbElapsedTime > " + diaconnG8Pump.tbElapsedTime) + } + + override fun getFriendlyName(): String { + return "PUMP_TEMP_BASAL_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalReportPacket.kt new file mode 100644 index 0000000000..73fa041172 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalReportPacket.kt @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TempBasalReportPacket + */ +class TempBasalReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0xCA.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalReportPacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.tbStatus = getByteToInt(bufferData) + diaconnG8Pump.isTempBasalInProgress = diaconnG8Pump.tbStatus == 1 + + // 응답받은 임시기저 상태가 주입중이면, pump객체에 정보를 갱신. + if(diaconnG8Pump.isTempBasalInProgress) { + diaconnG8Pump.tbTime = getByteToInt(bufferData) + diaconnG8Pump.tbInjectRateRatio = getShortToInt(bufferData) + if (diaconnG8Pump.tbInjectRateRatio >= 50000) { + diaconnG8Pump.tempBasalPercent = diaconnG8Pump.tbInjectRateRatio - 50000 + } + + if(diaconnG8Pump.tbInjectRateRatio in 1000..1600) { + diaconnG8Pump.tbInjectAbsoluteValue = (diaconnG8Pump.tbInjectRateRatio -1000) / 100.0 + diaconnG8Pump.tempBasalAbsoluteRate = diaconnG8Pump.tbInjectAbsoluteValue + } + } + aapsLogger.debug(LTag.PUMPCOMM, "tbStatus > " + diaconnG8Pump.tbStatus) + aapsLogger.debug(LTag.PUMPCOMM, "tbTime> " + diaconnG8Pump.tbTime) + aapsLogger.debug(LTag.PUMPCOMM, "tbInjectRateRatio > " + diaconnG8Pump.tbInjectRateRatio) + + } + + override fun getFriendlyName(): String { + return "PUMP_TEMP_BASAL_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingPacket.kt new file mode 100644 index 0000000000..b935ce2a94 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingPacket.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TempBasalSettingPacket + */ +class TempBasalSettingPacket( + injector: HasAndroidInjector, + private var status: Int, // (1:tempbasal running, 2:tempbasal dismissed) + private var time: Int, //hour group (1=00~05, 2=06~11, 3=12~17, 4=18~23) + private var injectRateRatio: Int +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x0A + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalSettingPacket Init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END) + val apsSecond = 946652400L //fixed value 2000-01-01 00:00:00 (second) + buffer.put(status.toByte()) // status + buffer.put(time.toByte()) + buffer.putShort(injectRateRatio.toShort()) // 임시기저 주입량/률 1000(0.00U)~1600(6.00U), 50000(0%)~50200(200%), 50000이상이면 주입률로 판정 + buffer.putLong(apsSecond) // TB_DTTM + + aapsLogger.debug(LTag.PUMPCOMM, " status --> ${status.toByte()} (1:tempbasal running, 2:tempbasal dismissed)") + aapsLogger.debug(LTag.PUMPCOMM, " time --> ${time.toByte()} ( value : 2~96 ( 2:30min, 3:45min....96:1440min ) 30min ~ 24 hour, step 15min ) ") + aapsLogger.debug(LTag.PUMPCOMM, "injectRateRatio --> $injectRateRatio , toShort = ${injectRateRatio.toShort()}") + aapsLogger.debug(LTag.PUMPCOMM, " tbDttm --> $apsSecond ") + + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_TEMP_BASAL_SETTING" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingResponsePacket.kt new file mode 100644 index 0000000000..843f245e96 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TempBasalSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TempBasalSettingResponsePacket + */ +class TempBasalSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x8A.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalSettingResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TempBasalSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_TEMP_BASAL_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquirePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquirePacket.kt new file mode 100644 index 0000000000..722e2030d2 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquirePacket.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TimeInquirePacket + */ +class TimeInquirePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x4F.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TimeInquirePacket init") + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_TIME_REQUEST" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquireResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquireResponsePacket.kt new file mode 100644 index 0000000000..86b1f3befd --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeInquireResponsePacket.kt @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TimeInquireResponsePacket + */ +class TimeInquireResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x50.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TimeInquireResponsePacket init") + } + + override fun handleMessage(data: ByteArray?) { + val result = defect(data) + if (result != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TimeInquireResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + val result2 = getByteToInt(bufferData) + if(!isSuccInquireResponseResult(result2)) { + failed = true + return; + } + } + + override fun getFriendlyName(): String { + return "PUMP_TIME_INQUIRE_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeReportPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeReportPacket.kt new file mode 100644 index 0000000000..2a284defe8 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeReportPacket.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TimeReportPacket + */ +class TimeReportPacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result =0 + init { + msgType = 0xCF.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TimeReportPacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TimeReportPacket Report Packet Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + diaconnG8Pump.year = getByteToInt(bufferData) // yyyy + diaconnG8Pump.month = getByteToInt(bufferData) // month + diaconnG8Pump.day = getByteToInt(bufferData) // day + diaconnG8Pump.hour = getByteToInt(bufferData) // hour + diaconnG8Pump.minute = getByteToInt(bufferData) // min + diaconnG8Pump.second = getByteToInt(bufferData) // second + + aapsLogger.debug(LTag.PUMPCOMM, "year --> ${diaconnG8Pump.year }") + aapsLogger.debug(LTag.PUMPCOMM, "month --> ${diaconnG8Pump.month }") + aapsLogger.debug(LTag.PUMPCOMM, "day --> ${diaconnG8Pump.day }") + aapsLogger.debug(LTag.PUMPCOMM, "hour --> ${diaconnG8Pump.hour }") + aapsLogger.debug(LTag.PUMPCOMM, "minute --> ${diaconnG8Pump.minute}") + aapsLogger.debug(LTag.PUMPCOMM, "second --> ${diaconnG8Pump.second}") + } + + override fun getFriendlyName(): String { + return "PUMP_TIME_REPORT" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingPacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingPacket.kt new file mode 100644 index 0000000000..ad158bb211 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingPacket.kt @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import org.joda.time.DateTime +import org.joda.time.DateTimeZone +import javax.inject.Inject + +/** + * TimeSettingPacket Request Packet + */ +class TimeSettingPacket( + injector: HasAndroidInjector, + private var time: Long = 0, + private var offset:Int = 0 +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + + init { + msgType = 0x0F + aapsLogger.debug(LTag.PUMPCOMM, "Time Sync between Phone and Pump") + + } + + override fun encode(msgSeq:Int): ByteArray { + val buffer = prefixEncode(msgType, msgSeq, MSG_CON_END); + val date = DateTime(time).withZone(DateTimeZone.UTC) + buffer.put((date.year - 2000 and 0xff).toByte()) + buffer.put((date.monthOfYear and 0xff).toByte()) + buffer.put((date.dayOfMonth and 0xff).toByte()) + buffer.put((date.hourOfDay + offset and 0xff).toByte()) + buffer.put((date.minuteOfHour and 0xff).toByte()) + buffer.put((date.secondOfMinute and 0xff).toByte()) + + return suffixEncode(buffer) + } + + override fun getFriendlyName(): String { + return "PUMP_TIME_SETTING_REQUEST" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingResponsePacket.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingResponsePacket.kt new file mode 100644 index 0000000000..ef78bf735f --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/packet/TimeSettingResponsePacket.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.diaconn.packet + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.logging.LTag +import javax.inject.Inject + +/** + * TimeSettingResponsePacket + */ +class TimeSettingResponsePacket( + injector: HasAndroidInjector +) : DiaconnG8Packet(injector ) { + + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + var result = 0 + init { + msgType = 0x8F.toByte() + aapsLogger.debug(LTag.PUMPCOMM, "TimeSettingResponsePacket init ") + } + + override fun handleMessage(data: ByteArray?) { + val defectCheck = defect(data) + if (defectCheck != 0) { + aapsLogger.debug(LTag.PUMPCOMM, "TimeSettingResponsePacket Got some Error") + failed = true + return + } else failed = false + + val bufferData = prefixDecode(data) + result = getByteToInt(bufferData) + + if(!isSuccSettingResponseResult(result)) { + diaconnG8Pump.bolusStartErrorCode = result + failed = true + return + } + diaconnG8Pump.otpNumber = getIntToInt(bufferData) + + aapsLogger.debug(LTag.PUMPCOMM, "Result --> $result") + aapsLogger.debug(LTag.PUMPCOMM, "otpNumber --> ${diaconnG8Pump.otpNumber}") + } + + override fun getFriendlyName(): String { + return "PUMP_TIME_SETTING_RESPONSE" + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BATTERY.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BATTERY.kt new file mode 100644 index 0000000000..db44c69fb3 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BATTERY.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* Battery Shortage Alarm Log +*/ +class LOG_ALARM_BATTERY private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL + private val alarmLevel: Byte, // 1=OCCUR, 2=STOP + private val ack: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_ALARM_BATTERY{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", alarmLevel=").append(alarmLevel.toInt()) + sb.append(", ack=").append(ack.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x28 + fun parse(data: String): LOG_ALARM_BATTERY { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_ALARM_BATTERY( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BLOCK.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BLOCK.kt new file mode 100644 index 0000000000..29b827e01e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_BLOCK.kt @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* Injection Blocked Alarm Log +*/ +class LOG_ALARM_BLOCK private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL + val alarmLevel: Byte, // 1=OCCUR + val ack: Byte, + val amount: Short, // 1=BASE, 2=Meal, 3=snack , 4=square, 5=dual, 6=tube change, 7=needle change, 8=insulin change + val reason: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_ALARM_BLOCK{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", alarmLevel=").append(alarmLevel.toInt()) + sb.append(", ack=").append(ack.toInt()) + sb.append(", amount=").append(amount.toInt()) + sb.append(", reason=").append(reason.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x29 + fun parse(data: String): LOG_ALARM_BLOCK { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_ALARM_BLOCK( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_SHORTAGE.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_SHORTAGE.kt new file mode 100644 index 0000000000..4d3acfbab4 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_ALARM_SHORTAGE.kt @@ -0,0 +1,56 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* Insulin shortage alarm +*/ +class LOG_ALARM_SHORTAGE private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 1=INFO, 2=WARNING, 3=MAJOR, 4=CRITICAL + val alarmLevel: Byte, // 1=OCCUR, 2=STOP + val ack: Byte, // (1~100U) + val remain: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_ALARM_SHORTAGE{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", alarmLevel=").append(alarmLevel.toInt()) + sb.append(", ack=").append(ack.toInt()) + sb.append(", remain=").append(remain.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x2A + fun parse(data: String): LOG_ALARM_SHORTAGE { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_ALARM_SHORTAGE( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_INJECTOR_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_INJECTOR_SUCCESS.kt new file mode 100644 index 0000000000..d5702c0e5b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_INJECTOR_SUCCESS.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 주사기 교체 성공 +*/ +class LOG_CHANGE_INJECTOR_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val primeAmount: Short, // 47.5=4750 + val remainAmount: Short, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_CHANGE_INJECTOR_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", primeAmount=").append(primeAmount.toInt()) + sb.append(", remainAmount=").append(remainAmount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x1A + fun parse(data: String): LOG_CHANGE_INJECTOR_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_CHANGE_INJECTOR_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_NEEDLE_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_NEEDLE_SUCCESS.kt new file mode 100644 index 0000000000..556b5d33d9 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_NEEDLE_SUCCESS.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 바늘 공기빼기 성공 +*/ +class LOG_CHANGE_NEEDLE_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val primeAmount: Short, // 47.5=4750 + val remainAmount: Short, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_CHANGE_NEEDLE_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", primeAmount=").append(primeAmount.toInt()) + sb.append(", remainAmount=").append(remainAmount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x1C + fun parse(data: String): LOG_CHANGE_NEEDLE_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_CHANGE_NEEDLE_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_TUBE_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_TUBE_SUCCESS.kt new file mode 100644 index 0000000000..ae97bddcce --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_CHANGE_TUBE_SUCCESS.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 튜브 공기빼기 성공 +*/ +class LOG_CHANGE_TUBE_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val primeAmount: Short, // 47.5=4750 + val remainAmount: Short, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_CHANGE_TUBE_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", primeAmount=").append(primeAmount.toInt()) + sb.append(", remainAmount=").append(remainAmount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x18 + fun parse(data: String): LOG_CHANGE_TUBE_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_CHANGE_TUBE_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY.kt new file mode 100644 index 0000000000..e7768b2e00 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 당일 주입 총량 (식사, 추가) +*/ +class LOG_INJECTION_1DAY private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 당일 식사주입 총량 47.5=4750 + val mealAmount: Short, // 당일 추가주입 총량 47.5=4750 + val extAmount: Short, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECTION_1DAY{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", mealAmount=").append(mealAmount.toInt()) + sb.append(", extAmount=").append(extAmount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x2F + fun parse(data: String): LOG_INJECTION_1DAY { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECTION_1DAY( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY_BASAL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY_BASAL.kt new file mode 100644 index 0000000000..1740d54276 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1DAY_BASAL.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 당일 주입 총량 (기저) +*/ +class LOG_INJECTION_1DAY_BASAL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + // 당일 기저주입 총량 47.5=4750 + val amount: Short, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECTION_1DAY_BASAL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", amount=").append(amount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + const val LOG_KIND: Byte = 0x2E + fun parse(data: String): LOG_INJECTION_1DAY_BASAL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECTION_1DAY_BASAL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer) + ) + } + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1HOUR_BASAL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1HOUR_BASAL.kt new file mode 100644 index 0000000000..f8acab887f --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_1HOUR_BASAL.kt @@ -0,0 +1,61 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 1시간 단위 기저 주입량 +*/ +class LOG_INJECTION_1HOUR_BASAL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + tbBeforeAmount: Short, + tbAfterAmount: Short, + val batteryRemain: Byte, + // 남은 전체 인슐린 량(47.5=4750) + private val remainTotalAmount: Short +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + val beforeAmount // 해당시간의 임시기저 계산 전 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + : Short = tbBeforeAmount + val afterAmount // 해당시간의 임시기저 계산 후 기저주입량: 기저주입막힘 발생 시 기저주입 막힘량 제외, 기저정지로 인해 주입되지 않은 량 제외, 리셋으로 인해 주입되지 않은 량 제외(47.5=4750) + : Short = tbAfterAmount + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECTION_1HOUR_BASAL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", tbBeforeAmount=").append(beforeAmount.toInt()) + sb.append(", tbAfterAmount=").append(afterAmount.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append(", remainTotalAmount=").append(remainTotalAmount.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x2C + fun parse(data: String): LOG_INJECTION_1HOUR_BASAL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECTION_1HOUR_BASAL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_DUAL_NORMAL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_DUAL_NORMAL.kt new file mode 100644 index 0000000000..d46ee4790a --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECTION_DUAL_NORMAL.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 듀얼(일반) 주입량: 듀얼(일반) 주입 완료 시 기록하는 방식 +*/ +class LOG_INJECTION_DUAL_NORMAL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 설정량 47.5=4750 + val setAmount: Short, // 주입량 47.5=4750 + val injectAmount: Short, // 1분 단위 주입 시간 Ex) 124 = 124분 = 2시간 4분 + private val injectTime: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECTION_DUAL_NORMAL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x35 + fun parse(data: String): LOG_INJECTION_DUAL_NORMAL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECTION_DUAL_NORMAL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_FAIL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_FAIL.kt new file mode 100644 index 0000000000..bafaea8de9 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_FAIL.kt @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* Dual Injection Fail Log +*/ +class LOG_INJECT_DUAL_FAIL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val injectNormAmount: Short, // 47.5=4750 + val injectSquareAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지 + val reason: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_DUAL_FAIL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", injectNormAmount=").append(injectNormAmount.toInt()) + sb.append(", injectSquareAmount=").append(injectSquareAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", reason=").append(reason.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x11 + fun parse(data: String): LOG_INJECT_DUAL_FAIL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_DUAL_FAIL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_SUCCESS.kt new file mode 100644 index 0000000000..c6738c38b2 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_DUAL_SUCCESS.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 듀얼주입 성공 +*/ +class LOG_INJECT_DUAL_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val injectNormAmount: Short, // 47.5=4750 + val injectSquareAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_DUAL_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", injectNormAmount=").append(injectNormAmount.toInt()) + sb.append(", injectSquareAmount=").append(injectSquareAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x10 + fun parse(data: String): LOG_INJECT_DUAL_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_DUAL_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_FAIL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_FAIL.kt new file mode 100644 index 0000000000..bc667b28e9 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_FAIL.kt @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 식사주입 실패 +*/ +class LOG_INJECT_MEAL_FAIL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + private val setAmount: Short, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, // 아침=1, 점심=2, 저녁=3 + val time: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지 + val reason: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_MEAL_FAIL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", time=").append(time.toInt()) + sb.append(", reason=").append(reason.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x09 + fun parse(data: String): LOG_INJECT_MEAL_FAIL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_MEAL_FAIL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_SUCCESS.kt new file mode 100644 index 0000000000..23e7f27b57 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_MEAL_SUCCESS.kt @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 식사주입 성공 +*/ +class LOG_INJECT_MEAL_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + private val setAmount: Short, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, // 아침=1, 점심=2, 저녁=3 + val time: Byte, + batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + val batteryRemain: Byte = batteryRemain + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_MEAL_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", time=").append(time.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x08 + fun parse(data: String): LOG_INJECT_MEAL_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_MEAL_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_FAIL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_FAIL.kt new file mode 100644 index 0000000000..2e9eb5fe0d --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_FAIL.kt @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 일반주입 실패 +*/ +class LOG_INJECT_NORMAL_FAIL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val setAmount: Short, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + val injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지 + val reason: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_NORMAL_FAIL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", reason=").append(reason.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0B + fun parse(data: String): LOG_INJECT_NORMAL_FAIL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_NORMAL_FAIL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_SUCCESS.kt new file mode 100644 index 0000000000..be3804eb00 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_NORMAL_SUCCESS.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 일반주입 성공 +*/ +class LOG_INJECT_NORMAL_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val setAmount: Short, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + val injectTime: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_NORMAL_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0A + fun parse(data: String): LOG_INJECT_NORMAL_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_NORMAL_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_FAIL.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_FAIL.kt new file mode 100644 index 0000000000..b6a4d990f1 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_FAIL.kt @@ -0,0 +1,61 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 스퀘어주입 실패 +*/ +class LOG_INJECT_SQUARE_FAIL private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, // 1=주입막힘, 2=배터리잔량부족, 3=약물부족, 4=사용자중지, 5=시스템리셋, 6=기타, 7=긴급정지 + val reason: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_SQUARE_FAIL{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", reason=").append(reason.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0E + fun parse(data: String): LOG_INJECT_SQUARE_FAIL { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_SQUARE_FAIL( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_SUCCESS.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_SUCCESS.kt new file mode 100644 index 0000000000..168903de2b --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_INJECT_SQUARE_SUCCESS.kt @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 스퀘어주입 성공 +*/ +class LOG_INJECT_SQUARE_SUCCESS private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val injectAmount: Short, // 1분단위 주입시간(124=124분=2시간4분) + private val injectTime: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_INJECT_SQUARE_SUCCESS{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", injectAmount=").append(injectAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0D + fun parse(data: String): LOG_INJECT_SQUARE_SUCCESS { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_INJECT_SQUARE_SUCCESS( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_RESET_SYS_V3.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_RESET_SYS_V3.kt new file mode 100644 index 0000000000..bc7a688382 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_RESET_SYS_V3.kt @@ -0,0 +1,56 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* + * System Reset Log + */ +class LOG_RESET_SYS_V3 private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + val batteryRemain: Byte, + val reason: Byte, // 사유(1:공장초기화 후 리셋, 2:긴급정지 해제 후 리셋, 3:사용자 배터리 교체 후 리셋, 4:캘리브레이션 후 리셋, 9:예상치 못한 시스템 리셋) + val rcon1: Short, // PIC 데이터 시트 내 정의된 2바이트 값 + val rcon2: Short // PIC 데이터 시트 내 정의된 2바이트 값 +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_RESET_SYS_V3{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append(", reason=").append(reason.toInt()) + sb.append(", rcon1=").append(rcon1.toInt()) + sb.append(", rcon2=").append(rcon2.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x01 + fun parse(data: String): LOG_RESET_SYS_V3 { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_RESET_SYS_V3( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_DUAL_INJECTION.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_DUAL_INJECTION.kt new file mode 100644 index 0000000000..2ff5212bfc --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_DUAL_INJECTION.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 듀얼주입 설정(시작) +*/ +class LOG_SET_DUAL_INJECTION private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + val setNormAmount: Short, // 47.5=4750 + val setSquareAmount: Short, // 47.5=4750 + private val injectTime: Byte, // 1~30( 1: 10min ) + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_SET_DUAL_INJECTION{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setNormAmount=").append(setNormAmount.toInt()) + sb.append(", setSquareAmount=").append(setSquareAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0F + fun parse(data: String): LOG_SET_DUAL_INJECTION { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_SET_DUAL_INJECTION( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_SQUARE_INJECTION.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_SQUARE_INJECTION.kt new file mode 100644 index 0000000000..562172146e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SET_SQUARE_INJECTION.kt @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 스퀘어주입 설정(시작) +*/ +class LOG_SET_SQUARE_INJECTION private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 47.5=4750 + val setAmount: Short, // 1~30(10분 단위 값 의미) + private val injectTime: Byte, + val batteryRemain: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + fun getInjectTime(): Int { + return injectTime and 0xff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_SET_SQUARE_INJECTION{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", setAmount=").append(setAmount.toInt()) + sb.append(", injectTime=").append(injectTime and 0xff) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x0C + fun parse(data: String): LOG_SET_SQUARE_INJECTION { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_SET_SQUARE_INJECTION( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_RELEASE_V2.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_RELEASE_V2.kt new file mode 100644 index 0000000000..d27625fe8d --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_RELEASE_V2.kt @@ -0,0 +1,71 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 일시정지 중지 (기저정지 해제) +*/ +class LOG_SUSPEND_RELEASE_V2 private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + batteryRemain: Byte, + patternType: Byte +) { + + val type: Byte + val kind: Byte + val batteryRemain: Byte + val patternType // 1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2 + : Byte + + override fun toString(): String { + val sb = StringBuilder("LOG_SUSPEND_RELEASE_V2{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append(", patternType=").append(patternType.toInt()) + sb.append('}') + return sb.toString() + } + + fun getBasalPattern():String { + //1=Injection blockage, 2=Battery shortage, 3=Drug shortage, 4=User shutdown, 5=System reset, 6=Other, 7=Emergency shutdown + return when(patternType) { + 1.toByte() -> "Base" + 2.toByte() -> "Life1" + 3.toByte() -> "Life2" + 4.toByte() -> "Life3" + 5.toByte() -> "Dr1" + 6.toByte() -> "Dr2" + else -> "No Pattern" + } + } + companion object { + + const val LOG_KIND: Byte = 0x04 + fun parse(data: String): LOG_SUSPEND_RELEASE_V2 { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_SUSPEND_RELEASE_V2( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + + init { + type = PumplogUtil.getType(typeAndKind) + kind = PumplogUtil.getKind(typeAndKind) + this.batteryRemain = batteryRemain + this.patternType = patternType + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_V2.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_V2.kt new file mode 100644 index 0000000000..4f69dc4c89 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_SUSPEND_V2.kt @@ -0,0 +1,63 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 일시정지 시작 (기저정지) +*/ +class LOG_SUSPEND_V2 private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + val batteryRemain: Byte, // 1=기본, 2=생활1, 3=생활2, 4=생활3, 5=닥터1, 6=닥터2 + val patternType: Byte +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + override fun toString(): String { + val sb = StringBuilder("LOG_SUSPEND_V2{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", batteryRemain=").append(batteryRemain.toInt()) + sb.append(", patternType=").append(patternType.toInt()) + sb.append('}') + return sb.toString() + } + + fun getBasalPattern(): String { + //1=Injection blockage, 2=Battery shortage, 3=Drug shortage, 4=User shutdown, 5=System reset, 6=Other, 7=Emergency shutdown + return when(patternType) { + 1.toByte() -> "Base" + 2.toByte() -> "Life1" + 3.toByte() -> "Life2" + 4.toByte() -> "Life3" + 5.toByte() -> "Dr1" + 6.toByte() -> "Dr2" + else -> "No Pattern" + } + } + + companion object { + + const val LOG_KIND: Byte = 0x03 + fun parse(data: String): LOG_SUSPEND_V2 { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_SUSPEND_V2( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_START_V3.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_START_V3.kt new file mode 100644 index 0000000000..029fe115e0 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_START_V3.kt @@ -0,0 +1,61 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import org.apache.commons.lang3.StringUtils +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 임시기저 설정(시작) +*/ +class LOG_TB_START_V3 private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, // 임시기저 시간(30분 ~ 24시간, 2 ~ 96, 1당 15분 단위 증감) + val tbTime: Byte, // 임시기저 주입량/률, Rate: 1000(0.00U) ~ 1600(6.00U), Ratio: 50000(0%) ~ 50200(200%), 50000이상이면 주입률로 판정, 별도 계산/역산식 참조 + private val tbInjectRateRatio: Short, + private val tbDttm: String // 앱에서 생성 전달한 임시기저 시작(요청) 시간 +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getTbInjectRateRatio(): Int { + return tbInjectRateRatio and 0xffff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_TB_START_V3{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", tbTime=").append(tbTime.toInt()) + sb.append(", tbInjectRateRatio=").append(tbInjectRateRatio and 0xffff) + if (!StringUtils.equals(tbDttm, PumplogUtil.getDttm("ffffffff"))) { + sb.append(", tbDttm=").append(tbDttm) + } + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x12 + fun parse(data: String): LOG_TB_START_V3 { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_TB_START_V3( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getDttm(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_STOP_V3.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_STOP_V3.kt new file mode 100644 index 0000000000..f1dc88fb61 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/LOG_TB_STOP_V3.kt @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.diaconn.pumplog + +import okhttp3.internal.and +import org.apache.commons.lang3.StringUtils +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/* +* 임시기저 중지(완료) +*/ +class LOG_TB_STOP_V3 private constructor( + val data: String, + val dttm: String, + typeAndKind: Byte, + // 임시기저 주입량/률, Rate: 1000(0.00U) ~ 1600(6.00U), Ratio: 50000(0%) ~ 50200(200%), 50000이상이면 주입률로 판정, 별도 계산/역산식 참조 + private val tbInjectRateRatio: Short, + // 0=완료, 4=사용자중단, 6=기타, 7=긴급정지 + val reason: Byte, + // 앱에서 생성 전달한 임시기저 시작(요청) 시간 + private val tbDttm: String +) { + + val type: Byte = PumplogUtil.getType(typeAndKind) + val kind: Byte = PumplogUtil.getKind(typeAndKind) + + fun getTbInjectRateRatio(): Int { + return tbInjectRateRatio and 0xffff + } + + override fun toString(): String { + val sb = StringBuilder("LOG_TB_STOP_V3{") + sb.append("LOG_KIND=").append(LOG_KIND.toInt()) + sb.append(", data='").append(data).append('\'') + sb.append(", dttm='").append(dttm).append('\'') + sb.append(", type=").append(type.toInt()) + sb.append(", kind=").append(kind.toInt()) + sb.append(", tbInjectRateRatio=").append(tbInjectRateRatio and 0xffff) + sb.append(", reason=").append(reason.toInt()) + if (!StringUtils.equals(tbDttm, PumplogUtil.getDttm("ffffffff"))) { + sb.append(", tbDttm=").append(tbDttm) + } + sb.append('}') + return sb.toString() + } + + companion object { + + const val LOG_KIND: Byte = 0x13 + fun parse(data: String): LOG_TB_STOP_V3 { + val bytes = PumplogUtil.hexStringToByteArray(data) + val buffer = ByteBuffer.wrap(bytes) + buffer.order(ByteOrder.LITTLE_ENDIAN) + return LOG_TB_STOP_V3( + data, + PumplogUtil.getDttm(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getShort(buffer), + PumplogUtil.getByte(buffer), + PumplogUtil.getDttm(buffer) + ) + } + } + +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/PumplogUtil.java b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/PumplogUtil.java new file mode 100644 index 0000000000..edb6288c92 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/pumplog/PumplogUtil.java @@ -0,0 +1,157 @@ +package info.nightscout.androidaps.diaconn.pumplog; + +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.StringUtils; + +import java.nio.ByteBuffer; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +/* + * 디아콘 G8 펌프 로그 유틸리티 클래스 + */ +public class PumplogUtil { + /* + * 바이트버퍼에서 4바이트 날짜를 구한다. + * @param buffer 바이트버퍼 + * @return GMT 날짜 문자열 + */ + public static String getDttm(ByteBuffer buffer) { + byte b0 = buffer.get(); + byte b1 = buffer.get(); + byte b2 = buffer.get(); + byte b3 = buffer.get(); + long pumpTime = Long.parseLong(String.format("%02x%02x%02x%02x", b3, b2, b1, b0), 16); + long epochTime = new Date(0).getTime(); // 1970-01-01 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("UCT")); + return sdf.format(new Date(epochTime + pumpTime * 1000)); + } + + /* + * 바이트버퍼에서 4바이트 날짜를 구한다. + * @param data 로그데이터 + * @return GMT 날짜 문자열 + */ + public static String getDttm(String data) { + byte[] bytes = PumplogUtil.hexStringToByteArray(data); + byte b0 = bytes[0]; + byte b1 = bytes[1]; + byte b2 = bytes[2]; + byte b3 = bytes[3]; + long pumpTime = Long.parseLong(String.format("%02x%02x%02x%02x", b3, b2, b1, b0), 16); + long epochTime = new Date(0).getTime(); // 1970-01-01 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + return sdf.format(new Date(epochTime + pumpTime * 1000)); + } + + /* + * 바이트버퍼에서 1바이트를 구한다. + * @param buffer 바이트버퍼 + * @return byte + */ + public static byte getByte(ByteBuffer buffer) { + return buffer.get(); + } + + /* + * 바이트버퍼에서 2바이트를 구한다. + * @param buffer 바이트버퍼 + * @return short + */ + public static short getShort(ByteBuffer buffer) { + return buffer.getShort(); + } + + /* + * 바이트버퍼에서 4바이트를 구한다. + * @param buffer 바이트버퍼 + * @return int + */ + public static int getInt(ByteBuffer buffer) { + return buffer.getInt(); + } + + /* + * 로그데이터에서 로그 타입 바이트를 구한다. + * @param data 로그데이터 + * @return byte + */ + public static byte getType(String data) { + byte[] bytes = hexStringToByteArray(data); + return getType(bytes[4]); + } + + /* + * 로그데이터에서 로그 종류 바이트를 구한다. + * @param data 로그데이터 + * @return byte + */ + public static byte getKind(String data) { + byte[] bytes = hexStringToByteArray(data); + //System.out.println("byte=" + Arrays.toString(bytes)); + return getKind(bytes[4]); + } + + /* + * 바이트 데이터에서 로그 타입 부분을 추출 한다. + * @param b 바이트 + * @return byte + */ + public static byte getType(byte b) { + return (byte) ((b >> 6) & 0b00000011); // 상위 2비트 추출 + } + + /* + * 바이트 데이터에서 로그 종류 부분을 추출 한다. + * @param b 바이트 + * @return byte + */ + public static byte getKind(byte b) { + return (byte) (b & 0b00111111); // 하위 6비트 추출 + } + + /* + * 16진수 표기 문자열을 바이트 배열로 변환한다. + * @param s 16진수 표기 문자열 + * @return byte[] + */ + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + /* + * 펌프 시간을 날짜 타입으로 변환한다.(펌프에서 GMT기준으로 초를 구하므로, Date 변환시 GMT 기준으로 구해야 한다. + * @param data 1970.1.1이후 경과한 초 + * @return 날짜(GMT기준) + */ + public static Date pumpTimeToGMTDate(Integer data) { + long epochTime = new Date(0).getTime(); // 1970-01-01 + long pumpTime = data.longValue() * 1000; // 초를 밀리초 단위로 변환 + int timeZoneOffset = TimeZone.getDefault().getRawOffset(); // GMT와 로컬 타임존 사이의 차이 + return new Date(epochTime + pumpTime - timeZoneOffset); + } + + /* + * 펌프 버전이 해당 버전보다 크거나 같은지 여부 확인(새로운 기능이 추가된 버전을 체크하기 위함) + */ + public static boolean isPumpVersionGe(String pump_version, int major, int minor) { + String version = RegExUtils.replaceAll(pump_version, "[^\\d\\.]", ""); + int pump_major = Integer.parseInt(StringUtils.split(version, ".")[0]); + int pump_minor = Integer.parseInt(StringUtils.split(version, ".")[1]); + if (pump_major > major) { // 메이저 버전이 클 때 + return true; + } else if (pump_major < major) { // 메이저 버전이 작을 때 + return false; + } else { // 메이저 버전이 같다면 마이너 버전이 같거나 클 때 + return pump_minor >= minor; + } + } +} \ No newline at end of file diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt new file mode 100644 index 0000000000..83b8475b9e --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt @@ -0,0 +1,367 @@ +package info.nightscout.androidaps.diaconn.service + +import android.bluetooth.* +import android.content.Context +import android.content.Intent +import android.os.SystemClock +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.activities.ErrorHelperActivity +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.packet.* +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.extensions.notify +import info.nightscout.androidaps.extensions.waitMillis +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.utils.resources.ResourceHelper +import java.util.* +import java.util.concurrent.ScheduledFuture +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class BLECommonService @Inject internal constructor( + private val injector: HasAndroidInjector, + private val aapsLogger: AAPSLogger, + private val resourceHelper: ResourceHelper, + private val context: Context, + private val rxBus: RxBusWrapper, + private val diaconnG8ResponseMessageHashTable: DiaconnG8ResponseMessageHashTable, + private val diaconnG8SettingResponseMessageHashTable: DiaconnG8SettingResponseMessageHashTable, + private val diaconnG8Pump: DiaconnG8Pump, +){ + + companion object { + private const val WRITE_DELAY_MILLIS: Long = 50 + private const val INDICATION_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" + private const val WRITE_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" + private const val CHARACTERISTIC_CONFIG_UUID = "00002902-0000-1000-8000-00805f9b34fb" + } + + private var scheduledDisconnection: ScheduledFuture<*>? = null + private var processedMessage: DiaconnG8Packet? = null + private var processedMessageByte: ByteArray? = null + private val mSendQueue = ArrayList() + private var bluetoothManager: BluetoothManager? = null + private var bluetoothAdapter: BluetoothAdapter? = null + private var connectDeviceName: String? = null + private var bluetoothGatt: BluetoothGatt? = null + + + var isConnected = false + var isConnecting = false + private var uartIndicate: BluetoothGattCharacteristic? = null + private var uartWrite: BluetoothGattCharacteristic? = null + + private var mSequence : Int = 0 + + private fun getMsgSequence(): Int { + val seq = mSequence % 255 + mSequence++ + if (mSequence == 255) { + mSequence = 0 + } + return seq + } + + @Synchronized + fun connect(from: String, address: String?): Boolean { + aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing Bluetooth ") + if (bluetoothManager == null) { + bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + if (bluetoothManager == null) { + aapsLogger.error("Unable to initialize BluetoothManager.") + return false + } + } + bluetoothAdapter = bluetoothManager?.adapter + if (bluetoothAdapter == null) { + aapsLogger.error("Unable to obtain a BluetoothAdapter.") + return false + } + + if (address == null) { + aapsLogger.error("unspecified address.") + return false + } + + val device = bluetoothAdapter?.getRemoteDevice(address) + if (device == null) { + aapsLogger.error("Device not found. Unable to connect from: $from") + return false + } + aapsLogger.debug(LTag.PUMPBTCOMM, "Trying to create a new connection from: $from") + connectDeviceName = device.name + bluetoothGatt = device.connectGatt(context, false, mGattCallback) + + isConnected = false + isConnecting = true + return true + } + + @Synchronized + fun stopConnecting() { + isConnecting = false + } + + @Synchronized + fun disconnect(from: String) { + aapsLogger.debug(LTag.PUMPBTCOMM, "disconnect from: $from") + + // cancel previous scheduled disconnection to prevent closing upcoming connection + scheduledDisconnection?.cancel(false) + scheduledDisconnection = null + + if (bluetoothAdapter == null || bluetoothGatt == null) { + aapsLogger.error("disconnect is not possible: (mBluetoothAdapter == null) " + (bluetoothAdapter == null)) + aapsLogger.error("disconnect is not possible: (mBluetoothGatt == null) " + (bluetoothGatt == null)) + return + } + bluetoothGatt?.setCharacteristicNotification(uartIndicate, false) + bluetoothGatt?.disconnect() + isConnected = false + SystemClock.sleep(2000) + } + + @Synchronized + fun close() { + aapsLogger.debug(LTag.PUMPBTCOMM, "BluetoothAdapter close") + bluetoothGatt?.close() + bluetoothGatt = null + } + + private val mGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() { + override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { + onConnectionStateChangeSynchronized(gatt, newState) // call it synchronized + } + + override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { + aapsLogger.debug(LTag.PUMPBTCOMM, "onServicesDiscovered") + if (status == BluetoothGatt.GATT_SUCCESS) { + findCharacteristic() + } + } + + override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { + aapsLogger.debug(LTag.PUMPBTCOMM, "(응답) onCharacteristicChanged: " + DiaconnG8Packet.toHex(characteristic.value)) + // 대량로그응답 처리. + if(characteristic.value[1] == 0xb2.toByte()) { + aapsLogger.debug(LTag.PUMPBTCOMM, "(대량 로그 처리 응답) onCharacteristicChanged: " + DiaconnG8Packet.toHex(characteristic.value)) + val message = BigLogInquireResponsePacket(injector) + message.handleMessage(characteristic.value) + + // 초기화 + mSendQueue.clear() + } else { + processResponseMessage(characteristic.value) + } + } + + override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { + aapsLogger.debug(LTag.PUMPBTCOMM, "(요청) onCharacteristicWrite: " + DiaconnG8Packet.toHex(characteristic.value)) + } + } + + @Synchronized + private fun writeCharacteristicNoResponse(characteristic: BluetoothGattCharacteristic, data: ByteArray) { + Thread(Runnable { + SystemClock.sleep(WRITE_DELAY_MILLIS) + if (bluetoothAdapter == null || bluetoothGatt == null) { + aapsLogger.error("BluetoothAdapter not initialized_ERROR") + isConnecting = false + isConnected = false + return@Runnable + } + characteristic.value = data + characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE + bluetoothGatt?.writeCharacteristic(characteristic) + }).start() + SystemClock.sleep(50) + } + + // private val uartIndicateBTGattChar: BluetoothGattCharacteristic + // get() = uartIndicate + // ?: BluetoothGattCharacteristic(UUID.fromString(INDICATION_UUID), BluetoothGattCharacteristic.PROPERTY_NOTIFY, 0).also { uartIndicate = it } + + private val uartWriteBTGattChar: BluetoothGattCharacteristic + get() = uartWrite + ?: BluetoothGattCharacteristic(UUID.fromString(WRITE_UUID), BluetoothGattCharacteristic.PROPERTY_WRITE or BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, 0).also { uartWrite = it } + + private fun getSupportedGattServices(): List? { + aapsLogger.debug(LTag.PUMPBTCOMM, "getSupportedGattServices") + if (bluetoothAdapter == null || bluetoothGatt == null) { + aapsLogger.error("BluetoothAdapter not initialized_ERROR") + isConnecting = false + isConnected = false + return null + } + return bluetoothGatt?.services + } + + private fun findCharacteristic() { + val gattServices = getSupportedGattServices() ?: return + var uuid: String + for (gattService in gattServices) { + val gattCharacteristics = gattService.characteristics + for (gattCharacteristic in gattCharacteristics) { + uuid = gattCharacteristic.uuid.toString() + if (INDICATION_UUID == uuid) { + uartIndicate = gattCharacteristic + //setCharacteristicNotification(uartIndicate, true) + bluetoothGatt?.setCharacteristicNotification(uartIndicate, true) + // nRF Connect 참고하여 추가함 + val descriptor: BluetoothGattDescriptor = uartIndicate!!.getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG_UUID)) + descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE + bluetoothGatt!!.writeDescriptor(descriptor) + } + if (WRITE_UUID == uuid) { + uartWrite = gattCharacteristic + } + } + } + } + + @Synchronized + private fun onConnectionStateChangeSynchronized(gatt: BluetoothGatt, newState: Int) { + aapsLogger.debug(LTag.PUMPBTCOMM, "onConnectionStateChange newState : $newState") + if (newState == BluetoothProfile.STATE_CONNECTED) { + gatt.discoverServices() + isConnected = true + isConnecting = false + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED)) + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + close() + isConnected = false + isConnecting = false + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)) + aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected + } + } + + // the rest of packets + fun sendMessage(message: DiaconnG8Packet, waitMillis: Long) { + // 펌프로 요청하기전 변수에 담기. 마지막 요청정보 확인용. + processedMessage = message + val sequence = getMsgSequence() + aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + message.friendlyName + " Sequence >>" + sequence) + // 요청 + val bytes = message.encode(sequence) + processedMessageByte = bytes + + aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage() before mSendQueue.size :: ${mSendQueue.size}") + // 펌프에 요청 보내기. + writeCharacteristicNoResponse(uartWriteBTGattChar, bytes) + // 요청 큐에 요청할 바이트 정보 담기. + synchronized(mSendQueue) { + if(mSendQueue.size > 10) mSendQueue.clear() + mSendQueue.add(bytes) + } + aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage() after mSendQueue.size :: ${mSendQueue.size}") + + // 메시지동기화 + synchronized(message) { + try { + message.waitMillis(waitMillis) //0.5초 대기. + } catch (e: InterruptedException) { + aapsLogger.error("sendMessage InterruptedException", e) + } + } + } + + // process common packet response + private fun processResponseMessage(data: ByteArray) { + isConnected = true + + //요청정보 + val originalMessageSeq = processedMessage?.getSeq(processedMessageByte) + + // 응답정보 + val receivedCommand = DiaconnG8Packet(injector).getCmd(data) + val receivedSeq = DiaconnG8Packet(injector).getSeq(data) + val receivedType = DiaconnG8Packet(injector).getType(data) + + aapsLogger.debug(LTag.PUMPBTCOMM, "originalMessageSeq :: $originalMessageSeq, receivedSeq :: $receivedSeq") + aapsLogger.debug(LTag.PUMPBTCOMM, "receivedCommand :: $receivedCommand") + + // 응답메시지가 조회응답인지. 설정응답인지 구분해야됨. + var message:DiaconnG8Packet? = null + // 요청시퀀스와 응답의 시퀀스가 동일한 경우에만 처리. + // 펌프로부터 받은 보고응답의 경우 처리 + if(receivedType == 3) { + message = diaconnG8ResponseMessageHashTable.findMessage(receivedCommand) + // injection Blocked Report + if(message is InjectionBlockReportPacket ) { + message.handleMessage(data) + diaconnG8Pump.bolusBlocked = true + val i = Intent(context, ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", resourceHelper.gs(R.string.injectionblocked)) + i.putExtra("title", resourceHelper.gs(R.string.injectionblocked)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(i) + return + } + // battery warning report + if(message is BatteryWarningReportPacket ) { + message.handleMessage(data) + val i = Intent(context, ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", resourceHelper.gs(R.string.needbatteryreplace)) + i.putExtra("title", resourceHelper.gs(R.string.batterywarning)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(i) + return + } + + // insulin lack warning report + if(message is InsulinLackReportPacket ) { + message.handleMessage(data) + val i = Intent(context, ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", resourceHelper.gs(R.string.needinsullinreplace)) + i.putExtra("title", resourceHelper.gs(R.string.insulinlackwarning)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(i) + return + } + + } else { + // 큐에 담긴 명령 대기중에 있는 것 조회 처리. + synchronized(mSendQueue) { + val sendQueueSize = mSendQueue.size + if (sendQueueSize > 0) { + for (i in sendQueueSize-1 downTo 0 ) { + val sendQueueSeq = DiaconnG8Packet(injector).getSeq(mSendQueue[i]) + val sendQueueType = DiaconnG8Packet(injector).getType(mSendQueue[i]) + if (sendQueueSeq == receivedSeq) { + // 설정명령에 대한 응답 + if (sendQueueType == 0) { + message = diaconnG8SettingResponseMessageHashTable.findMessage(receivedCommand) + + // 조회명령에 대한 응답 + } else if (sendQueueType == 1) { + message = diaconnG8ResponseMessageHashTable.findMessage(receivedCommand) + } + // 처리 후 큐에서 삭제. + mSendQueue.removeAt(i) + break + } + } + } + } + } + + if (message != null) { + aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + message!!.friendlyName + " " + DiaconnG8Packet.toHex(data)) + // process received data + message!!.handleMessage(data) + message!!.setReceived() + synchronized(message!!) { + // notify to sendMessage + message!!.notify() + } + } else aapsLogger.error("Unknown message received " + DiaconnG8Packet.toHex(data)) + } +} diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/DiaconnG8Service.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/DiaconnG8Service.kt new file mode 100644 index 0000000000..611f8fef23 --- /dev/null +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/DiaconnG8Service.kt @@ -0,0 +1,641 @@ +package info.nightscout.androidaps.diaconn.service + +import android.app.Service +import android.content.Context +import android.content.Intent +import android.os.Binder +import android.os.IBinder +import android.os.SystemClock +import dagger.android.DaggerService +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.activities.ErrorHelperActivity +import info.nightscout.androidaps.data.PumpEnactResult +import info.nightscout.androidaps.diaconn.DiaconnG8Plugin +import info.nightscout.androidaps.diaconn.DiaconnG8Pump +import info.nightscout.androidaps.diaconn.R +import info.nightscout.androidaps.diaconn.events.EventDiaconnG8NewStatus +import info.nightscout.androidaps.diaconn.packet.* +import info.nightscout.androidaps.dialogs.BolusProgressDialog +import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.events.EventInitializationChanged +import info.nightscout.androidaps.events.EventProfileSwitchChanged +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.Profile +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.queue.commands.Command +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import org.joda.time.DateTime +import org.joda.time.DateTimeZone +import java.util.concurrent.TimeUnit +import javax.inject.Inject +import kotlin.math.abs +import kotlin.math.ceil +import kotlin.math.min + +class DiaconnG8Service : DaggerService() { + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var sp: SP + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var context: Context + @Inject lateinit var diaconnG8Plugin : DiaconnG8Plugin + @Inject lateinit var diaconnG8Pump: DiaconnG8Pump + @Inject lateinit var diaconnG8ResponseMessageHashTable: DiaconnG8ResponseMessageHashTable + @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var constraintChecker: ConstraintChecker + @Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + @Inject lateinit var bleCommonService: BLECommonService + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var pumpSync: PumpSync + @Inject lateinit var dateUtil: DateUtil + + private val disposable = CompositeDisposable() + private val mBinder: IBinder = LocalBinder() + private var lastApproachingDailyLimit: Long = 0 + + override fun onCreate() { + super.onCreate() + disposable.add(rxBus + .toObservable(EventAppExit::class.java) + .observeOn(Schedulers.io()) + .subscribe({ stopSelf() }) { fabricPrivacy.logException(it) } + ) + } + + inner class LocalBinder : Binder() { + val serviceInstance: DiaconnG8Service + get() = this@DiaconnG8Service + } + + override fun onBind(intent: Intent): IBinder { + return mBinder + } + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + return Service.START_STICKY + } + + override fun onDestroy() { + disposable.clear() + super.onDestroy() + } + + val isConnected: Boolean + get() = bleCommonService.isConnected + + val isConnecting: Boolean + get() = bleCommonService.isConnecting + + fun connect(from: String, address: String): Boolean { + return bleCommonService.connect(from, address) + } + + fun stopConnecting() { + bleCommonService.stopConnecting() + } + + fun disconnect(from: String) { + bleCommonService.disconnect(from) + } + + fun sendMessage(message: DiaconnG8Packet, waitMillis: Long) { + bleCommonService.sendMessage(message, waitMillis) + } + + private fun sendMessage(message: DiaconnG8Packet) { + bleCommonService.sendMessage(message, 500) + } + + fun readPumpStatus() { + try { + val pump = activePlugin.activePump + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings))) + sendMessage(BasalLimitInquirePacket(injector), 2000) // basal Limit + sendMessage(SneckLimitInquirePacket(injector), 2000) // bolus Limit + sendMessage(BigMainInfoInquirePacket(injector), 2000) // Pump Main Info + sendMessage(SoundInquirePacket(injector), 2000) // sounds + sendMessage(DisplayTimeInquirePacket(injector), 2000) // display + sendMessage(LanguageInquirePacket(injector), 2000) // language + + diaconnG8Pump.lastConnection = System.currentTimeMillis() + + val profile = profileFunction.getProfile() + if (profile != null && abs(diaconnG8Pump.baseAmount - profile.getBasal()) >= pump.pumpDescription.basalStep) { + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings))) + + if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) { + rxBus.send(EventProfileSwitchChanged()) + } + } + + // 시간 설정 + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumptime))) + var timeDiff = (diaconnG8Pump.getPumpTime() - System.currentTimeMillis()) / 1000L + if (diaconnG8Pump.getPumpTime() == 0L) { + // initial handshake was not successful + // de-initialize pump + diaconnG8Pump.reset() + rxBus.send(EventDiaconnG8NewStatus()) + rxBus.send(EventInitializationChanged()) + return + } + aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds") + // phone timezone + val tz = DateTimeZone.getDefault() + val instant = DateTime.now().millis + val offsetInMilliseconds = tz.getOffset(instant).toLong() + val offset = TimeUnit.MILLISECONDS.toHours(offsetInMilliseconds).toInt() + if (abs(timeDiff) > 60) { + if (abs(timeDiff) > 60 * 60 * 1.5) { + aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds - large difference") + //If time-diff is very large, warn user until we can synchronize history readings properly + ErrorHelperActivity.runAlarm(context, resourceHelper.gs(R.string.largetimediff), resourceHelper.gs(R.string.largetimedifftitle), R.raw.error) + + + //de-initialize pump + diaconnG8Pump.reset() + rxBus.send(EventDiaconnG8NewStatus()) + rxBus.send(EventInitializationChanged()) + return + } else { + // 폰과 휴대폰의 시간 동기화 + // 임시기저가 진행 여부에 따른 시간설정 분기. + if(!diaconnG8Pump.isTempBasalInProgress) { + val msgPacket = TimeSettingPacket(injector, dateUtil.now(), offset) + sendMessage(msgPacket) + + // otp process + if(!processConfirm(msgPacket.msgType)) return + + timeDiff = (diaconnG8Pump.getPumpTime() - System.currentTimeMillis()) / 1000L + aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds") + } + } + } + loadHistory() + val eb = pumpSync.expectedPumpState().extendedBolus + diaconnG8Pump.fromExtendedBolus(eb) + val tbr = pumpSync.expectedPumpState().temporaryBasal + diaconnG8Pump.fromTemporaryBasal(tbr) + rxBus.send(EventDiaconnG8NewStatus()) + rxBus.send(EventInitializationChanged()) + //NSUpload.uploadDeviceStatus(); + if (diaconnG8Pump.dailyTotalUnits > diaconnG8Pump.maxDailyTotalUnits * Constants.dailyLimitWarning) { + aapsLogger.debug(LTag.PUMPCOMM, "Approaching daily limit: " + diaconnG8Pump.dailyTotalUnits + "/" + diaconnG8Pump.maxDailyTotalUnits) + if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) { + val reportFail = Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT) + rxBus.send(EventNewNotification(reportFail)) + pumpSync.insertAnnouncement(resourceHelper.gs(R.string.approachingdailylimit) + ": " + diaconnG8Pump.dailyTotalUnits + "/" + diaconnG8Pump.maxDailyTotalUnits + "U", null, PumpType.DIACONN_G8, diaconnG8Pump.serialNo.toString()) + lastApproachingDailyLimit = System.currentTimeMillis() + } + } + } catch (e: Exception) { + aapsLogger.error(LTag.PUMPCOMM, "Unhandled exception", e) + } + aapsLogger.debug(LTag.PUMPCOMM, "Pump status loaded") + } + + fun loadHistory(): PumpEnactResult { + if (!diaconnG8Plugin.isInitialized()) { + val result = PumpEnactResult(injector).success(false) + result.comment = "pump not initialized" + return result + } + sendMessage(LogStatusInquirePacket(injector), 1000) + + // pump version check + if(diaconnG8Pump.isPumpVersionGe2_63) { + sendMessage(IncarnationInquirePacket(injector), 1000) + } + + val result = PumpEnactResult(injector) + + // pump log status + val pumpLastNum = diaconnG8Pump.pumpLastLogNum + val pumpWrappingCount = diaconnG8Pump.pumpWrappingCount + val apsIncarnationNum = sp.getInt(resourceHelper.gs(R.string.apsIncarnationNo), 65536) + // aps last log num + val pumpSerialNo = sp.getInt(resourceHelper.gs(R.string.pumpserialno), 0) + val apsWrappingCount = sp.getInt(resourceHelper.gs(R.string.apsWrappingCount), 0) + val apsLastLogNum = sp.getInt(resourceHelper.gs(R.string.apslastLogNum), 0) + + // if first install app + if(apsWrappingCount == 0 && apsLastLogNum == 0 ) { + pumpLogDefaultSetting() + } + + // if pump reset + if(apsIncarnationNum != diaconnG8Pump.pumpIncarnationNum) { + pumpLogDefaultSetting() + sp.putInt(resourceHelper.gs(R.string.apsIncarnationNo), diaconnG8Pump.pumpIncarnationNum) + } + + // if another pump + if(pumpSerialNo != diaconnG8Pump.serialNo) { + pumpLogDefaultSetting() + sp.putInt(resourceHelper.gs(R.string.pumpserialno), diaconnG8Pump.serialNo) + } + + val apsLastNum = apsWrappingCount * 10000 + apsLastLogNum + if((pumpWrappingCount * 10000 + pumpLastNum) < apsLastLogNum ) { + pumpLogDefaultSetting() + } + + val start:Int? // log sync startNo + val end:Int? // log sync endNo + if (((pumpWrappingCount * 10000 + pumpLastNum) - apsLastNum) > 10000) { + start = pumpLastNum + end = 10000 + } else if (pumpWrappingCount > apsWrappingCount && apsLastLogNum < 9999) { + start = apsLastLogNum + 1 + end = 10000 + } else if (pumpWrappingCount > apsWrappingCount && apsLastLogNum >= 9999) { + start = 0 + end = pumpLastNum + } else { + start = apsLastLogNum + 1 + end = pumpLastNum + } + + // pump log loop size + val pumpLogPageSize = 11 + val loopCount: Int = ceil (((end - start) / 11.0)).toInt() + + // log sync start! + if (loopCount > 0) { + diaconnG8Pump.isProgressPumpLogSync = true + + for (i in 0 until loopCount) { + val startLogNo: Int = start + i * pumpLogPageSize + val endLogNo: Int = startLogNo + min(end - startLogNo, pumpLogPageSize) + val msg = BigLogInquirePacket(injector, startLogNo, endLogNo, 100) + sendMessage(msg) + } + diaconnG8Pump.historyDoneReceived = true + while (!diaconnG8Pump.historyDoneReceived && bleCommonService.isConnected) { + SystemClock.sleep(100) + } + result.success(true) + diaconnG8Pump.lastConnection = System.currentTimeMillis() + } + return result + } + + fun setUserSettings(): PumpEnactResult { + val result = PumpEnactResult(injector) + + val msg: DiaconnG8Packet = when(diaconnG8Pump.setUserOptionType) { + DiaconnG8Pump.ALARM -> SoundSettingPacket(injector, diaconnG8Pump.beepAndAlarm, diaconnG8Pump.alarmIntesity) + DiaconnG8Pump.LCD -> DisplayTimeoutSettingPacket(injector, diaconnG8Pump.lcdOnTimeSec) + DiaconnG8Pump.LANG -> LanguageSettingPacket(injector, diaconnG8Pump.selectedLanguage) + DiaconnG8Pump.BOLUS_SPEED -> BolusSpeedSettingPacket(injector, diaconnG8Pump.bolusSpeed) + else -> null + } ?: return result.success(false) + + sendMessage(msg, 2000) + + + + // pump confirm + if(diaconnG8Pump.otpNumber == 0) { + aapsLogger.error(LTag.PUMPCOMM, "otp is not received yet") + result.success(false) + result.comment("펌프와 연결 상태를 확인해주세요.") + return result + } + + sendMessage(AppConfirmSettingPacket(injector, msg.msgType, diaconnG8Pump.otpNumber)) + + diaconnG8Pump.otpNumber = 0 + SystemClock.sleep(100) + return result.success(true) + } + + fun bolus(insulin: Double, carbs: Int, carbTime: Long, t: EventOverviewBolusProgress.Treatment): Boolean { + if (!isConnected) return false + if (BolusProgressDialog.stopPressed) return false + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.startingbolus))) + + // bolus speed setting + val apsPrefBolusSpeed = sp.getInt("g8_bolusspeed", 5) + val isSpeedSyncToPump = sp.getBoolean("diaconn_g8_isbolusspeedsync", false) + + // aps speed check + if(!isSpeedSyncToPump) { + val msg = BolusSpeedSettingPacket(injector, apsPrefBolusSpeed) + sendMessage(msg, 2000) + sendMessage(AppConfirmSettingPacket(injector, msg.msgType, diaconnG8Pump.otpNumber)) + diaconnG8Pump.otpNumber = 0 + } + + // pump bolus speed inquire + sendMessage(BolusSpeedInquirePacket(injector), 1000) + diaconnG8Pump.bolusDone = false + diaconnG8Pump.bolusingTreatment = t + diaconnG8Pump.bolusAmountToBeDelivered = insulin + diaconnG8Pump.bolusStopped = false + diaconnG8Pump.bolusStopForced = false + diaconnG8Pump.bolusProgressLastTimeStamp = dateUtil.now() + val start = InjectionSnackSettingPacket(injector, (insulin * 100).toInt()) + if (carbs > 0) { + pumpSync.syncCarbsWithTimestamp(carbTime, carbs.toDouble(), null, PumpType.DIACONN_G8, diaconnG8Pump.serialNo.toString()) + } + val bolusStart = System.currentTimeMillis() + if (insulin > 0) { + if (!diaconnG8Pump.bolusStopped) { + sendMessage(start, 1000) + // otp process + if(!processConfirm(start.msgType)) return false + } else { + t.insulin = 0.0 + return false + } + } + val bolusingEvent = EventOverviewBolusProgress + bolusingEvent.t = t + bolusingEvent.percent = 99 + //diaconnG8Pump.bolusingTreatment = null + var speed = 12 + when (diaconnG8Pump.speed) { + 1 -> speed = 60 + 2 -> speed = 30 + 3 -> speed = 20 + 4 -> speed = 15 + 5 -> speed = 12 + 6 -> speed = 10 + 7 -> speed = 9 + 8 -> speed = 8 + } + + val bolusDurationInMSec = (insulin * speed * 1000).toLong() + val expectedEnd = bolusStart + bolusDurationInMSec + 7500L + val totalwaitTime = (expectedEnd - System.currentTimeMillis()) /1000 + while (!diaconnG8Pump.bolusDone) { + val waitTime = (expectedEnd - System.currentTimeMillis()) / 1000 + bolusingEvent.status = String.format(resourceHelper.gs(R.string.waitingforestimatedbolusend), if(waitTime < 0) 0 else waitTime) + var progressPecent = 0 + if(totalwaitTime > waitTime) { + progressPecent = ((totalwaitTime - waitTime) * 100 / totalwaitTime).toInt() + } + bolusingEvent.percent = min(progressPecent, 100) + rxBus.send(bolusingEvent) + SystemClock.sleep(200) + } + + // do not call loadHistory() directly, reconnection may be needed + commandQueue.loadEvents(object : Callback() { + override fun run() { + // reread bolus status + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus))) + sendMessage(InjectionSnackInquirePacket(injector), 1000) // last bolus + // 볼러스 결과 보고패킷에서 처리함. + bolusingEvent.percent = 100 + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.disconnecting))) + } + }) + return !start.failed + } + + fun bolusStop() { + val stop = InjectionCancelSettingPacket(injector, 0x07.toByte()) + + diaconnG8Pump.bolusStopForced = true + if (isConnected) { + sendMessage(stop,2000) + // otp process + if(!processConfirm(stop.msgType)) return + while (!diaconnG8Pump.bolusStopped) { + SystemClock.sleep(200) + } + } else { + diaconnG8Pump.bolusStopped = true + } + } + + fun tempBasal(absoluteRate: Double, durationInHours: Int): Boolean { + if (!isConnected) return false + if (diaconnG8Pump.isTempBasalInProgress) { + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))) + val msgPacket = TempBasalSettingPacket(injector, 2, diaconnG8Pump.tbTime, diaconnG8Pump.tbInjectRateRatio) + // tempbasal stop + sendMessage(msgPacket, 2000) + // otp process + if(!processConfirm(msgPacket.msgType)) return false + diaconnG8Pump.tempBasalStart= dateUtil.now() + } + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))) + val tbInjectRate = ((absoluteRate*100) + 1000).toInt() + val msgTBR = TempBasalSettingPacket(injector, 1, (durationInHours * 60) / 15, tbInjectRate) + sendMessage(msgTBR, 2000) + // otp process + if(!processConfirm(msgTBR.msgType)) return false + // pump tempbasal status inquire + sendMessage(TempBasalInquirePacket(injector)) + loadHistory() + val tbr = pumpSync.expectedPumpState().temporaryBasal + diaconnG8Pump.fromTemporaryBasal(tbr) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return msgTBR.success() + } + + fun highTempBasal(absoluteRate: Double): Boolean { + if (diaconnG8Pump.isTempBasalInProgress) { + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))) + val msgPacket = TempBasalSettingPacket(injector, 2, diaconnG8Pump.tbTime, diaconnG8Pump.tbInjectRateRatio) + // tempbasal stop + sendMessage(msgPacket, 2000) + // otp process + if(!processConfirm(msgPacket.msgType)) return false + diaconnG8Pump.tempBasalStart= dateUtil.now() + // SystemClock.sleep(500) + } + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))) + + + val tbTime = 2 // 2: 30min, 3:45min, 4:60min + var newAbsoluteRate = absoluteRate + if (absoluteRate < 0.0) newAbsoluteRate = 0.0 + if (absoluteRate > 6.0) newAbsoluteRate = 6.0 // pump Temp Max percent = 200 + + aapsLogger.debug(LTag.PUMPCOMM, "APS Temp basal start absoluteRate: $newAbsoluteRate duration 30 min") + val tbInjectRate = absoluteRate * 100 + 1000 + val msgTBR = TempBasalSettingPacket(injector, 1, tbTime, tbInjectRate.toInt()) + sendMessage(msgTBR, 2000) + // otp process + if(!processConfirm(msgTBR.msgType)) return false + sendMessage(TempBasalInquirePacket(injector)) + SystemClock.sleep(500) + loadHistory() + val tbr = pumpSync.expectedPumpState().temporaryBasal + diaconnG8Pump.fromTemporaryBasal(tbr) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return true + } + + fun tempBasalShortDuration(absoluteRate: Double, durationInMinutes: Int): Boolean { + if (durationInMinutes != 15 && durationInMinutes != 30) { + aapsLogger.error(LTag.PUMPCOMM, "Wrong duration param") + return false + } + if (diaconnG8Pump.isTempBasalInProgress) { + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))) + val msgPacket = TempBasalSettingPacket(injector, 2, diaconnG8Pump.tbTime, diaconnG8Pump.tbInjectRateRatio) + // tempbasal stop + sendMessage(msgPacket, 2000) + // otp process + if(!processConfirm(msgPacket.msgType)) return false + SystemClock.sleep(500) + } + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal))) + val tbInjectRate = absoluteRate * 100 + 1000 + val msgTBR = TempBasalSettingPacket(injector, 1, 2, tbInjectRate.toInt()) + sendMessage(msgTBR, 2000) + // otp process + if(!processConfirm(msgTBR.msgType)) return false + sendMessage(TempBasalInquirePacket(injector)) + loadHistory() + val tbr = pumpSync.expectedPumpState().temporaryBasal + diaconnG8Pump.fromTemporaryBasal(tbr) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return msgTBR.success() + } + + fun tempBasalStop(): Boolean { + if (!isConnected) return false + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal))) + val msgPacket = TempBasalSettingPacket(injector, 2, diaconnG8Pump.tbTime, diaconnG8Pump.tbInjectRateRatio) + // tempbasal stop + sendMessage(msgPacket, 2000) + // otp process + if(!processConfirm(msgPacket.msgType)) return false + SystemClock.sleep(500) + if(diaconnG8Pump.isTempBasalInProgress) { + sendMessage(TempBasalInquirePacket(injector), 2000) + } + loadHistory() + val tbr = pumpSync.expectedPumpState().temporaryBasal + diaconnG8Pump.fromTemporaryBasal(tbr) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return msgPacket.success() + } + + fun extendedBolus(insulin: Double, durationInMinutes: Int): Boolean { + if (!isConnected) return false + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingextendedbolus))) + aapsLogger.error(LTag.PUMPCOMM, "insulin: $insulin durationInMinutes: $durationInMinutes") + + val msgExtended = InjectionExtendedBolusSettingPacket(injector, (insulin * 100).toInt(), durationInMinutes, dateUtil.now()) + sendMessage(msgExtended, 2000) + // otp process + if(!processConfirm(msgExtended.msgType)) return false + + loadHistory() + val eb = pumpSync.expectedPumpState().extendedBolus + diaconnG8Pump.fromExtendedBolus(eb) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return msgExtended.success() + } + + fun extendedBolusStop(): Boolean { + if (!isConnected) return false + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingextendedbolus))) + val msgStop = InjectionCancelSettingPacket(injector, 0x08.toByte()) + sendMessage(msgStop, 2000) + // otp process + if(!processConfirm(msgStop.msgType)) return false + loadHistory() + val eb = pumpSync.expectedPumpState().extendedBolus + diaconnG8Pump.fromExtendedBolus(eb) + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return msgStop.success() + } + + fun updateBasalsInPump(profile: Profile): Boolean { + if (!isConnected) return false + rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.updatingbasalrates))) + val basalList = diaconnG8Pump.buildDiaconnG8ProfileRecord(profile) + + val requestReqPacket1 = BasalSettingPacket( + injector, 1, 1, (basalList[0] * 100).toInt(), (basalList[1] * 100).toInt(), (basalList[2] * 100).toInt(), (basalList[3] * 100).toInt(), (basalList[4] * 100).toInt(), (basalList[5] * 100).toInt() + ) + val requestReqPacket2= BasalSettingPacket( + injector, 1, 2, (basalList[6] * 100).toInt(), (basalList[7] * 100).toInt(), (basalList[8] * 100).toInt(), (basalList[9] * 100).toInt(), (basalList[10] * 100).toInt(), (basalList[11] * 100).toInt() + ) + val requestReqPacket3= BasalSettingPacket( + injector, 1, 3, (basalList[12] * 100).toInt(), (basalList[13] * 100).toInt(), (basalList[14] * 100).toInt(), (basalList[15] * 100).toInt(), (basalList[16] * 100).toInt(), (basalList[17] * 100).toInt() + ) + val requestReqPacket4= BasalSettingPacket( + injector, 1, 4, (basalList[18] * 100).toInt(), (basalList[19] * 100).toInt(), (basalList[20] * 100).toInt(), (basalList[21] * 100).toInt(), (basalList[22] * 100).toInt(), (basalList[23] * 100).toInt() + ) + // setting basal pattern 1,2,3,4 + sendMessage(requestReqPacket1) + sendMessage(requestReqPacket2) + sendMessage(requestReqPacket3) + sendMessage(requestReqPacket4) + + // otp process + if(!processConfirm(0x0B)) return false + // pump saving time about 30 second + aapsLogger.debug(LTag.PUMPCOMM, "30 seconds Waiting!!") + SystemClock.sleep(30000) + + val msgPacket = InjectionBasalSettingPacket(injector, 1) + sendMessage(msgPacket, 2000) + // otp process + if(!processConfirm(msgPacket.msgType)) return false + readPumpStatus() + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)) + return requestReqPacket4.success() + } + + private fun pumpLogDefaultSetting() { + val apsWrappingCount = diaconnG8Pump.pumpWrappingCount + val apsLastLogNum = if(diaconnG8Pump.pumpLastLogNum - 1 < 0 ) 0 else diaconnG8Pump.pumpLastLogNum - 1 + sp.putInt(resourceHelper.gs(R.string.apslastLogNum), apsLastLogNum) + sp.putInt(resourceHelper.gs(R.string.apsWrappingCount), apsWrappingCount) + } + + private fun processConfirm(msgType:Byte) : Boolean { + // pump confirm + if(diaconnG8Pump.otpNumber == 0) { + aapsLogger.error(LTag.PUMPCOMM, "otp is not received yet") + + // Comments are made as dialogs are exposed twice each in the event of an error. + // Thread { + // val i = Intent(context, ErrorHelperActivity::class.java) + // i.putExtra("soundid", R.raw.boluserror) + // i.putExtra("status", resourceHelper.gs(R.string.diaconn_g8_errotpreceivedyet)) + // i.putExtra("title", resourceHelper.gs(R.string.pumperror)) + // i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // context.startActivity(i) + // }.start() + + return false + } + sendMessage(AppConfirmSettingPacket(injector, msgType, diaconnG8Pump.otpNumber), 2000) + diaconnG8Pump.otpNumber = 0 + return true + } +} \ No newline at end of file diff --git a/diaconn/src/main/res/drawable/ic_diaconn_g8.xml b/diaconn/src/main/res/drawable/ic_diaconn_g8.xml new file mode 100644 index 0000000000..d98c6c2109 --- /dev/null +++ b/diaconn/src/main/res/drawable/ic_diaconn_g8.xml @@ -0,0 +1,6100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/diaconn/src/main/res/layout/diaconn_g8_blescanner_activity.xml b/diaconn/src/main/res/layout/diaconn_g8_blescanner_activity.xml new file mode 100644 index 0000000000..86b6406ee1 --- /dev/null +++ b/diaconn/src/main/res/layout/diaconn_g8_blescanner_activity.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + diff --git a/diaconn/src/main/res/layout/diaconn_g8_blescanner_item.xml b/diaconn/src/main/res/layout/diaconn_g8_blescanner_item.xml new file mode 100644 index 0000000000..9a39302163 --- /dev/null +++ b/diaconn/src/main/res/layout/diaconn_g8_blescanner_item.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/diaconn/src/main/res/layout/diaconn_g8_fragment.xml b/diaconn/src/main/res/layout/diaconn_g8_fragment.xml new file mode 100644 index 0000000000..43b11361ec --- /dev/null +++ b/diaconn/src/main/res/layout/diaconn_g8_fragment.xml @@ -0,0 +1,714 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +