index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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: 0 // if max_iob is not provided, will default to zero
  9. , max_daily_safety_multiplier: 3
  10. , current_basal_safety_multiplier: 4
  11. , autosens_max: 1.2
  12. , autosens_min: 0.7
  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. , maxMealAbsorptionTime: 6 // Handling of long lasting effects of "heavy meals" containing large cqantities of fat and protein might be improved by letting the system consider meal effects for longer than the default six hours.
  26. , skip_neutral_temps: false // if true, don't set neutral temps
  27. , unsuspend_if_no_temp: false // if true, pump will un-suspend after a zero temp finishes
  28. , 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))
  29. , 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.
  30. , remainingCarbsFraction: 1.0 // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
  31. , remainingCarbsCap: 90 // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
  32. // WARNING: use SMB with caution: it can and will automatically bolus up to max_iob worth of extra insulin
  33. , enableUAM: false // enable detection of unannounced meal carb absorption
  34. , A52_risk_enable: false
  35. , enableSMB_with_COB: false // enable supermicrobolus while COB is positive
  36. , enableSMB_with_temptarget: false // enable supermicrobolus for eating soon temp targets
  37. // *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with Libre or similar
  38. // LimiTTer, etc. do not properly filter out high-noise SGVs. xDrip+ builds greater than or equal to
  39. // version number d8e-7097-2018-01-22 provide proper noise values, so that oref0 can ignore high noise
  40. // readings, and can temporarily raise the BG target when sensor readings have medium noise,
  41. // resulting in appropriate SMB behaviour. Older versions of xDrip+ should not be used with enableSMB_always.
  42. // Using SMB overnight with such data sources risks causing a dangerous overdose of insulin
  43. // if the CGM sensor reads falsely high and doesn't come down as actual BG does
  44. , enableSMB_always: false // always enable supermicrobolus (unless disabled by high temptarget)
  45. , enableSMB_after_carbs: false // enable supermicrobolus for 6h after carbs, even with 0 COB
  46. , enableSMB_high_bg: false // enable SMBs when a high BG is detected, based on the high BG target (adjusted or profile)
  47. , 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.
  48. // *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with Libre or similar.
  49. , allowSMB_with_high_temptarget: false // allow supermicrobolus (if otherwise enabled) even with high temp targets
  50. , maxSMBBasalMinutes: 30 // maximum minutes of basal that can be delivered as a single SMB with uncovered COB
  51. , maxUAMSMBBasalMinutes: 30 // maximum minutes of basal that can be delivered as a single SMB when IOB exceeds COB
  52. , SMBInterval: 3 // minimum interval between SMBs, in minutes.
  53. , bolus_increment: 0.1 // minimum bolus that can be delivered as an SMB
  54. , maxDelta_bg_threshold: 0.2 // maximum change in bg to use SMB, above that will disable SMB
  55. , curve: "rapid-acting" // change this to "ultra-rapid" for Fiasp, or "bilinear" for old curve
  56. , useCustomPeakTime: false // allows changing insulinPeakTime
  57. , insulinPeakTime: 75 // number of minutes after a bolus activity peaks. defaults to 55m for Fiasp if useCustomPeakTime: false
  58. , carbsReqThreshold: 1 // grams of carbsReq to trigger a pushover
  59. , offline_hotspot: false // enabled an offline-only local wifi hotspot if no Internet available
  60. , noisyCGMTargetMultiplier: 1.3 // increase target by this amount when looping off raw/noisy CGM data
  61. , suspend_zeros_iob: true // recognize pump suspends as non insulin delivery events
  62. // send the glucose data to the pump emulating an enlite sensor. This allows to setup high / low warnings when offline and see trend.
  63. // To enable this feature, enable the sensor, set a sensor with id 0000000, go to start sensor and press find lost sensor.
  64. , enableEnliteBgproxy: false
  65. // TODO: make maxRaw a preference here usable by oref0-raw in myopenaps-cgm-loop
  66. //, maxRaw: 200 // highest raw/noisy CGM value considered safe to use for looping
  67. , calc_glucose_noise: false
  68. , target_bg: false // set to an integer value in mg/dL to override pump min_bg
  69. , 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.
  70. , adjustmentFactor: 0.8
  71. , adjustmentFactorSigmoid: 0.5
  72. , useNewFormula: false
  73. , enableDynamicCR: false
  74. , sigmoid: false
  75. , weightPercentage: 0.65
  76. , tddAdjBasal: false // Enable adjustment of basal based on the ratio of 24 h : 10 day average TDD
  77. , threshold_setting: 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. profile.maxCOB = allDefaults.maxCOB;
  111. profile.maxMealAbsorptionTime = allDefaults.maxMealAbsorptionTime;
  112. console.error(profile);
  113. return profile
  114. }
  115. function generate (inputs, opts) {
  116. var profile = opts && opts.type ? opts : defaults( );
  117. // check if inputs has overrides for any of the default prefs
  118. // and apply if applicable
  119. for (var pref in profile) {
  120. if (inputs.hasOwnProperty(pref)) {
  121. profile[pref] = inputs[pref];
  122. }
  123. }
  124. var pumpsettings_data = inputs.settings;
  125. if (inputs.settings.insulin_action_curve > 1) {
  126. profile.dia = pumpsettings_data.insulin_action_curve;
  127. } else {
  128. console.error('DIA of', profile.dia, 'is not supported');
  129. return -1;
  130. }
  131. if (inputs.model) {
  132. profile.model = inputs.model;
  133. }
  134. profile.skip_neutral_temps = inputs.skip_neutral_temps;
  135. profile.current_basal = basal.basalLookup(inputs.basals);
  136. profile.basalprofile = inputs.basals;
  137. _.forEach(profile.basalprofile, function(basalentry) {
  138. basalentry.rate = +(Math.round(basalentry.rate + "e+3") + "e-3");
  139. });
  140. profile.max_daily_basal = basal.maxDailyBasal(inputs);
  141. profile.max_basal = basal.maxBasalLookup(inputs);
  142. if (profile.current_basal === 0) {
  143. console.error("current_basal of",profile.current_basal,"is not supported");
  144. return -1;
  145. }
  146. if (profile.max_daily_basal === 0) {
  147. console.error("max_daily_basal of",profile.max_daily_basal,"is not supported");
  148. return -1;
  149. }
  150. if (profile.max_basal < 0.1) {
  151. console.error("max_basal of",profile.max_basal,"is not supported");
  152. return -1;
  153. }
  154. var range = targets.bgTargetsLookup(inputs, profile);
  155. profile.out_units = inputs.targets.user_preferred_units;
  156. profile.min_bg = Math.round(range.min_bg);
  157. profile.max_bg = Math.round(range.max_bg);
  158. profile.bg_targets = inputs.targets;
  159. _.forEach(profile.bg_targets.targets, function(bg_entry) {
  160. bg_entry.high = Math.round(bg_entry.high);
  161. bg_entry.low = Math.round(bg_entry.low);
  162. bg_entry.min_bg = Math.round(bg_entry.min_bg);
  163. bg_entry.max_bg = Math.round(bg_entry.max_bg);
  164. });
  165. delete profile.bg_targets.raw;
  166. profile.temptargetSet = range.temptargetSet;
  167. profile.sens = isf.isfLookup(inputs.isf);
  168. profile.isfProfile = inputs.isf;
  169. if (profile.sens < 5) {
  170. console.error("ISF of",profile.sens,"is not supported");
  171. return -1;
  172. }
  173. if (typeof(inputs.carbratio) !== "undefined") {
  174. profile.carb_ratio = carb_ratios.carbRatioLookup(inputs, profile);
  175. profile.carb_ratios = inputs.carbratio;
  176. } else {
  177. console.error("Profile wasn't given carb ratio data, cannot calculate carb_ratio");
  178. }
  179. return profile;
  180. }
  181. generate.defaults = defaults;
  182. generate.displayedDefaults = displayedDefaults;
  183. exports = module.exports = generate;