Java Code Examples for com.eveningoutpost.dexdrip.Models.UserError.Log#i()

The following examples show how to use com.eveningoutpost.dexdrip.Models.UserError.Log#i() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DexCollectionService.java    From xDrip with GNU General Public License v3.0 6 votes vote down vote up
private void closeCycle(boolean should_close) {
    if (mBluetoothGatt != null) {
        try {
            if (JoH.ratelimit("refresh-gatt", 60)) {
                Log.d(TAG, "Refresh result close: " + JoH.refreshDeviceCache(TAG, mBluetoothGatt));
            }
            if (should_close) {
                Log.i(TAG, "connect: mBluetoothGatt isn't null, Closing.");
                mBluetoothGatt.close();
            } else {
                Log.i(TAG, "preserving existing connection");
            }
        } catch (NullPointerException e) {
            Log.wtf(TAG, "Concurrency related null pointer in connect");
        } finally {
            if (should_close) mBluetoothGatt = null;
        }
    }
}
 
Example 2
Source File: Blukon.java    From xDrip with GNU General Public License v3.0 6 votes vote down vote up
private static int nowGetGlucoseValue(byte[] input) {
    final int curGluc;
    final long rawGlucose;

    // option to use 13 bit mask
    //final boolean thirteen_bit_mask = Pref.getBooleanDefaultFalse("testing_use_thirteen_bit_mask");
    final boolean thirteen_bit_mask = true;
    // grep 2 bytes with BG data from input bytearray, mask out 12 LSB bits and rescale for xDrip+
    rawGlucose = ((input[3 + m_nowGlucoseOffset + 1] & (thirteen_bit_mask ? 0x1F : 0x0F)) << 8) | (input[3 + m_nowGlucoseOffset] & 0xFF);
    Log.i(TAG, "rawGlucose=" + rawGlucose + ", m_nowGlucoseOffset=" + m_nowGlucoseOffset);

    // rescale
    curGluc = getGlucose(rawGlucose);

    return curGluc;
}
 
Example 3
Source File: TransmitterData.java    From xDrip with GNU General Public License v3.0 6 votes vote down vote up
public static TransmitterData getForTimestamp(double timestamp) {//KS
    try {
        Sensor sensor = Sensor.currentSensor();
        if (sensor != null) {
            TransmitterData bgReading = new Select()
                    .from(TransmitterData.class)
                    .where("timestamp <= ?", (timestamp + (60 * 1000))) // 1 minute padding (should never be that far off, but why not)
                    .orderBy("timestamp desc")
                    .executeSingle();
            if (bgReading != null && Math.abs(bgReading.timestamp - timestamp) < (3 * 60 * 1000)) { //cool, so was it actually within 4 minutes of that bg reading?
                Log.i(TAG, "getForTimestamp: Found a BG timestamp match");
                return bgReading;
            }
        }
    } catch (Exception e) {
        Log.e(TAG,"getForTimestamp() Got exception on Select : "+e.toString());
        return null;
    }
    Log.d(TAG, "getForTimestamp: No luck finding a BG timestamp match");
    return null;
}
 
Example 4
Source File: Blukon.java    From xDrip-plus with GNU General Public License v3.0 6 votes vote down vote up
public static boolean isCollecting() {
    // use internal logic to decide if we are collecting something, if we return true here
    // then we will never get reset due to missed reading service restarts
    long m_minutesDiff = 0;

    m_minutesDiff = (long) (JoH.msSince(m_timeLastCmdReceived) / Constants.MINUTE_IN_MS);

    Log.i(TAG, "m_minutesDiff to last cmd=" + m_minutesDiff + ", last cmd received at: " + JoH.dateTimeText(m_timeLastCmdReceived));

    if (m_communicationStarted) {
        //we need to make sure communication did not stop a long time ago because of another issue
        if (m_minutesDiff > 2)//min. A cmd should be received within a few ms so if after this time nothing has been received we overwrite this flag
        {
            m_communicationStarted = false;
        }
    }

    return m_communicationStarted;
}
 
