Guest User

Untitled

a guest
Oct 20th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.54 KB | None | 0 0
  1. package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import org.joda.time.Instant;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9.  
  10. import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
  11.  
  12. /**
  13. * Created by geoff on 6/1/15.
  14. * <p>
  15. * There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to
  16. * choose from: Standard, A, and B
  17. * <p>
  18. * The byte array seems to be 21 three byte entries long, plus a zero? If the profile is completely empty, it should
  19. * have one entry: [0,0,0x3F] (?) The first entry of [0,0,0] marks the end of the used entries.
  20. * <p>
  21. * Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if
  22. * there are no more entries.
  23. * <p>
  24. * Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start
  25. * time-of-day for the basal rate period (in 30 minute increments?)
  26. */
  27. public class BasalProfile {
  28.  
  29. public static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1;
  30. // private static final String TAG = "BasalProfile";
  31. private static final Logger LOG = LoggerFactory.getLogger(BasalProfile.class);
  32. private static final boolean DEBUG_BASALPROFILE = false;
  33. protected byte[] mRawData; // store as byte array to make transport (via parcel) easier
  34. List<BasalProfileEntry> listEntries;
  35.  
  36.  
  37. public BasalProfile() {
  38. init();
  39. }
  40.  
  41.  
  42. public BasalProfile(byte[] data) {
  43. setRawData(data);
  44. }
  45.  
  46.  
  47. // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class.
  48. protected static int readUnsignedByte(byte b) {
  49. return (b < 0) ? b + 256 : b;
  50. }
  51.  
  52.  
  53. public void init() {
  54. mRawData = new byte[MAX_RAW_DATA_SIZE];
  55. mRawData[0] = 0;
  56. mRawData[1] = 0;
  57. mRawData[2] = 0x3f;
  58. }
  59.  
  60.  
  61. public boolean setRawData(byte[] data) {
  62. if (data == null) {
  63. LOG.error("setRawData: buffer is null!");
  64. return false;
  65. }
  66.  
  67. if (data.length == 1) {
  68. data = MedtronicUtil.createByteArray(data[0], (byte)0, (byte)0);
  69. }
  70.  
  71. // int len = Math.min(MAX_RAW_DATA_SIZE, data.length);
  72. mRawData = data;
  73. // System.arraycopy(data, 0, mRawData, 0, len);
  74. if (DEBUG_BASALPROFILE) {
  75. LOG.debug(String.format("setRawData: copied raw data buffer of %d bytes.", data.length));
  76. }
  77. return true;
  78. }
  79.  
  80.  
  81. public void dumpBasalProfile() {
  82. LOG.debug("Basal Profile entries:");
  83. List<BasalProfileEntry> entries = getEntries();
  84. for (int i = 0; i < entries.size(); i++) {
  85. BasalProfileEntry entry = entries.get(i);
  86. String startString = entry.startTime.toString("HH:mm");
  87. // this doesn't work
  88. LOG.debug(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", i + 1, entry.rate,
  89. entry.rate_raw, startString, entry.startTime_raw));
  90.  
  91. }
  92. }
  93.  
  94.  
  95. public String getBasalProfileAsString() {
  96. StringBuffer sb = new StringBuffer("Basal Profile entries:\n");
  97. List<BasalProfileEntry> entries = getEntries();
  98. for (int i = 0; i < entries.size(); i++) {
  99. BasalProfileEntry entry = entries.get(i);
  100. String startString = entry.startTime.toString("HH:mm");
  101.  
  102. sb.append(String.format("Entry %d, rate=%.3f, start=%s\n", i + 1, entry.rate, startString));
  103. }
  104.  
  105. return sb.toString();
  106. }
  107.  
  108.  
  109. // TODO: this function must be expanded to include changes in which profile is in use.
  110. // and changes to the profiles themselves.
  111. public BasalProfileEntry getEntryForTime(Instant when) {
  112. BasalProfileEntry rval = new BasalProfileEntry();
  113. List<BasalProfileEntry> entries = getEntries();
  114. if (entries.size() == 0) {
  115. LOG.warn(String.format("getEntryForTime(%s): table is empty",
  116. when.toDateTime().toLocalTime().toString("HH:mm")));
  117. return rval;
  118. }
  119. // Log.w(TAG,"Assuming first entry");
  120. rval = entries.get(0);
  121. if (entries.size() == 1) {
  122. LOG.debug("getEntryForTime: Only one entry in profile");
  123. return rval;
  124. }
  125.  
  126. int localMillis = when.toDateTime().toLocalTime().getMillisOfDay();
  127. boolean done = false;
  128. int i = 1;
  129. while (!done) {
  130. BasalProfileEntry entry = entries.get(i);
  131. if (DEBUG_BASALPROFILE) {
  132. LOG.debug(String.format("Comparing 'now'=%s to entry 'start time'=%s", when.toDateTime().toLocalTime()
  133. .toString("HH:mm"), entry.startTime.toString("HH:mm")));
  134. }
  135. if (localMillis >= entry.startTime.getMillisOfDay()) {
  136. rval = entry;
  137. if (DEBUG_BASALPROFILE)
  138. LOG.debug("Accepted Entry");
  139. } else {
  140. // entry at i has later start time, keep older entry
  141. if (DEBUG_BASALPROFILE)
  142. LOG.debug("Rejected Entry");
  143. done = true;
  144. }
  145. i++;
  146. if (i >= entries.size()) {
  147. done = true;
  148. }
  149. }
  150. if (DEBUG_BASALPROFILE) {
  151. LOG.debug(String.format("getEntryForTime(%s): Returning entry: rate=%.3f (%d), start=%s (%d)", when
  152. .toDateTime().toLocalTime().toString("HH:mm"), rval.rate, rval.rate_raw,
  153. rval.startTime.toString("HH:mm"), rval.startTime_raw));
  154. }
  155. return rval;
  156. }
  157.  
  158.  
  159. public List<BasalProfileEntry> getEntries() {
  160. List<BasalProfileEntry> entries = new ArrayList<>();
  161.  
  162. if (mRawData == null || mRawData[2] == 0x3f) {
  163. LOG.warn("Raw Data is empty.");
  164. return entries; // an empty list
  165. }
  166. boolean done = false;
  167. int r, st;
  168.  
  169. for (int i = 0; i < mRawData.length - 2; i += 3) {
  170.  
  171. if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0))
  172. break;
  173.  
  174. r = MedtronicUtil.makeUnsignedShort(mRawData[i + 1], mRawData[i]); // readUnsignedByte(mRawData[i]);
  175. st = readUnsignedByte(mRawData[i + 2]);
  176. entries.add(new BasalProfileEntry(r, st));
  177. }
  178.  
  179. return entries;
  180. }
  181.  
  182.  
  183. /**
  184. * This is used to prepare new profile
  185. *
  186. * @param entry
  187. */
  188. public void addEntry(BasalProfileEntry entry) {
  189. if (listEntries == null)
  190. listEntries = new ArrayList<>();
  191.  
  192. listEntries.add(entry);
  193. }
  194.  
  195.  
  196. public byte[] generateRawData() {
  197.  
  198. List<Byte> outData = new ArrayList<>();
  199.  
  200. for (BasalProfileEntry profileEntry : listEntries) {
  201.  
  202. byte[] strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true);
  203.  
  204. outData.add(profileEntry.rate_raw[0]);
  205. outData.add(profileEntry.rate_raw[1]);
  206. outData.add(profileEntry.startTime_raw);
  207. }
  208.  
  209. this.setRawData(MedtronicUtil.createByteArray(outData));
  210.  
  211. return this.mRawData;
  212. }
  213.  
  214.  
  215. // TODO extend to be done by half hour
  216. public Double[] getProfilesByHour() {
  217.  
  218. List<BasalProfileEntry> entries = getEntries();
  219.  
  220. if (entries.size() == 0) {
  221. return null;
  222. }
  223.  
  224. Double[] basalByHour = new Double[24];
  225.  
  226. for (int i = 0; i < entries.size(); i++) {
  227. BasalProfileEntry current = entries.get(i);
  228.  
  229. int currentTime = (current.startTime_raw % 2 == 0) ? current.startTime_raw : current.startTime_raw - 1;
  230.  
  231. currentTime = (currentTime * 30) / 60;
  232.  
  233. int lastHour = 0;
  234. if ((i + 1) == entries.size()) {
  235. lastHour = 24;
  236. } else {
  237. BasalProfileEntry basalProfileEntry = entries.get(i + 1);
  238.  
  239. int rawTime = (basalProfileEntry.startTime_raw % 2 == 0) ? basalProfileEntry.startTime_raw
  240. : basalProfileEntry.startTime_raw - 1;
  241.  
  242. lastHour = (rawTime * 30) / 60;
  243. }
  244.  
  245. // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour);
  246.  
  247. for (int j = currentTime; j < lastHour; j++) {
  248. basalByHour[j] = current.rate;
  249. }
  250. }
  251.  
  252. // StringBuilder sb = new StringBuilder();
  253. //
  254. // for (int i = 0; i < 24; i++) {
  255. // sb.append("" + i + "=" + basalByHour[i]);
  256. // sb.append("\n");
  257. // }
  258. //
  259. // System.out.println("Basal Profile: \n" + sb.toString());
  260.  
  261. return basalByHour;
  262. }
  263.  
  264.  
  265. public byte[] getRawData() {
  266. return this.mRawData;
  267. }
  268. }
Add Comment
Please, Sign In to add comment