Skip to content

Commit

Permalink
Add little-endian insulin decoding for basal rate schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
ecc1 committed Jun 19, 2018
1 parent 25796d8 commit e7b965b
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 5 deletions.
5 changes: 2 additions & 3 deletions basal.go
Expand Up @@ -16,14 +16,13 @@ type BasalRateSchedule []BasalRate
func decodeBasalRateSchedule(data []byte) BasalRateSchedule {
var sched []BasalRate
for i := 0; i < len(data)-2; i += 3 {
r := data[i]
rate := twoByteInsulinLE(data[i : i+2])
t := data[i+2]
// Don't stop if the 00:00 rate happens to be zero.
if i > 1 && r == 0 && t == 0 {
if i > 1 && rate == 0 && t == 0 {
break
}
start := halfHoursToTimeOfDay(t)
rate := byteToInsulin(r, 23)
sched = append(sched, BasalRate{Start: start, Rate: rate})
}
return sched
Expand Down
8 changes: 8 additions & 0 deletions basal_test.go
Expand Up @@ -66,6 +66,14 @@ func TestBasalRates(t *testing.T) {
{parseTD("23:00"), 2300},
},
},
{
[]byte{0x28, 0x00, 0x00, 0x40, 0x01, 0x08, 0x28, 0x00, 0x2C, 0x00, 0x00, 0x00},
BasalRateSchedule{
{parseTD("00:00"), 1000},
{parseTD("04:00"), 8000},
{parseTD("22:00"), 1000},
},
},
}
for _, c := range cases {
s := decodeBasalRateSchedule(c.data)
Expand Down
3 changes: 1 addition & 2 deletions historyrecord.go
Expand Up @@ -382,8 +382,7 @@ func decodeDailyTotal(data []byte, family Family) HistoryRecord {
func decodeBasalRate(data []byte) BasalRate {
return BasalRate{
Start: halfHoursToTimeOfDay(data[0]),
Rate: byteToInsulin(data[1], 23),
// data[2] unused
Rate: twoByteInsulinLE(data[1:3]),
}
}

Expand Down
19 changes: 19 additions & 0 deletions testdata/records-522.json
Expand Up @@ -522,5 +522,24 @@
"Time": "2017-06-24T14:01:44-04:00",
"Data": "CABsgS4YET8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"Info": null
},
{
"Type": "BasalProfileAfter",
"Time": "2018-06-16T19:58:18-04:00",
"Data": "CQNSuhMQEgAoAAhAASwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"Info": [
{
"Start": "00:00",
"Rate": 1
},
{
"Start": "04:00",
"Rate": 8
},
{
"Start": "22:00",
"Rate": 1
}
]
}
]
4 changes: 4 additions & 0 deletions units.go
Expand Up @@ -110,3 +110,7 @@ func byteToInsulin(strokes uint8, family Family) Insulin {
func twoByteInsulin(data []byte, family Family) Insulin {
return intToInsulin(twoByteInt(data), family)
}

func twoByteInsulinLE(data []byte) Insulin {
return intToInsulin(twoByteIntLE(data), 23)
}
12 changes: 12 additions & 0 deletions unmarshal.go
Expand Up @@ -4,10 +4,18 @@ func twoByteUint(data []byte) uint16 {
return uint16(data[0])<<8 | uint16(data[1])
}

func twoByteUintLE(data []byte) uint16 {
return uint16(data[1])<<8 | uint16(data[0])
}

func twoByteInt(data []byte) int {
return int(int16(twoByteUint(data)))
}

func twoByteIntLE(data []byte) int {
return int(int16(twoByteUintLE(data)))
}

func fourByteUint(data []byte) uint32 {
return uint32(twoByteUint(data[0:2]))<<16 | uint32(twoByteUint(data[2:4]))
}
Expand All @@ -21,6 +29,10 @@ func marshalUint16(n uint16) []byte {
return []byte{byte(n >> 8), byte(n & 0xFF)}
}

func marshalUint16LE(n uint16) []byte {
return []byte{byte(n & 0xFF), byte(n >> 8)}
}

func marshalUint32(n uint32) []byte {
return append(marshalUint16(uint16(n>>16)), marshalUint16(uint16(n))...)
}
42 changes: 42 additions & 0 deletions unmarshal_test.go
Expand Up @@ -27,6 +27,27 @@ func TestTwoByteUint(t *testing.T) {
}
}

func TestTwoByteUintLE(t *testing.T) {
cases := []struct {
val uint16
rep []byte
}{
{0x1234, []byte{0x34, 0x12}},
{0, []byte{0x00, 0x00}},
{math.MaxUint16, []byte{0xFF, 0xFF}},
}
for _, c := range cases {
val := twoByteUintLE(c.rep)
if val != c.val {
t.Errorf("twoByteUintLE(% X) == %04X, want %04X", c.rep, val, c.val)
}
rep := marshalUint16LE(c.val)
if !bytes.Equal(rep, c.rep) {
t.Errorf("marshalUint16LE(%04X) == % X, want % X", c.val, rep, c.rep)
}
}
}

func TestTwoByteInt(t *testing.T) {
cases := []struct {
val int
Expand All @@ -48,6 +69,27 @@ func TestTwoByteInt(t *testing.T) {
}
}

func TestTwoByteIntLE(t *testing.T) {
cases := []struct {
val int
rep []byte
}{
{0x1234, []byte{0x34, 0x12}},
{0, []byte{0x00, 0x00}},
{256, []byte{0x00, 0x01}},
{-1, []byte{0xFF, 0xFF}},
{-256, []byte{0x00, 0xFF}},
{math.MaxInt16, []byte{0xFF, 0x7F}},
{math.MinInt16, []byte{0x00, 0x80}},
}
for _, c := range cases {
val := twoByteIntLE(c.rep)
if val != c.val {
t.Errorf("twoByteIntLE(% X) == %d, want %d", c.rep, val, c.val)
}
}
}

func TestFourByteUint(t *testing.T) {
cases := []struct {
val uint32
Expand Down

0 comments on commit e7b965b

Please sign in to comment.