Example 5
Source File: BgReading.java    From xDrip with GNU General Public License v3.0 6 votes vote down vote up
public static void create(SensorRecord sensorRecord, long addativeOffset, Context context) {
    Log.i(TAG, "create: gonna make some sensor records: " + sensorRecord.getUnfiltered());
    if (BgReading.is_new(sensorRecord, addativeOffset)) {
        BgReading bgReading = new BgReading();
        Sensor sensor = Sensor.currentSensor();
        Calibration calibration = Calibration.getForTimestamp(sensorRecord.getSystemTime().getTime() + addativeOffset);
        if (sensor != null && calibration != null) {
            bgReading.sensor = sensor;
            bgReading.sensor_uuid = sensor.uuid;
            bgReading.calibration = calibration;
            bgReading.calibration_uuid = calibration.uuid;
            bgReading.raw_data = (sensorRecord.getUnfiltered() / 1000);
            bgReading.filtered_data = (sensorRecord.getFiltered() / 1000);
            bgReading.timestamp = sensorRecord.getSystemTime().getTime() + addativeOffset;
            if (bgReading.timestamp > new Date().getTime()) {
                return;
            }
            bgReading.uuid = UUID.randomUUID().toString();
            bgReading.time_since_sensor_started = bgReading.timestamp - sensor.started_at;
            bgReading.calculateAgeAdjustedRawValue();
            bgReading.save();
        }
    }
}
 
Example 6
Source File: BgReading.java    From xDrip-Experimental with GNU General Public License v3.0 6 votes vote down vote up
public static BgReading getForTimestamp(double timestamp) {
    Sensor sensor = Sensor.currentSensor();
    if(sensor != null) {
        BgReading bgReading = new Select()
                .from(BgReading.class)
                .where("Sensor = ? ", sensor.getId())
                .where("timestamp <= ?", (timestamp + (60 * 1000))) // 1 minute padding (should never be that far off, but why not)
                .where("calculated_value = 0")
                .where("raw_calculated = 0")
                .orderBy("timestamp desc")
                .executeSingle();
        if(bgReading != null && Math.abs(bgReading.timestamp - timestamp) < (3*60*1000)) { //cool, so was it actually within 4 minutes of that bg reading?
            Log.i(TAG, "getForTimestamp: Found a BG timestamp match");
            return bgReading;
        }
    }
    Log.d(TAG, "getForTimestamp: No luck finding a BG timestamp match");
    return null;
}
 
Example 7
Source File: ShareTest.java    From xDrip-plus with GNU General Public License v3.0 6 votes vote down vote up
public void attemptConnection() {
    mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    if (device != null) {
        details.append("\nConnection state: " + " Device is not null");
        mConnectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
    }

    Log.i(TAG, "Connection state: " + mConnectionState);
    details.append("\nConnection state: " + mConnectionState);
    if (mConnectionState == STATE_DISCONNECTED || mConnectionState == STATE_DISCONNECTING) {
        ActiveBluetoothDevice btDevice = new Select().from(ActiveBluetoothDevice.class)
                .orderBy("_ID desc")
                .executeSingle();
        if (btDevice != null) {
            details.append("\nBT Device: " + btDevice.name);
            mDeviceName = btDevice.name;
            mDeviceAddress = btDevice.address;
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            boolean newConnection = true;
            if(newConnection) {
                is_connected = connect(mDeviceAddress);
                details.append("\nConnecting...: ");
            }
        }
    }
}
 
Example 8
Source File: BgReading.java    From xDrip with GNU General Public License v3.0 6 votes vote down vote up
public static BgReading getForTimestamp(double timestamp) {
    Sensor sensor = Sensor.currentSensor();
    if (sensor != null) {
        BgReading bgReading = new Select()
                .from(BgReading.class)
                .where("Sensor = ? ", sensor.getId())
                .where("timestamp <= ?", (timestamp + (60 * 1000))) // 1 minute padding (should never be that far off, but why not)
                .where("calculated_value = 0")
                .where("raw_calculated = 0")
                .orderBy("timestamp desc")
                .executeSingle();
        if (bgReading != null && Math.abs(bgReading.timestamp - timestamp) < (3 * 60 * 1000)) { //cool, so was it actually within 4 minutes of that bg reading?
            Log.i(TAG, "getForTimestamp: Found a BG timestamp match");
            return bgReading;
        }
    }
    Log.d(TAG, "getForTimestamp: No luck finding a BG timestamp match");
    return null;
}
 
Example 9
Source File: BgReading.java    From xDrip-Experimental with GNU General Public License v3.0 6 votes vote down vote up
public static boolean is_new(SensorRecord sensorRecord, long addativeOffset) {
    double timestamp = sensorRecord.getSystemTime().getTime() + addativeOffset;
    Sensor sensor = Sensor.currentSensor();
    if(sensor != null) {
        BgReading bgReading = new Select()
                .from(BgReading.class)
                .where("Sensor = ? ", sensor.getId())
                .where("timestamp <= ?",  (timestamp + (60*1000))) // 1 minute padding (should never be that far off, but why not)
                .orderBy("timestamp desc")
                .executeSingle();
        if(bgReading != null && Math.abs(bgReading.timestamp - timestamp) < (3*60*1000)) { //cool, so was it actually within 4 minutes of that bg reading?
            Log.i(TAG, "isNew; Old Reading");
            return false;
        }
    }
    Log.i(TAG, "isNew: New Reading");
    return true;
}
 
Example 10
Source File: LibreTrendGraph.java    From xDrip with GNU General Public License v3.0 5 votes vote down vote up
private static ArrayList<Float> getLatestBgForXMinutes(int NumberOfMinutes) {

        Log.i(TAG, "getLatestBgForXMinutes number of minutes = " + NumberOfMinutes);
        
        List<LibreTrendPoint> LibreTrendPoints = LibreTrendUtil.getInstance().getData(JoH.tsl() - NumberOfMinutes * 60 * 1000, JoH.tsl());
        if(LibreTrendPoints == null || LibreTrendPoints.size() == 0) {
            Log.e(TAG, "Error getting data from getLatestBgForXMinutes");
            return null;
        }
        
        LibreTrendLatest libreTrendLatest = LibreTrendUtil.getInstance().getLibreTrendLatest();
        if(libreTrendLatest.glucoseLevelRaw == 0) {
            Log.e(TAG, "libreBlock exists but libreTrendLatest.glucoseLevelRaw is zero ");
            return null;
        }
        ArrayList<Float> ret = new ArrayList<Float>();
        
        double factor = libreTrendLatest.bg / libreTrendLatest.glucoseLevelRaw;
        if(factor == 0) {
            // We don't have the calculated value, but we do have the raw value. (No calibration exists)
            // I want to show raw data.
            Log.w(TAG, "Bg data was not calculated, working on raw data");
            List<BgReading> latestReading = BgReading.latestForGraph (1, libreTrendLatest.timestamp - 1000, libreTrendLatest.timestamp + 1000);
            if(latestReading == null || latestReading.size() == 0) {
                Log.e(TAG, "libreBlock exists but no matching bg record exists");
                return null;
            }
            
            factor = latestReading.get(0).raw_data / libreTrendLatest.glucoseLevelRaw;
        }
        
        int count = 0;
        for(int i = libreTrendLatest.id ; i >= 0 && count < NumberOfMinutes; i--) {
            count ++;
            ret.add(new Float(factor * LibreTrendPoints.get(i).rawSensorValue));
        }
            
        return ret;

    }
 
Example 11
Source File: NFCReaderX.java    From xDrip with GNU General Public License v3.0 5 votes vote down vote up
static public ReadingData getTrend(LibreBlock libreBlock) {
    if(libreBlock.byte_start != 0 || libreBlock.byte_end < 344) {
        Log.i(TAG, "libreBlock exists but does not have enough data " + libreBlock.timestamp);
        return null;
    }
    ReadingData result = parseData(0, "", libreBlock.blockbytes, JoH.tsl());
    if(result.trend.size() == 0 || result.trend.get(0).glucoseLevelRaw == 0) {
        Log.i(TAG, "libreBlock exists but no trend data exists, or first value is zero " + libreBlock.timestamp);
        return null;
    }
    
    // TODO: verify checksum
    return result;
}
 
Example 12
Source File: LibreTrendUtil.java    From xDrip-plus with GNU General Public License v3.0 5 votes vote down vote up
public synchronized static LibreTrendUtil getInstance() {
   if(singleton == null) {
      singleton = new LibreTrendUtil();
   }
   Log.i(TAG, "getInstance this = " + singleton);
   return singleton;
}
 
Example 13
Source File: DexShareCollectionService.java    From xDrip-Experimental with GNU General Public License v3.0 5 votes vote down vote up
public void setListeners(int listener_number) {
    Log.i(TAG, "Setting Listener: #" + listener_number);
    if (listener_number == 1) {
        step = 2;
        setCharacteristicIndication(mReceiveDataCharacteristic);
    } else {
        step = 3;
        attemptRead();
    }
}
 
Example 14
Source File: ListenerService.java    From xDrip-plus with GNU General Public License v3.0 5 votes vote down vote up
private synchronized void startMeasurement() {
    if (mSensorManager == null) mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));

    //if (BuildConfig.DEBUG) {
    logAvailableSensors();
    //}
    mCounterSteps = 0;
    Log.i(TAG, "startMeasurement SensorService Event listener for step counter sensor register");

    android.hardware.Sensor stepCounterSensor = mSensorManager.getDefaultSensor(SENS_STEP_COUNTER);

    // Register the listener
    if (mSensorManager != null) {
        if (stepCounterSensor != null) {
            if (mPrefs.getBoolean("showSteps", false)) {
                int delay = Integer.parseInt(mPrefs.getString("step_delay_time", "10"));
                Log.d(TAG, "startMeasurement delay " + delay + " seconds.");
                Log.d(TAG, "startMeasurement Event listener for step counter sensor registered with a max delay of " + delay + " seconds.");
                mSensorManager.registerListener(mListener, stepCounterSensor, SensorManager.SENSOR_DELAY_UI, delay * BATCH_LATENCY_1s);
            }
            else {
                Log.d(TAG, "startMeasurement Event listener for step counter sensor registered with a max delay of " + BATCH_LATENCY_400s);
                mSensorManager.registerListener(mListener, stepCounterSensor, SensorManager.SENSOR_DELAY_NORMAL, BATCH_LATENCY_400s);
            }
        } else {
            Log.d(TAG, "startMeasurement No Step Counter Sensor found");
        }
    }
}
 
Example 15
Source File: Notifications.java    From xDrip with GNU General Public License v3.0 5 votes vote down vote up
private long calcuatleArmTimeUnclearalert(Context ctx, long now, boolean unclearAlert) {
    if (!unclearAlert) {
        return Long.MAX_VALUE;
    }
    Long wakeTimeUnclear = Long.MAX_VALUE;

    UserNotification userNotification = UserNotification.GetNotificationByType("bg_unclear_readings_alert");
    if (userNotification == null) {
        // This is the case, that we are in unclear sensor reading, but for small time, so there is no call 
    	Log.i(TAG, "No active alert exists. returning Long.MAX_VALUE");
    	return Long.MAX_VALUE;
    } else {
        // This alert is snoozed
        // reminder - userNotification.timestamp is the time that the alert should be played again
        wakeTimeUnclear = (long)userNotification.timestamp;
    }
    
    if(wakeTimeUnclear < now ) {
        // we should alert now,
        wakeTimeUnclear = now;
    }
    if( wakeTimeUnclear == Long.MAX_VALUE) {
        // Should not happen
        Log.e(TAG ,"calcuatleArmTimeUnclearalert wakeTimeUnclear bad value setting it to one minute from now " + new Date(wakeTimeUnclear) + " in " +  ((wakeTimeUnclear - now)/60000d) + " minutes" );
        return now + 60 * 1000;
    }
    Log.w(TAG ,"calcuatleArmTimeUnclearalert returning " + new Date(wakeTimeUnclear) + " in " +  ((wakeTimeUnclear - now)/60000d) + " minutes" );
    return wakeTimeUnclear;
}
 
