pazaan / 600SeriesAndroidUploader

Your Medtronic 600-series pump data, direct to Nightscout
http://pazaan.github.io/600SeriesAndroidUploader/
MIT License
189 stars 314 forks source link

pumpstatusresponse - LastBolusAmount #145

Open cfaagaard opened 6 years ago

cfaagaard commented 6 years ago

Found another byte....

BolusEstimate at my index 13 ( at yours index 16, I think). Its a int32 and the raw value is ex. 105000 and should be divide with 10000 = 10,5. It looks like it is changed every time the bolus wizard has been used.

Pogman commented 6 years ago

This location has the last bolus delivered. There is also a last bolus delivered time and reference number that go with this. I have a sheet of findings that you might find useful:

Pogman commented 6 years ago
----------------------------------------------------------

Status Message Payload

           ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?A ?B ?C ?D ?E ?F
0x00000000 XX XX XX QQ nb NB NB NB -- -- -- -- NM NM NR nr
0x00000010 kb KB KB KB KT KT KT KT KR kr BP BR BR BR BR tb
0x00000020 TB TB TB TR TM TM bu BU BU BU PP rr RR RR RR RH
0x00000030 RM ii II II II SV SV ST ST ST ST SO SO SO SO LS
0x00000040 SA SS SU SC SC SB SX SX BW BG BG WW WW WT WT WT
0x00000050 WT WO WO WO WO -- -- -- sm sm SM SM sn sn SN SN

XX = header

QQ = pump status
BP = basal pattern
BR = basal rate (div 10000)
TB = temp basal (div 10000)
TR = temp basal percent
TM = temp minutes remaining
BU = basal units delivered today (div 10000)
PP = battery
RR = reservoir (div 10000)
RH = reservoir hours remaining
RM = reservoir mins remaining
II = active insulin (div 10000)
SV = sgv
ST = sgv time rtc
SO = sgv time offset
LS = low suspend active
SA = sgv trend
BW = bolus wizard
BG = bgv
WW = alert
WT = alert time rtc
WO = alert time offset

NB = now bolusing amount delivered (div 10000)
NM = now bolusing minutes remaining
NR = now bolusing reference

KB = last bolus amount (div 10000)
KT = last bolus time
KR = last bolus reference

SS = sensor status
SU = sensor control?
SC = sensor calibration minutes remaining
SB = sensor battery
SX = sensor rate of change (div 100)

SM = sensor mode count? (incs each sensor on and each off and at other unspecified times/events)
SN = sensor mode count? (incs each sensor on and each off and at other unspecified times/events)

-- = unknown use or zero while monitoring

lower case used for unconfirmed but assumed related values ie: rr RR RR RR (is it 24bit or 32bit) 

----------------------------------------------------------

[QQ] 8bit  = pump status

00000001 = suspended
00000010 = now bolusing normal
00000100 = now bolusing square
00001000 = now bolusing dual
00010000 = insulin delivery active
00100000 = temp basal active
01000000 = cgm active
10000000 = ?

----101- = seen during resv change? prime?

----------------------------------------------------------

Last bolus delivered:

[KB] 32bit = last bolus amount (/10000 for decimal value)
[KT] 32bit = last bolus time
[KR] 8bit  = bolus reference (inc each bolus)
[kr] 8bit  = unconfirmed part of reference? seen as zero while monitoring

Now bolusing:

[NB] 32bit = bolusing amount delivered (normal/square/dual check pump status for type) (/10000 for decimal value)
[NM] 16bit = bolusing minutes remaining (user set limit = 480 minutes / 8 hours)
[NR] 8bit  = bolusing = bolus reference, [KR] will contain this ref when complete normal/square
[nr] 8bit  = unconfirmed part of reference? seen as zero while monitoring

<normal> when bolusing finished updates: [KB] with full bolus amount [KT] time normal bolusing started 
<square> when square bolusing finished updates: [KB] with square bolus amount [KT] time square bolusing started
<dual>   when normal bolusing finished updates: [KB] with normal bolus amount [KT] time normal bolusing started [KR] = [NR]
         when square bolusing finished updates: [KB] with square bolus amount [KT] time square bolusing started [KR] = [NR] (same ref used for both parts)

if an additional normal bolus is done while a square is being delivered [KB] [KT] [KR] will show this bolus and change again to square when that finishes. 

----------------------------------------------------------

Sensor/Transmitter:

[SS] 8bit  = sensor status

