ZeroBasalScheduleTest.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. //
  2. // ZeroBasalScheduleTests.swift
  3. // OmniBLE
  4. //
  5. // Created by Joseph Moran on 03/19/2022.
  6. // Copyright © 2022 LoopKit Authors. All rights reserved.
  7. //
  8. import XCTest
  9. @testable import OmniBLE
  10. class ZeroBasalScheduleTests: XCTestCase {
  11. func checkBasalScheduleExtraCommandDataWithLessPrecision(_ data: Data, _ expected: Data, line: UInt = #line) {
  12. // The XXXXXXXX field is in thousands of a millisecond. Since we use TimeIntervals (floating point) for
  13. // recreating the offset, we can have small errors in reproducing the the encoded output, which we really
  14. // don't care about.
  15. func extractXXXXXXXX(_ data: Data) -> TimeInterval {
  16. return TimeInterval(Double(data[6...].toBigEndian(UInt32.self)) / 1000000.0)
  17. }
  18. let xxxxxxxx1 = extractXXXXXXXX(data)
  19. let xxxxxxxx2 = extractXXXXXXXX(expected)
  20. XCTAssertEqual(xxxxxxxx1, xxxxxxxx2, accuracy: 0.01, line: line)
  21. func blurXXXXXXXX(_ inStr: String) -> String {
  22. let start = inStr.index(inStr.startIndex, offsetBy:12)
  23. let end = inStr.index(start, offsetBy:8)
  24. return inStr.replacingCharacters(in: start..<end, with: "........")
  25. }
  26. print(blurXXXXXXXX(data.hexadecimalString))
  27. XCTAssertEqual(blurXXXXXXXX(data.hexadecimalString), blurXXXXXXXX(expected.hexadecimalString), line: line)
  28. }
  29. func testZeroOneZeroSegment() {
  30. let entries = [
  31. BasalScheduleEntry(rate: 1.00, startTime: .hours(0)),
  32. BasalScheduleEntry(rate: 0.00, startTime: .hours(0.5)),
  33. BasalScheduleEntry(rate: 1.00, startTime: .hours(1.0)),
  34. ]
  35. let schedule = BasalSchedule(entries: entries)
  36. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp napp
  37. // PDM: 1a 16 494e532e 00 029b 13 1698 0004 000a 0000 f00a f00a d00a
  38. let hh = 0x13
  39. let ssss = 0x1698
  40. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  41. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  42. XCTAssertEqual("1a16494e532e00029b1316980004000a0000f00af00ad00a", cmd1.data.hexadecimalString)
  43. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  44. // PDM: 13 1a 40 02 0b19 002dc6c0 0064 0112a880 0001 eb49d200 11f8 0112a880
  45. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  46. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "131a40020b19002dc6c000640112a8800001eb49d20011f80112a880")!, cmd2.data)
  47. }
  48. func testZeroMinBasal() {
  49. let entries = [
  50. BasalScheduleEntry(rate: 0.00, startTime: .hours(0)),
  51. BasalScheduleEntry(rate: 0.05, startTime: .hours(23)),
  52. ]
  53. let schedule = BasalSchedule(entries: entries)
  54. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp
  55. // PDM: 1a 14 494e532e 00 0097 28 3638 0000 f000 f000 e000 0001
  56. let hh = 0x28
  57. let ssss = 0x3638
  58. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  59. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  60. XCTAssertEqual("1a14494e532e0000972836380000f000f000e0000001", cmd1.data.hexadecimalString)
  61. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  62. // PDM: 13 14 40 00 0006 6769ffc0 002e eb49d200 000a 15752a00
  63. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  64. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "1314400000066769ffc0002eeb49d200000a15752a00")!, cmd2.data)
  65. }
  66. func testZeroSomeZeroBasal() {
  67. let entries = [
  68. BasalScheduleEntry(rate: 1.05, startTime: .hours(0)),
  69. BasalScheduleEntry(rate: 0.00, startTime: .hours(6)),
  70. BasalScheduleEntry(rate: 0.75, startTime: .hours(7.5)),
  71. BasalScheduleEntry(rate: 0.85, startTime: .hours(9)),
  72. BasalScheduleEntry(rate: 0.65, startTime: .hours(9.5)),
  73. BasalScheduleEntry(rate: 0.00, startTime: .hours(13.5)),
  74. BasalScheduleEntry(rate: 0.10, startTime: .hours(15.5)),
  75. BasalScheduleEntry(rate: 0.05, startTime: .hours(17)),
  76. BasalScheduleEntry(rate: 0.20, startTime: .hours(19.5)),
  77. BasalScheduleEntry(rate: 0.35, startTime: .hours(21)),
  78. BasalScheduleEntry(rate: 2.75, startTime: .hours(22.5)),
  79. ]
  80. let schedule = BasalSchedule(entries: entries)
  81. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp napp napp napp napp napp napp napp napp
  82. // PDM: 1a 24 494e532e 00 018e 28 1518 0000 b80a 2000 2807 0009 7806 3000 2001 4800 2002 0004 1803 281b
  83. let hh = 0x28
  84. let ssss = 0x1518
  85. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  86. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  87. XCTAssertEqual("1a24494e532e00018e2815180000b80a2000280700097806300020014800200200041803281b", cmd1.data.hexadecimalString)
  88. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  89. // PDM: 13 4a 40 08 001c 02aea540 04ec 01059449 0003 eb49d200 00e1 016e3600 0055 01432096 0208 01a68d13 0004 eb49d200 001e 0aba9500 0019 15752a00 003c 055d4a80 0069 0310bcdb 0339 0063e02e
  90. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  91. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "134a4008001c02aea54004ec010594490003eb49d20000e1016e3600005501432096020801a68d130004eb49d200001e0aba9500001915752a00003c055d4a8000690310bcdb03390063e02e")!, cmd2.data)
  92. }
  93. func testZeroBasalTest1() {
  94. let entries = [
  95. BasalScheduleEntry(rate: 0.00, startTime: .hours(0)),
  96. BasalScheduleEntry(rate: 0.05, startTime: .hours(1)),
  97. BasalScheduleEntry(rate: 0.00, startTime: .hours(2)),
  98. BasalScheduleEntry(rate: 0.15, startTime: .hours(3)),
  99. BasalScheduleEntry(rate: 0.00, startTime: .hours(5)),
  100. BasalScheduleEntry(rate: 0.20, startTime: .hours(7)),
  101. BasalScheduleEntry(rate: 0.00, startTime: .hours(9)),
  102. BasalScheduleEntry(rate: 0.25, startTime: .hours(11)),
  103. BasalScheduleEntry(rate: 0.00, startTime: .hours(14)),
  104. ]
  105. let schedule = BasalSchedule(entries: entries)
  106. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp napp napp napp napp napp napp
  107. // PDM: 1a 20 494e532e 00 0089 1b 1f30 0001 2000 0001 1000 3801 3000 3002 3000 5802 f000 3000
  108. let hh = 0x1b
  109. let ssss = 0x1f30
  110. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  111. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  112. XCTAssertEqual("1a20494e532e0000891b1f30000120000001100038013000300230005802f0003000", cmd1.data.hexadecimalString)
  113. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  114. // PDM: 13 3e 40 07 000e 03b20b80 0002 eb49d200 000a 15752a00 0002 eb49d200 003c 07270e00 0004 eb49d200 0050 055d4a80 0004 eb49d200 0096 044aa200 0014 eb49d200
  115. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  116. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "133e4007000e03b20b800002eb49d200000a15752a000002eb49d200003c07270e000004eb49d2000050055d4a800004eb49d2000096044aa2000014eb49d200")!, cmd2.data)
  117. }
  118. func testZeroBasalTest2() {
  119. let entries = [
  120. BasalScheduleEntry(rate: 0.00, startTime: .hours(0)),
  121. BasalScheduleEntry(rate: 0.05, startTime: .hours(1)),
  122. BasalScheduleEntry(rate: 0.00, startTime: .hours(2)),
  123. BasalScheduleEntry(rate: 0.15, startTime: .hours(3)),
  124. BasalScheduleEntry(rate: 0.25, startTime: .hours(7)),
  125. BasalScheduleEntry(rate: 0.00, startTime: .hours(9)),
  126. BasalScheduleEntry(rate: 0.25, startTime: .hours(11)),
  127. BasalScheduleEntry(rate: 0.00, startTime: .hours(14)),
  128. BasalScheduleEntry(rate: 0.30, startTime: .hours(17)),
  129. ]
  130. let schedule = BasalSchedule(entries: entries)
  131. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp napp napp napp napp napp
  132. // PDM: 1a 1e 494e532e 00 00ca 1b 1e40 0001 2000 0001 1000 7801 3802 3000 5802 5000 d003
  133. let hh = 0x1b
  134. let ssss = 0x1e40
  135. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  136. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  137. XCTAssertEqual("1a1e494e532e0000ca1b1e40000120000001100078013802300058025000d003", cmd1.data.hexadecimalString)
  138. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  139. // PDM: 13 3e 40 06 000e 01e84800 0002 eb49d200 000a 15752a00 0002 eb49d200 0078 07270e00 0064 044aa200 0004 eb49d200 0096 044aa200 0006 eb49d200 01a4 03938700
  140. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  141. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "133e4006000e01e848000002eb49d200000a15752a000002eb49d200007807270e000064044aa2000004eb49d2000096044aa2000006eb49d20001a403938700")!, cmd2.data)
  142. }
  143. func testZeroBasalTest4() {
  144. let entries = [
  145. BasalScheduleEntry(rate: 0.00, startTime: .hours(0)),
  146. BasalScheduleEntry(rate: 0.05, startTime: .hours(1)),
  147. BasalScheduleEntry(rate: 0.00, startTime: .hours(2)),
  148. BasalScheduleEntry(rate: 0.15, startTime: .hours(3)),
  149. BasalScheduleEntry(rate: 0.00, startTime: .hours(5)),
  150. BasalScheduleEntry(rate: 0.20, startTime: .hours(7)),
  151. BasalScheduleEntry(rate: 0.00, startTime: .hours(9)),
  152. BasalScheduleEntry(rate: 0.25, startTime: .hours(11)),
  153. BasalScheduleEntry(rate: 0.00, startTime: .hours(12)),
  154. ]
  155. let schedule = BasalSchedule(entries: entries)
  156. // 1a LL NNNNNNNN 00 CCCC HH SSSS PPPP napp napp napp napp napp napp napp napp napp napp
  157. // PDM: 1a 20 494e532e 00 00bc 1b 1d70 0000 2000 0001 1000 3801 3000 3002 3000 1802 f000 7000
  158. let hh = 0x1b
  159. let ssss = 0x1d70
  160. let offset = TimeInterval(minutes: Double((hh + 1) * 30)) - TimeInterval(seconds: Double(ssss / 8))
  161. let cmd1 = SetInsulinScheduleCommand(nonce: 0x494e532e, basalSchedule: schedule, scheduleOffset: offset)
  162. XCTAssertEqual("1a20494e532e0000bc1b1d70000020000001100038013000300230001802f0007000", cmd1.data.hexadecimalString)
  163. // 13 LL BO MM NNNN XXXXXXXX YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ YYYY ZZZZZZZZ
  164. // PDM: 13 3e 40 08 0015 3825c780 0002 eb49d200 000a 15752a00 0002 eb49d200 003c 07270e00 0004 eb49d200 0050 055d4a80 0004 eb49d200 0032 044aa200 0018 eb49d200
  165. let cmd2 = BasalScheduleExtraCommand(schedule: schedule, scheduleOffset: offset, acknowledgementBeep: false, completionBeep: true, programReminderInterval: 0)
  166. checkBasalScheduleExtraCommandDataWithLessPrecision(Data(hexadecimalString: "133e400800153825c7800002eb49d200000a15752a000002eb49d200003c07270e000004eb49d2000050055d4a800004eb49d2000032044aa2000018eb49d200")!, cmd2.data)
  167. }
  168. }