Example 16
Source File: Notifications.java    From xDrip-plus with GNU General Public License v3.0 5 votes vote down vote up
private void ArmTimer(Context ctx, boolean unclearAlert) {
    Calendar calendar = Calendar.getInstance();
    final long now = calendar.getTimeInMillis();
    Log.d("Notifications", "ArmTimer called");

    long wakeTime = calcuatleArmTime(ctx, now, unclearAlert);

    
    if(wakeTime < now ) {
        Log.e("Notifications" , "ArmTimer recieved a negative time, will fire in 6 minutes");
        wakeTime = now + 6 * 60000;
    } else if  (wakeTime >=  now + 6 * 60000) {
    	 Log.i("Notifications" , "ArmTimer recieved a bigger time, will fire in 6 minutes");
         wakeTime = now + 6 * 60000;
    }  else if (wakeTime == now) {
        Log.e("Notifications", "should arm right now, waiting one more second to avoid infinitue loop");
        wakeTime = now + 1000;
    }
    
    AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);

    
    Log.d("Notifications" , "ArmTimer waking at: "+ new Date(wakeTime ) +" in " +
        (wakeTime - now) /60000d + " minutes");
    if (wakeIntent != null)
        alarm.cancel(wakeIntent);
    wakeIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), 0);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, wakeTime, wakeIntent);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        alarm.setExact(AlarmManager.RTC_WAKEUP, wakeTime, wakeIntent);
    } else {
        alarm.set(AlarmManager.RTC_WAKEUP, wakeTime, wakeIntent);
    }
}
 
Example 17
Source File: Sensor.java    From xDrip-plus with GNU General Public License v3.0 5 votes vote down vote up
public static void stopSensor() {
    Sensor sensor = currentSensor();
    if(sensor == null) {
        return;
    }
    sensor.stopped_at = new Date().getTime();
    Log.i("SENSOR", "Sensor stopped at " + sensor.stopped_at);
    sensor.save();
    SensorSendQueue.addToQueue(sensor);

}
 
Example 18
Source File: blueReader.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
private static synchronized void processNewTransmitterData(TransmitterData transmitterData, long timestamp) {
    if (transmitterData == null) {
        return;
    }

    final Sensor sensor = Sensor.currentSensor();
    if (sensor == null) {
        Log.i(TAG, "setSerialDataToTransmitterRawData: No Active Sensor, Data only stored in Transmitter Data");
        return;
    }

    if(PersistentStore.getLong("blueReader_Full_Battery") <3000 )
        PersistentStore.setLong("blueReader_Full_Battery", 4100);

    double blueReaderDays =0;
    if (transmitterData.sensor_battery_level > PersistentStore.getLong("blueReader_Full_Battery")) {
        PersistentStore.setLong("blueReader_Full_Battery", transmitterData.sensor_battery_level);
        Log.i(TAG, "blueReader_Full_Battery set to: " + transmitterData.sensor_battery_level) ;
    }
    int localBridgeBattery =((transmitterData.sensor_battery_level - 3300) * 100 / (((int) (long) PersistentStore.getLong("blueReader_Full_Battery"))-3300));
    Pref.setInt("bridge_battery", localBridgeBattery);
    sensor.latest_battery_level = localBridgeBattery;
    blueReaderDays = 6.129200670865791d / (1d + Math.pow(((double)transmitterData.sensor_battery_level/3763.700630306379d),(-61.04241888028577d))); //todo compare with test-formular, and new Data of batterylog
    if (transmitterData.sensor_battery_level < 3600) {
        blueReaderDays=blueReaderDays + 0.1d;
    }
    blueReaderDays = ((Math.round((blueReaderDays)*10d)/10d));

    PersistentStore.setString("bridge_battery_days", String.valueOf(blueReaderDays));
    sensor.save();
    if (Pref.getBooleanDefaultFalse("blueReader_writebatterylog")) {
        final String dir = getExternalDir();
        makeSureDirectoryExists(dir);
        writeLog(dir + BatLog,
                DateFormat.format("yyyyMMdd-kkmmss", System.currentTimeMillis()).toString() + "|" +
                        PersistentStore.getLong("blueReader_Full_Battery") + "|" +
                        transmitterData.sensor_battery_level + "|" +
                        sensor.latest_battery_level + "|" +
                        blueReaderDays
        );
    }
    DexCollectionService.last_transmitter_Data = transmitterData;
    Log.d(TAG, "BgReading.create: new BG reading at " + timestamp + " with a timestamp of " + transmitterData.timestamp);
    BgReading.create(transmitterData.raw_data, transmitterData.filtered_data, xdrip.getAppContext(), transmitterData.timestamp);

}
 