00000001 = calibrating
00000010 = calibration complete
00000100 = notice (bad isig / no sgv / warmup / large rate of change)
00001000 = ?
00010000 = ?
00100000 = ?
01000000 = ?
10000000 = ?

[SU] 8bit  = ?
[SC] 16bit = time remaining to next calibration in minutes (720 mins max count, FFFF = unknown)
[SB] 8bit  = transmitter battery (0x3F=100% 0x2B=73% 0x27=47% 0x23=23% ...)
[SX] 16bit = isig rate of change? relates to use for trend arrows? (/100 for decimal value) (RATE_OF_CHANGE value in Carelink)

sensor warm-up noted:
[SS] = 04
[SU] = 02 / 01 / 00 changes during warm-up
[SC] = next cal in minutes ie 120 mins for warm-up
[SB] = 3F
[SX] = 0
[SV] = 0301

overdue calibration:
[SS] = 04
[SC] = 0

[sm] 16bit = unconfirmed part of [SM]? seen as zero while monitoring
[SM] 16bit = sensor mode count? (incs each sensor on and each off and at other unspecified times/events)
[sn] 16bit = unconfirmed part of [SN]? seen as zero while monitoring
[SN] 16bit = sensor mode count? (incs each sensor on and each off and at other unspecified times/events)

[SM] and [SN] always mirror each other

----------------------------------------------------------
cfaagaard commented 6 years ago

This is great, @Pogman !! Thank you. There are some numbers here that I have been looking for;
SC = sensor calibration minutes remaining (this is going be sent a task into my wunderlist, as my kid sometimes forgets to calibrate) So this just made my day.

II = active insulin (div 10000) : I have this as a int16 and then I have "BolusEstModifiedByUser" (byte) just before.

cfaagaard commented 6 years ago

and you are right about the naming of the "BolusEstimate"; it is better to call it "LastBolusAmount". I have just changed the heading on this issue.

cfaagaard commented 6 years ago

@Pogman ; I am starting looking into the history-statusmessages in order to get "old" status. Do you know of any information like the one you provided about the statusresponse?

Pogman commented 6 years ago

II = active insulin (IOB) This may be 24bit then as 16bit would be to small. Can you confirm for sure that this byte is "BolusEstModifiedByUser"? It also makes me question all of the 4 byte values that have been proposed that hold insulin values - they just fit so neatly into 4 byte slots! but 3 bytes is plenty to hold the info needed.

I've not done anything yet with the history. Lennart or Volker may know more.

pazaan commented 6 years ago

I have documented quite a lot of the message structure at https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/docs/packetStructure.md (SVGs at https://github.com/tidepool-org/chrome-uploader/tree/pazaan/electron-medtronic600/lib/drivers/medtronic600/docs/images/svg).

I haven't documented the History message yet, but the JavaScript code for how to read it is available at https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/NGPHistoryParser.js

I'll be updating the documentation with the findings in this thread.

pazaan commented 6 years ago

I also have a bunch of notes from my initial reverse engineering efforts at https://github.com/pazaan/decoding-contour-next-link/blob/master/Random%20Protocol%20Notes.txt

cfaagaard commented 6 years ago

@Pogman , I can confirm it is NOT BolusEstModifiedByUser. Sorry for the "misinformation". I have closed the other issue. But something else is going on in those bytes.... I will leave it alone for now and look into the history. And then maybe it is easier to join and compare the datasets from carelink and the pump-readings. Thanks a lot @pazaan, it looks very interesting. Aaaahhhh, compressed, not encrypted.... Jesus, how did you figure that one out.

cfaagaard commented 6 years ago

@Pogman , but you can have the "II = active insulin" as two bytes if you "ActiveInsulinRaw & 0x0000ffff", except when the byte I thought was "BolusEstModifiedByUser" equals 1.... then you also have to "(ActiveInsulinRaw & 0x0000ffff) + 0x0000ffff". But as I said I am leaving this for now and looking into the history. And then maybe I will find the answer in the history-messages. I'll be back.

Pogman commented 6 years ago

If you mask it to 2 bytes it would only hold a max of 6 units of active insulin as it's a div 10000 decimal value. As 3 bytes it can hold 1677 units. I suppose for safety you could mask it as 00FFFFFF and that would cover any doubt with the last byte.

volkerrichert commented 6 years ago

i started to port the history messages from S to java but get lost

cfaagaard commented 6 years ago

@volkerrichert : this S-code. Is it on github somewhere? Thanks.

pazaan commented 6 years ago

I think the "S" is missing a "J" - It's JavaScript code 😉

https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/medtronic600Driver.js

Keep in mind that I'm currently refactoring it (it turns out that any message can have a "Multipacket Transfer"). See also https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/NGPHistoryParser.js

cfaagaard commented 6 years ago

Thanks, pazaan. I have studying that code pretty hard :-) (thanks again, I have no idea how you find all the "patterns" in those bytes. Pretty impressive). I am almost done porting that code to c#. Done with the request/response part. But my decompres-size do not match the uncompres-size that you extract from the payload and then some times my decompressing-code fails...... Testing with different from/to-dates at the moment. If I find something do want a note here (in this issue) or at the tidepool project.

