index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. var basal = require('./basal');
  2. var targets = require('./targets');
  3. var isf = require('./isf');
  4. var carb_ratios = require('./carbs');
  5. var _ = require('lodash');
  6. function defaults ( ) {
  7. return /* profile */ {
  8. max_iob: 9 // if max_iob is not provided, will default to zero
  9. , max_daily_safety_multiplier: 5
  10. , current_basal_safety_multiplier: 6
  11. , autosens_max: 2.5
  12. , autosens_min: 0.5
  13. , rewind_resets_autosens: true // reset autosensitivity to neutral for awhile after each pump rewind
  14. // , autosens_adjust_targets: false // when autosens detects sensitivity/resistance, also adjust BG target accordingly
  15. , high_temptarget_raises_sensitivity: false // raise sensitivity for temptargets >= 101. synonym for exercise_mode
  16. , low_temptarget_lowers_sensitivity: false // lower sensitivity for temptargets <= 99.
  17. , sensitivity_raises_target: false // raise BG target when autosens detects sensitivity
  18. , resistance_lowers_target: false // lower BG target when autosens detects resistance
  19. , exercise_mode: false // when true, > 100 mg/dL high temp target adjusts sensitivityRatio for exercise_mode. This majorly changes the behavior of high temp targets from before. synonmym for high_temptarget_raises_sensitivity
  20. , half_basal_exercise_target: 160 // when temptarget is 160 mg/dL *and* exercise_mode=true, run 50% basal at this level (120 = 75%; 140 = 60%)
  21. // create maxCOB and default it to 120 because that's the most a typical body can absorb over 4 hours.
  22. // (If someone enters more carbs or stacks more; OpenAPS will just truncate dosing based on 120.
  23. // Essentially, this just limits AMA/SMB as a safety cap against excessive COB entry)
  24. , maxCOB: 120
  25. , skip_neutral_temps: false // if true, don't set neutral temps
  26. , unsuspend_if_no_temp: false // if true, pump will un-suspend after a zero temp finishes
  27. , min_5m_carbimpact: 8 // mg/dL per 5m (8 mg/dL/5m corresponds to 24g/hr at a CSF of 4 mg/dL/g (x/5*60/4))
  28. , autotune_isf_adjustmentFraction: 1.0 // keep autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.
  29. , remainingCarbsFraction: 1.0 // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
  30. , remainingCarbsCap: 90 // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
  31. // WARNING: use SMB with caution: it can and will automatically bolus up to max_iob worth of extra insulin
  32. , enableUAM: true // enable detection of unannounced meal carb absorption
  33. , A52_risk_enable: false
  34. , enableSMB_with_COB: true // enable supermicrobolus while COB is positive
  35. , enableSMB_with_temptarget: true // enable supermicrobolus for eating soon temp targets
  36. // *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with Libre or similar
  37. // LimiTTer, etc. do not properly filter out high-noise SGVs. xDrip+ builds greater than or equal to
  38. // version number d8e-7097-2018-01-22 provide proper noise values, so that oref0 can ignore high noise
  39. // readings, and can temporarily raise the BG target when sensor readings have medium noise,
  40. // resulting in appropriate SMB behaviour. Older versions of xDrip+ should not be used with enableSMB_always.
  41. // Using SMB overnight with such data sources risks causing a dangerous overdose of insulin
  42. // if the CGM sensor reads falsely high and doesn't come down as actual BG does
  43. , enableSMB_always: false // always enable supermicrobolus (unless disabled by high temptarget)
  44. , enableSMB_after_carbs: false // enable supermicrobolus for 6h after carbs, even with 0 COB
  45. // *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with Libre or similar.
  46. , allowSMB_with_high_temptarget: true // allow supermicrobolus (if otherwise enabled) even with high temp targets
  47. , maxSMBBasalMinutes: 90 // maximum minutes of basal that can be delivered as a single SMB with uncovered COB
  48. , maxUAMSMBBasalMinutes: 90 // maximum minutes of basal that can be delivered as a single SMB when IOB exceeds COB
  49. , SMBInterval: 3 // minimum interval between SMBs, in minutes.
  50. , bolus_increment: 0.05 // minimum bolus that can be delivered as an SMB
  51. , maxDelta_bg_threshold: 0.2 // maximum change in bg to use SMB, above that will disable SMB
  52. , curve: "rapid-acting" // change this to "ultra-rapid" for Fiasp, or "bilinear" for old curve
  53. , useCustomPeakTime: false // allows changing insulinPeakTime
  54. , insulinPeakTime: 45 // number of minutes after a bolus activity peaks. defaults to 55m for Fiasp if useCustomPeakTime: false
  55. , carbsReqThreshold: 1 // grams of carbsReq to trigger a pushover
  56. , offline_hotspot: false // enabled an offline-only local wifi hotspot if no Internet available
  57. , noisyCGMTargetMultiplier: 1.3 // increase target by this amount when looping off raw/noisy CGM data
  58. , suspend_zeros_iob: true // recognize pump suspends as non insulin delivery events
  59. // send the glucose data to the pump emulating an enlite sensor. This allows to setup high / low warnings when offline and see trend.
  60. // To enable this feature, enable the sensor, set a sensor with id 0000000, go to start sensor and press find lost sensor.
  61. , enableEnliteBgproxy: false
  62. // TODO: make maxRaw a preference here usable by oref0-raw in myopenaps-cgm-loop
  63. //, maxRaw: 200 // highest raw/noisy CGM value considered safe to use for looping
  64. , calc_glucose_noise: false
  65. , target_bg: false // set to an integer value in mg/dL to override pump min_bg
  66. // autoISF variables
  67. , smb_delivery_ratio: 0.5 //Default value: 0.5 Used if flexible delivery ratio is not used. This is another key OpenAPS safety cap, and specifies what share of the total insulin required can be delivered as SMB. This is to prevent people from getting into dangerous territory by setting SMB requests from the caregivers phone at the same time. Increase this experimental value slowly and with caution.
  68. , adjustmentFactor: 0.8
  69. , adjustmentFactorSigmoid: 0.5
  70. , useNewFormula: false
  71. , enableDynamicCR: false
  72. , sigmoid: false
  73. , weightPercentage: 0.65
  74. , tddAdjBasal: false // Enable adjustment of basal based on the ratio of 24 h : 10 day average TDD
  75. , enableSMB_high_bg: false // enable SMBs when a high BG is detected, based on the high BG target (adjusted or profile)
  76. , enableSMB_high_bg_target: 110 // set the value enableSMB_high_bg will compare against to enable SMB. If BG > than this value, SMBs should enable.
  77. , threshold_setting: 0.60 // Use a configurable threshold setting
  78. }
  79. }
  80. function displayedDefaults () {
  81. var allDefaults = defaults();
  82. var profile = { };
  83. profile.max_iob = allDefaults.max_iob;
  84. profile.max_daily_safety_multiplier = allDefaults.max_daily_safety_multiplier;
  85. profile.current_basal_safety_multiplier= allDefaults.current_basal_safety_multiplier;
  86. profile.autosens_max = allDefaults.autosens_max;
  87. profile.autosens_min = allDefaults.autosens_min;
  88. profile.rewind_resets_autosens = allDefaults.rewind_resets_autosens;
  89. profile.exercise_mode = allDefaults.exercise_mode;
  90. profile.sensitivity_raises_target = allDefaults.sensitivity_raises_target;
  91. profile.unsuspend_if_no_temp = allDefaults.unsuspend_if_no_temp;
  92. profile.enableSMB_with_COB = allDefaults.enableSMB_with_COB;
  93. profile.enableSMB_with_temptarget = allDefaults.enableSMB_with_temptarget;
  94. profile.enableUAM = allDefaults.enableUAM;
  95. profile.curve = allDefaults.curve;
  96. profile.offline_hotspot = allDefaults.offline_hotspot;
  97. profile.bolus_increment = allDefaults.bolus_increment;
  98. profile.smb_delivery_ratio = allDefaults.smb_delivery_ratio;
  99. profile.maxDelta_bg_threshold = allDefaults.maxDelta_bg_threshold;
  100. profile.adjustmentFactor = allDefaults.adjustmentFactor;
  101. profile.adjustmentFactorSigmoid = allDefaults.adjustmentFactorSigmoid;
  102. profile.useNewFormula = allDefaults.useNewFormula;
  103. profile.enableDynamicCR = allDefaults.enableDynamicCR;
  104. profile.sigmoid = allDefaults.sigmoid;
  105. profile.weightPercentage = allDefaults.weightPercentage;
  106. profile.tddAdjBasal = allDefaults.tddAdjBasal;
  107. profile.threshold_setting = allDefaults.threshold_setting;
  108. profile.enableSMB_high_bg = allDefaults.enableSMB_high_bg;
  109. profile.enableSMB_high_bg_target = allDefaults.enableSMB_high_bg_target;
  110. console.error(profile);
  111. return profile
  112. }
  113. function generate (inputs, opts) {
  114. var profile = opts && opts.type ? opts : defaults( );
  115. // check if inputs has overrides for any of the default prefs
  116. // and apply if applicable
  117. for (var pref in profile) {
  118. if (inputs.hasOwnProperty(pref)) {
  119. profile[pref] = inputs[pref];
  120. }
  121. }
  122. var pumpsettings_data = inputs.settings;
  123. if (inputs.settings.insulin_action_curve > 1) {
  124. profile.dia = pumpsettings_data.insulin_action_curve;
  125. } else {
  126. console.error('DIA of', profile.dia, 'is not supported');
  127. return -1;
  128. }
  129. if (inputs.model) {
  130. profile.model = inputs.model;
  131. }
  132. profile.skip_neutral_temps = inputs.skip_neutral_temps;
  133. profile.current_basal = basal.basalLookup(inputs.basals);
  134. profile.basalprofile = inputs.basals;
  135. _.forEach(profile.basalprofile, function(basalentry) {
  136. basalentry.rate = +(Math.round(basalentry.rate + "e+3") + "e-3");
  137. });
  138. profile.max_daily_basal = basal.maxDailyBasal(inputs);
  139. profile.max_basal = basal.maxBasalLookup(inputs);
  140. if (profile.current_basal === 0) {
  141. console.error("current_basal of",profile.current_basal,"is not supported");
  142. return -1;
  143. }
  144. if (profile.max_daily_basal === 0) {
  145. console.error("max_daily_basal of",profile.max_daily_basal,"is not supported");
  146. return -1;
  147. }
  148. if (profile.max_basal < 0.1) {
  149. console.error("max_basal of",profile.max_basal,"is not supported");
  150. return -1;
  151. }
  152. var range = targets.bgTargetsLookup(inputs, profile);
  153. profile.out_units = inputs.targets.user_preferred_units;
  154. profile.min_bg = Math.round(range.min_bg);
  155. profile.max_bg = Math.round(range.max_bg);
  156. profile.bg_targets = inputs.targets;
  157. _.forEach(profile.bg_targets.targets, function(bg_entry) {
  158. bg_entry.high = Math.round(bg_entry.high);
  159. bg_entry.low = Math.round(bg_entry.low);
  160. bg_entry.min_bg = Math.round(bg_entry.min_bg);
  161. bg_entry.max_bg = Math.round(bg_entry.max_bg);
  162. });
  163. delete profile.bg_targets.raw;
  164. profile.temptargetSet = range.temptargetSet;
  165. profile.sens = isf.isfLookup(inputs.isf);
  166. profile.isfProfile = inputs.isf;
  167. if (profile.sens < 5) {
  168. console.error("ISF of",profile.sens,"is not supported");
  169. return -1;
  170. }
  171. if (typeof(inputs.carbratio) !== "undefined") {
  172. profile.carb_ratio = carb_ratios.carbRatioLookup(inputs, profile);
  173. profile.carb_ratios = inputs.carbratio;
  174. } else {
  175. console.error("Profile wasn't given carb ratio data, cannot calculate carb_ratio");
  176. }
  177. return profile;
  178. }
  179. generate.defaults = defaults;
  180. generate.displayedDefaults = displayedDefaults;
  181. exports = module.exports = generate;