Example 19
Source File: ListenerService.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    // TODO can use equals() instead of compareTo()
    Log.d(TAG, "OnSharedPreferenceChangeListener entered key=" + ((key != null && !key.isEmpty()) ? key : ""));
    if(key.compareTo("enable_wearG5") == 0 || key.compareTo("force_wearG5") == 0 || key.compareTo("node_wearG5") == 0) {
        Log.i(TAG, "OnSharedPreferenceChangeListener sendPrefSettings and processConnect for key=" + key);
        sendPrefSettings();
        processConnect();
    }
    else if(key.compareTo("bridge_battery") == 0 || key.compareTo("nfc_sensor_age") == 0 ||
            key.compareTo("bg_notifications") == 0 || key.compareTo("persistent_high_alert_enabled") == 0 ||
            key.compareTo("show_wear_treatments") == 0){
        Log.d(TAG, "OnSharedPreferenceChangeListener sendPrefSettings for key=" + key);
        sendPrefSettings();
    }
    else if (key.compareTo("use_wear_health") == 0 || key.compareTo("showSteps") == 0 || key.compareTo("step_delay_time") == 0
            || key.equals("use_wear_heartrate")) {
        setupStepSensor();
    }
    else if (key.compareTo("sync_wear_logs") == 0) {
        last_send_previous_log = JoH.tsl();
        PersistentStore.setLong(pref_last_send_previous_log, last_send_previous_log);
    }
    /*else if (key.compareTo("show_wear_treatments") == 0) {
        Log.d(TAG, "OnSharedPreferenceChangeListener sendPrefSettings for key=" + key);
        Context context = xdrip.getAppContext();
        showTreatments(context, "all");
    }*/
    else if (key.compareTo("overrideLocale") == 0) {
        if (prefs.getBoolean("overrideLocale", false)) {
            Log.d(TAG, "overrideLocale true; Request phone locale");
            sendData(WEARABLE_LOCALE_CHANGED_PATH, null);
        }
    }
    else {//if(key.compareTo("dex_txid") == 0 || key.compareTo(DexCollectionType.DEX_COLLECTION_METHOD) == 0){
        //Restart collector for change in the following received from phone in syncPrefData():
        //DexCollectionType.DEX_COLLECTION_METHOD - dex_collection_method, share_key or dex_txid
        //Advanced BT Settings:
        //use_transmiter_pl_bluetooth
        //use_rfduino_bluetooth, ...
        if (restartCollectorPrefs.contains(key)) {
            Log.d(TAG, "OnSharedPreferenceChangeListener restartCollectorPrefs requires collector restart key=" + key);
            stopBtService();
        }
        processConnect();
    }
}
 