pazaan commented 6 years ago

Ah, you must specify the buffer size. If you let LZO "guess", it will get it wrong.

cfaagaard commented 6 years ago

I am in the process of doing this. But I can see that the historySizeCompressed is not matching the actual size of the payload. And I thought these numbers should match before giving it to the lzo. Should I do this? Or should I just give it "historySizeCompressed" no matter of the actual size. https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/medtronic600Driver.js#L1273

cfaagaard commented 6 years ago

stupid question on my side. Sorry. Ignore. I will keep debugging it. :-)

cfaagaard commented 6 years ago

Found the error. Now all the numbers are correct and I feed lzo with historySizeUncompressed and it extracts all the events. HURRRRAAAA!!!! Thank you so much!

(I have commited my code to github if you are interested)

pazaan commented 6 years ago

Congrats! Well done! Don't feel bad - it took me two days to figure this bug out :p

cfaagaard commented 6 years ago

Thanks. Well it is pretty easy when I just have to look at your code.

cfaagaard commented 6 years ago

@pazaan : In the weekend I have tested different settings for the history-events-read-proces. So right now I read 24 hours back every 5 minutes.... stress testing.... and generating entries/treatments for NS entirely from the history-data. It takes about 10-15 seconds extra to get that much data out.

I got me thinking. The tidepool-project; is it possible to upload data to tidepool, but not using the chrome-uploader? I can not find any info about a rest API or something like that. I want the raspberry pi to upload data to tidepool automatically every day.

pazaan commented 6 years ago

Yes, it is possible. DM me on Gitter for more info.

Pogman commented 6 years ago

@pazaan hey - being looking at history for the uploader and multipacket transfer and just noticed that you said that any message can have a "Multipacket Transfer".

I was wondering about this as I had noticed some rare behaviour in some pump responses and have just been cancelling out the comms to avoid crashing the CNL. Perhaps I should have some checking for this sort of behaviour and accounted for in all pump responses? Any thoughts on this?

pazaan commented 6 years ago

@Pogman - yes, any NGP Message can have a Multipacket Transfer once the payload gets over a certain size. For example, a basal schedule message for a basal schedule that has a different basal pattern for every hour will trigger a Multipacket Transfer.

See https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/medtronic600Driver.js#L761-L950 and https://github.com/tidepool-org/chrome-uploader/blob/pazaan/electron-medtronic600/lib/drivers/medtronic600/medtronic600Driver.js#L678-L759

It would make sense for us to account for it as well - and we'll need to once we want to start reading history messages anyway.

Pogman commented 6 years ago

ok thanks - one other thing you might confirm for me: The history is always sent as a 24 hour period? ie I want an hour from 14:00-15:00 and its 18:00 now it will send 00:00-18:00? and if I want anything from yesterday it will be the full 24 hour day?

Also something I've found that may or not be a bug (I've only started digging) in the Tidepool docs and code that relate to Transmit Packet Request and the mode flags. My notes:

// note: pazaan tidepool docs have encrypted/speed mode flags the other way around but testing indicates that this is the way it should be // 0x10 always needed for encryption or else there is a timeout // 0x01 optional but using this does increase comms speed without needing to engage an EHSM session request

Using high speed this way does not seem to cause pump channel changing... mmm investigating.

Pogman commented 6 years ago

A further note on these mode flags: when an EHSM session if requested then this state must be engaged via the mode flag for all further pump comms or risk of radio channel change is high in a noisy environment. Btw the uploader was actually hard coded to just use 0x10.

On the big plus side this gives us EHSM mode back for realtime use in the uploader.

Also poke me with a pointy stick and call me Phillis but how long has it taken to get to the bottom of this! ah well... :)

cfaagaard commented 6 years ago

Another project which handles the history: https://github.com/paulokow/pump_data_downloader