class FreestyleLibre::Reader
Constants
- INIT_COMMAND_SEQUENCE
- PRODUCT_ID
- VENDOR_ID
Public Class Methods
new(interface = nil)
click to toggle source
@param interface [Number] The interface number of the device; needed in case you have several readers connected
# File lib/freestyle_libre/reader.rb, line 9 def initialize(interface = nil) HIDAPI::SetupTaskHelper.new(VENDOR_ID, PRODUCT_ID, "abbott-freestyle-libre", interface).run @device = HIDAPI::open(VENDOR_ID, PRODUCT_ID, interface) raise 'device could not be opened' unless @device INIT_COMMAND_SEQUENCE.each do |c| write_report(c, '') read_report end end
Public Instance Methods
arresult()
click to toggle source
Manual measurements and date/time changes @return [Record]
# File lib/freestyle_libre/reader.rb, line 81 def arresult write_report(0x60, '$arresult?') read_multi.map { |record| ar(record) }.compact end
close()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 86 def close @device.close end
database_record_number()
click to toggle source
latest record ID ???
# File lib/freestyle_libre/reader.rb, line 65 def database_record_number # TODO: not sure this matches the description. # We should check that by scanning the tag two times and seeing that the number of new history # matches the increase of this number write_report(0x60, '$dbrnum?') read_text_command.gsub('DB Record Number =', '').strip.to_i end
date_time()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 30 def date_time write_report(0x60, '$date?') date = read_text_command.strip write_report(0x60, '$time?') DateTime.strptime("#{date} #{read_text_command}", '%m,%d,%y %H,%M') end
date_time=(value)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 37 def date_time=(value) write_report(0x60, "$date,#{value.strftime('%-m,%-d,%y')}") read_text_command write_report(0x60, "$time,#{value.strftime('%H,%M')}") read_text_command end
history()
click to toggle source
Automatic glucose measurements
# File lib/freestyle_libre/reader.rb, line 74 def history write_report(0x60, '$history?') read_multi.map { |record| auto_measurement(record) } end
patient_id()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 59 def patient_id write_report(0x60, '$ptid?') read_text_command.strip end
patient_id=(value)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 54 def patient_id=(value) write_report(0x60, "$ptid,#{value}") read_text_command end
patient_name()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 49 def patient_name write_report(0x60, '$ptname?') read_text_command.strip end
patient_name=(value)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 44 def patient_name=(value) write_report(0x60, "$ptname,#{value}") read_text_command end
serial()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 20 def serial write_report(0x60, '$sn?') read_text_command.strip end
software_version()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 25 def software_version write_report(0x60, '$swver?') read_text_command.strip end
Private Instance Methods
ar(record)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 92 def ar(record) fields = record.split(',').map(&:strip) case fields[1] when "2" manual_measurement(fields) end end
auto_measurement(record)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 109 def auto_measurement(record) fields = record.split(',').map(&:strip) Record.new(id: fields[0].to_i, date_time: parse_date_time(fields[2...7]), first_sensor_reading: fields[12]== "1", value: fields[13].to_i, sensor_runtime_minutes: fields[14].to_i, errored: fields[15].nil? || (fields[15].to_i & 0x8000) > 0, error_code: fields[15]) end
extract_text(msg)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 146 def extract_text(msg) msg, status = msg.split('CMD ') raise "*#{status}" unless status == "OK\r\n" msg, checksum = msg.split('CKSM:') validate_checksum!(msg, checksum.to_i(16)) msg end
manual_measurement(fields)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 100 def manual_measurement(fields) Record.new(id: fields[0].to_i, type: fields[1], date_time: parse_date_time(fields[2...7]), value: fields[12].to_i, errored: fields[28].nil? || (fields[28].to_i & 0x8000) > 0, error_code: fields[28]) end
parse_date_time(fields)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 120 def parse_date_time(fields) DateTime.new(fields[2].to_i + 2000, fields[0].to_i, fields[1].to_i, fields[3].to_i, fields[4].to_i, fields[5].to_i) end
read_multi()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 125 def read_multi msg = "" while true report = read_report raise "unexpected message type 0x#{report[:msg_type].to_s(16)}" unless report[:msg_type] == 0x60 msg += report[:msg] break if report[:msg].end_with?("CMD OK\r\n") end result = extract_text(msg).split("\r\n") record_count, checksum = result.pop.split(',') raise "wrong number of records: declared #{record_count}, got result.length" unless record_count.to_i == result.length validate_checksum!(result.join("\r\n")+"\r\n", checksum.to_i(16)) result end
read_report()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 158 def read_report reading = @device.read.bytes msg_type = reading.shift length = reading.shift return read_report if msg_type == 0x22 && length == 0x1 msg = reading.pack('C*')[0...length] while msg.length < length msg += @device.read.pack('C*')[0...(length - msg.length)] end {msg_type: msg_type , msg: msg} end
read_text_command()
click to toggle source
# File lib/freestyle_libre/reader.rb, line 140 def read_text_command report = read_report raise "unexpected message type 0x#{report[:msg_type].to_s(16)}" unless report[:msg_type] == 0x60 extract_text(report[:msg]) end
validate_checksum!(msg, checksum)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 154 def validate_checksum!(msg, checksum) raise "checksum failed" unless checksum = msg.bytes.reduce(0){ |m, b| m + b } end
write_report(cmd, value)
click to toggle source
# File lib/freestyle_libre/reader.rb, line 170 def write_report(cmd, value) value = value.bytes @device.write([0x00, cmd, value.length, *value, *Array.new(61-value.length, 0x00) ]) end