Example 20
Source File: G5CollectionService.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
private synchronized void processRxCharacteristic(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            Log.i(TAG, "onCharacteristicChanged On Main Thread? " + isOnMainThread());
            Log.e(TAG, "CharBytes-nfy" + Arrays.toString(characteristic.getValue()));
            Log.i(TAG, "CharHex-nfy" + Extensions.bytesToHex(characteristic.getValue()));


            byte[] buffer = characteristic.getValue();
            byte firstByte = buffer[0];
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && gatt != null) {
                gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
            }
            Log.d(TAG, "Received opcode reply: " + JoH.bytesToHex(new byte[] { firstByte }));
            if (firstByte == 0x2f) {
                SensorRxMessage sensorRx = new SensorRxMessage(characteristic.getValue());

                ByteBuffer sensorData = ByteBuffer.allocate(buffer.length);
                sensorData.order(ByteOrder.LITTLE_ENDIAN);
                sensorData.put(buffer, 0, buffer.length);

                int sensor_battery_level = 0;
                if (sensorRx.status == TransmitterStatus.BRICKED) {
                    //TODO Handle this in UI/Notification
                    sensor_battery_level = 206; //will give message "EMPTY"
                } else if (sensorRx.status == TransmitterStatus.LOW) {
                    sensor_battery_level = 209; //will give message "LOW"
                } else {
                    sensor_battery_level = 216; //no message, just system status "OK"
                }

                //Log.e(TAG, "filtered: " + sensorRx.filtered);
                disconnected133 = 0; // reset as we got a reading
                disconnected59 = 0;
                lastState = "Got data OK: " + JoH.hourMinuteString();
                successes++;
                failures=0;
                Log.e(TAG, "SUCCESS!! unfiltered: " + sensorRx.unfiltered + " timestamp: " + sensorRx.timestamp + " " + JoH.qs((double)sensorRx.timestamp / 86400, 1) + " days");
                if (sensorRx.unfiltered == 0) {
                    lastState = "Transmitter sent raw sensor value of 0 !! This isn't good. " + JoH.hourMinuteString();
                }
                last_transmitter_timestamp = sensorRx.timestamp;
                if ((getVersionDetails) && (!haveFirmwareDetails())) {
                    doVersionRequestMessage(gatt, characteristic);
                } else if ((getBatteryDetails) && (getBatteryStatusNow || !haveCurrentBatteryStatus())) {
                    doBatteryInfoRequestMessage(gatt, characteristic);
                } else {
                    doDisconnectMessage(gatt, characteristic);
                }

                // TODO beware that wear G5CollectionService is now getting rather out of sync with app version
                final boolean g6 = usingG6();
                processNewTransmitterData(g6 ? sensorRx.unfiltered * G6_SCALING : sensorRx.unfiltered, g6 ? sensorRx.filtered * G6_SCALING : sensorRx.filtered, sensor_battery_level, new Date().getTime());

                // was this the first success after we force enabled always_authenticate?
                if (force_always_authenticate && (successes == 1)) {
                    Log.wtf(TAG, "We apparently only got a reading after forcing the Always Authenticate option");
                    Home.toaststaticnext("Please Enable G5 Always Authenticate debug option!");
                    // TODO should we actually change the settings here?
                }
            } else if (firstByte == GlucoseRxMessage.opcode) {
                disconnected133 = 0; // reset as we got a reading
                disconnected59 = 0;
                GlucoseRxMessage glucoseRx = new GlucoseRxMessage(characteristic.getValue());
                Log.e(TAG, "SUCCESS!! glucose unfiltered: " + glucoseRx.unfiltered);
                successes++;
                failures=0;
                doDisconnectMessage(gatt, characteristic);
                processNewTransmitterData(glucoseRx.unfiltered, glucoseRx.filtered, 216, new Date().getTime());
            } else if (firstByte == VersionRequestRxMessage.opcode) {
                if (!setStoredFirmwareBytes(defaultTransmitter.transmitterId, characteristic.getValue(), true)) {
                    Log.wtf(TAG, "Could not save out firmware version!");
                }
                doDisconnectMessage(gatt, characteristic);
            } else if (firstByte == BatteryInfoRxMessage.opcode) {
                if (!setStoredBatteryBytes(defaultTransmitter.transmitterId, characteristic.getValue())) {
                    Log.wtf(TAG, "Could not save out battery data!");
                }
                getBatteryStatusNow = false;
                doDisconnectMessage(gatt, characteristic);
            } else {
                Log.e(TAG, "onCharacteristic CHANGED unexpected opcode: " + firstByte + " (have not disconnected!)");
            }
            Log.e(TAG, "OnCharacteristic CHANGED finished: ");
        }