Merge pull request #3 from JohanDegraeve/master

sync
This commit is contained in:
bubbledevteam 2019-08-01 15:07:45 +08:00 committed by GitHub
commit ff21d0b403
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 8 deletions

View File

@ -180,6 +180,7 @@
F8BDD450221CAA64006EAB84 /* TextsCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BDD44F221CAA64006EAB84 /* TextsCommon.swift */; };
F8BDD452221DEAB2006EAB84 /* TextsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BDD451221DEAB1006EAB84 /* TextsSettingsView.swift */; };
F8BDD455221DEF22006EAB84 /* SettingsViews.strings in Resources */ = {isa = PBXBuildFile; fileRef = F8BDD457221DEF22006EAB84 /* SettingsViews.strings */; };
F8C5EBE522F297F000563B5F /* SensorSerialNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5EBE422F297EF00563B5F /* SensorSerialNumber.swift */; };
F8E3C3AB21FE17B700907A04 /* StringProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E3C3AA21FE17B700907A04 /* StringProtocol.swift */; };
F8E3C3AD21FE551C00907A04 /* DexcomCalibrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E3C3AC21FE551C00907A04 /* DexcomCalibrator.swift */; };
F8EA6C8221B723BC0082976B /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8EA6C8121B723BC0082976B /* Date.swift */; };
@ -479,6 +480,7 @@
F8BDD451221DEAB1006EAB84 /* TextsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsSettingsView.swift; sourceTree = "<group>"; };
F8BDD456221DEF22006EAB84 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SettingsViews.strings; sourceTree = "<group>"; };
F8BDD458221DEF24006EAB84 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/SettingsViews.strings; sourceTree = "<group>"; };
F8C5EBE422F297EF00563B5F /* SensorSerialNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorSerialNumber.swift; sourceTree = "<group>"; };
F8E3C3AA21FE17B700907A04 /* StringProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringProtocol.swift; sourceTree = "<group>"; };
F8E3C3AC21FE551C00907A04 /* DexcomCalibrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DexcomCalibrator.swift; sourceTree = "<group>"; };
F8EA6C8121B723BC0082976B /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
@ -861,6 +863,7 @@
F8A54AFB22D9179100934E7A /* Utilities */ = {
isa = PBXGroup;
children = (
F8C5EBE422F297EF00563B5F /* SensorSerialNumber.swift */,
F8A54AFC22D9179100934E7A /* CRC.swift */,
F8A54AFD22D9179100934E7A /* ParseLibreData.swift */,
F8A54AFE22D9179100934E7A /* SensorState.swift */,
@ -1471,6 +1474,7 @@
F8B3A856227F28DC004BA588 /* AlertTypeSettingsViewController.swift in Sources */,
F8A54AE822D911BA00934E7A /* BatteryStatusRxMessage.swift in Sources */,
F8A1584F22ECB281007F5B5D /* SettingsViewInfoViewModel.swift in Sources */,
F8C5EBE522F297F000563B5F /* SensorSerialNumber.swift in Sources */,
F8B3A845227F090E004BA588 /* SettingsViewDexcomSettingsViewModel.swift in Sources */,
F8A1585F22EDB81E007F5B5D /* ConstantsLog.swift in Sources */,
F8A1586522EDB89D007F5B5D /* ConstantsDefaultAlertTypeSettings.swift in Sources */,

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.4.2</string>
<string>2.5.0</string>
<key>CFBundleVersion</key>
<string>2.4.2</string>
<string>2.5.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSBluetoothPeripheralUsageDescription</key>

View File

@ -39,10 +39,13 @@ class CGMBubbleTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, C
/// used as parameter in call to cgmTransmitterDelegate.cgmTransmitterInfoReceived, when there's no glucosedata to send
var emptyArray: [RawGlucoseData] = []
// current sensor serial number, if nil then it's not known yet
private var sensorSerialNumber:String?
// MARK: - Initialization
/// - parameters:
/// - address: if already connected before, then give here the address that was received during previous connect, if not give nil
init(address:String?, delegate:CGMTransmitterDelegate, timeStampLastBgReading:Date) {
init(address:String?, delegate:CGMTransmitterDelegate, timeStampLastBgReading:Date, sensorSerialNumber:String?) {
// assign addressname and name or expected devicename
var newAddressAndName:BluetoothTransmitter.DeviceAddressAndName = BluetoothTransmitter.DeviceAddressAndName.notYetConnected(expectedName: expectedDeviceNameBubble)
@ -50,6 +53,9 @@ class CGMBubbleTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, C
newAddressAndName = BluetoothTransmitter.DeviceAddressAndName.alreadyConnectedBefore(address: address)
}
// initialize sensorSerialNumber
self.sensorSerialNumber = sensorSerialNumber
// assign CGMTransmitterDelegate
cgmTransmitterDelegate = delegate
@ -130,6 +136,30 @@ class CGMBubbleTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, C
rxBuffer.append(value.suffix(from: 4))
if rxBuffer.count >= 352 {
if (Crc.LibreCrc(data: &rxBuffer, headerOffset: BubbleHeaderLength)) {
if let sensorSerialNumberData = SensorSerialNumber(withUID: Data(rxBuffer.subdata(in: 5..<13))) {
let newSerialNumber = sensorSerialNumberData.serialNumber
// verify serial number and if changed inform delegate
if newSerialNumber != sensorSerialNumber {
os_log(" new sensor detected : %{public}@", log: log, type: .info, newSerialNumber)
sensorSerialNumber = newSerialNumber
// inform delegate about new sensor detected
cgmTransmitterDelegate?.newSensorDetected()
// also reset timestamp last reading, to be sure that if new sensor is started, we get historic data
timeStampLastBgReading = Date(timeIntervalSince1970: 0)
// inform delegate about sensorSerialNumber
cgmTransmitterDelegate?.cgmTransmitterInfoReceived(glucoseData: &emptyArray, transmitterBatteryInfo: nil, sensorState: nil, sensorTimeInMinutes: nil, firmware: nil, hardware: nil, hardwareSerialNumber: nil, bootloader: nil, sensorSerialNumber: sensorSerialNumber)
}
}
//get readings from buffer and send to delegate
var result = parseLibreData(data: &rxBuffer, timeStampLastBgReadingStoredInDatabase: timeStampLastBgReading, headerOffset: BubbleHeaderLength)
//TODO: sort glucosedata before calling newReadingsReceived
@ -156,7 +186,7 @@ class CGMBubbleTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate, C
// MARK: CGMTransmitter protocol functions
/// to ask pairing - empty function because G4 doesn't need pairing
/// to ask pairing - empty function because Bubble doesn't need pairing
///
/// this function is not implemented in BluetoothTransmitter.swift, otherwise it might be forgotten to look at in future CGMTransmitter developments
func initiatePairing() {}

View File

@ -88,7 +88,7 @@ class CGMGNSEntryTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate,
/// used as parameter in call to cgmTransmitterDelegate.cgmTransmitterInfoReceived, when there's no glucosedata to send
var emptyArray: [RawGlucoseData] = []
// MARK: - functions
// MARK: - public functions
/// - parameters:
/// - address: if already connected before, then give here the address that was received during previous connect, if not give nil
@ -325,7 +325,9 @@ class CGMGNSEntryTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate,
}
}
/// creates readable representation of characteristicUUID, for logging only
// MARK: - private helper functions
/// creates CBUUID_Characteristic_UUID for the characteristicUUID
private func receivedCharacteristicUUIDToCharacteristic(characteristicUUID:String) -> CBUUID_Characteristic_UUID? {
if CBUUID_Characteristic_UUID.CBUUID_BatteryLevel.rawValue.containsIgnoringCase(find: characteristicUUID) {
return CBUUID_Characteristic_UUID.CBUUID_BatteryLevel

View File

@ -130,6 +130,9 @@ class CGMMiaoMiaoTransmitter:BluetoothTransmitter, BluetoothTransmitterDelegate,
let hardware = String(describing: rxBuffer[16...17].hexEncodedString())
let batteryPercentage = Int(rxBuffer[13])
let serialNumber = SensorSerialNumber(withUID: Data(rxBuffer.subdata(in: 5..<13)))?.serialNumber ?? "-"
debuglogging("serialNumber = " + serialNumber)
//get readings from buffer and send to delegate
var result = parseLibreData(data: &rxBuffer, timeStampLastBgReadingStoredInDatabase: timeStampLastBgReading, headerOffset: miaoMiaoHeaderLength)
//TODO: sort glucosedata before calling newReadingsReceived

View File

@ -0,0 +1,109 @@
//
// FreestyleLibreSensor.swift
// LibreMonitor
//
// Created by Uwe Petersen on 01.04.18.
// Copyright © 2018 Uwe Petersen. All rights reserved.
//
import Foundation
struct SensorSerialNumber: CustomStringConvertible {
let uid: Data
fileprivate let lookupTable = ["0","1","2","3","4","5","6","7","8","9","A","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","T","U","V","W","X","Y","Z"]
init?(withUID uid: Data) {
guard uid.count == 8 else {return nil}
self.uid = uid
}
// MARK: - computed properties
var serialNumber: String {
// The serial number of the sensor can be derived from its uid.
//
// The numbers an letters of the serial number are coded a compressed scheme that uses only 32 numbers and letters,
// by omitting the letters B, I, O and S. This information is stored in consecutive units of five bits.
//
// The encoding thus is as follows:
// index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// char: 0 1 2 3 4 5 6 7 8 9 A (B) C D E F G H (I) J K L M N (O) P Q R (S) T U V W X Y Z
//
// Example: 75 ce 86 00 00 a0 07 e0
// Uid is E0 07 A0 00 00 25 90 5E, and the corresponding serial number is "0M00009DHCR"
// \ / \ /
// -+- -----+--------
// | |
// | +-- This part encodes the serial number, see below
// +-- Standard first two bytes, where 0x07 is the code for "Texas Instruments Tag-it", see https://en.wikipedia.org/wiki/ISO/IEC_15693
//
// 1.) Convert the part without E007, i.e. A0 00 00 25 90 5E to binary representation
//
// A 0 0 0 0 0 2 5 9 0 5 E
// 1010 0000 0000 0000 0000 0000 0010 0101 1001 0000 0101 1110
//
// 2.) Split this binary array in units of five bits length from the beginning and pad with two zeros at the end and
// calculate the corresponding integer and retreive the corresponding char from the table above
//
// Byte # 0 1 2 3 4 5
// Bit # 8765 4321 8765 4321 8765 4321 8765 4321 8765 4321 8765 4321
//
// +-- 1010 0000 0000 0000 0000 0000 0010 0101 1001 0000 0101 1110 + 00
// | \ /\ /\ /\ / \ /\ /\ /\ / \ /\ /
// +-> 10100 00000 00000 00000 00000 01001 01100 10000 01011 11000
// | | | | | | | | | |
// | | | | | | | | | +- = 24 -> "R" (Byte 6) << 2 Mask 0x1F
// | | | | | | | | +-------- = 11 -> "C" (Byte 5) >> 3 Mask 0x1F
// | | | | | | | +--------------- = 16 -> "H" (Byte 4) Mask 0x1F
// | | | | | | +---------------------- = 12 -> "D" (Byte 3) << 2 + (Byte 4) >> 5 Mask 0x1F
// | | | | | +----------------------------- = 9 -> "9" (Byte 3) >> 2 Mask 0x1F
// | | | | +------------------------------------ = 0 -> "0" (Byte 2) << 1 + (Byte 3) >> 7 Mask 0x1F
// | | | +------------------------------------------- = 0 -> "0" (Byte 1) << 4 + (Byte 2) >> 4 Mask 0x1F
// | | +-------------------------------------------------- = 0 -> "0" (Byte 1) >> 1 Mask 0x1F
// | +--------------------------------------------------------- = 0 -> "0" (Byte 0) << 2 + (Byte 1) >> 6 Mask 0x1F
// +---------------------------------------------------------------- = 20 -> "M" (byte 0) >> 3 Mask 0x1F
//
//
// 3.) Prepend "0" at the beginning an thus receive "0M00009DHCR"
guard uid.count == 8 else {return "invalid uid"}
let bytes = Array(uid.reversed().suffix(6)) // 5E 90 25 00 00 A0 07 E0" -> E0 07 A0 00 00 25 90 5E -> A0 00 00 25 90 5E
// A0 00 00 25 90 5E -> "M00009DHCR"
var fiveBitsArray = [UInt8]() // Mask later with 0x1F to use only five bits
fiveBitsArray.append( bytes[0] >> 3 )
fiveBitsArray.append( bytes[0] << 2 + bytes[1] >> 6 )
fiveBitsArray.append( bytes[1] >> 1 )
fiveBitsArray.append( bytes[1] << 4 + bytes[2] >> 4 )
fiveBitsArray.append( bytes[2] << 1 + bytes[3] >> 7 )
fiveBitsArray.append( bytes[3] >> 2 )
fiveBitsArray.append( bytes[3] << 3 + bytes[4] >> 5 )
fiveBitsArray.append( bytes[4] )
fiveBitsArray.append( bytes[5] >> 3 )
fiveBitsArray.append( bytes[5] << 2 )
let serialNumber = fiveBitsArray.reduce("0", { // prepend with "0" according to step 3.)
$0 + lookupTable[ Int(0x1F & $1) ] // Mask with 0x1F to only take the five relevant bits
})
return serialNumber
}
var uidString: String {
return Data(self.uid).hexEncodedString()
}
var prettyUidString: String {
let stringArray = self.uid.map({String(format: "%02X", $0)})
return stringArray.dropFirst().reduce(stringArray.first!, {$0 + ":" + $1} )
}
// MARK: - CustomStringConvertible Protocoll
var description: String {
return "Uid is \(prettyUidString) and derived serial number is \(serialNumber)"
}
}

View File

@ -392,7 +392,8 @@ class BluetoothTransmitter: NSObject, CBCentralManagerDelegate, CBPeripheralDele
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
timeStampLastStatusUpdate = Date()
os_log("didDiscoverCharacteristicsFor", log: log, type: .info)
os_log("didDiscoverCharacteristicsFor for service with uuid %{public}@", log: log, type: .info, String(describing:service.uuid))
if let error = error {
os_log(" didDiscoverCharacteristicsFor error: %{public}@", log: log, type: .error , error.localizedDescription)
}

View File

@ -596,7 +596,7 @@ final class RootViewController: UIViewController {
calibrator = Libre1Calibrator()
case .Bubble:
cgmTransmitter = CGMBubbleTransmitter(address: UserDefaults.standard.bluetoothDeviceAddress, delegate: self, timeStampLastBgReading: Date(timeIntervalSince1970: 0))
cgmTransmitter = CGMBubbleTransmitter(address: UserDefaults.standard.bluetoothDeviceAddress, delegate: self, timeStampLastBgReading: Date(timeIntervalSince1970: 0), sensorSerialNumber: UserDefaults.standard.sensorSerialNumber)
calibrator = Libre1Calibrator()
case .GNSentry: