internal static void insert_after_command(UUID fromService, UUID fromCharacteristic,
                                                  Bluetooth_CMD btc_replacement)
        {
            List <Bluetooth_CMD> tmp_queue = new List <Bluetooth_CMD>();

            try
            {
                foreach (var btc in GlucoseGattCallback.Queue)
                {
                    tmp_queue.Add(btc);
                    if (btc.service.Equals(fromService) && btc.characteristic.Equals(fromCharacteristic))
                    {
                        if (btc_replacement != null)
                        {
                            tmp_queue.Add(btc_replacement);
                        }
                        btc_replacement = null; // first only item
                    }
                }

                GlucoseGattCallback.Queue.Clear();
                GlucoseGattCallback.Queue.AddRange(tmp_queue);
            }
            catch (Exception e)
            {
                Debug.WriteLine("Got exception in insert_after: ", e);
            }
        }
 private static void check_queue_age()
 {
     queue_check_scheduled = 0;
     if (GlucoseGattCallback.Queue.Any())
     {
         Bluetooth_CMD btc = GlucoseGattCallback.Queue.FirstOrDefault();
         if (btc != null)
         {
             long queue_age = DateTime.Now.Millisecond - btc.timestamp;
             if (GlucoseGattCallback.Debug)
             {
                 Debug.WriteLine("check queue age.. " + queue_age + " on " + btc.note);
             }
             if (queue_age > QUEUE_TIMEOUT)
             {
                 Debug.WriteLine("Timed out on: " + btc.note);
                 GlucoseGattCallback.Queue.Clear();
                 GlucoseGattCallback.last_queue_command = null;
                 System.Threading.Thread.Sleep(3000);
                 //reconnect(); hmm we would like to reconnect here
             }
         }
     }
     else
     {
         if (GlucoseGattCallback.Debug)
         {
             Debug.WriteLine("check queue age - queue is empty");
         }
     }
 }
 internal static void replace_command(UUID fromService, UUID fromCharacteristic, string type,
                                      Bluetooth_CMD btc_replacement)
 {
     try
     {
         foreach (var btc in GlucoseGattCallback.Queue)
         {
             if (btc.service.Equals(fromService) &&
                 btc.characteristic.Equals(fromCharacteristic) &&
                 btc.cmd.Equals(type))
             {
                 btc.service        = btc_replacement.service;
                 btc.characteristic = btc_replacement.characteristic;
                 btc.cmd            = btc_replacement.cmd;
                 btc.data           = btc_replacement.data;
                 btc.note           = btc_replacement.note;
                 Debug.WriteLine("Replaced service: " + fromService + " -> " + btc_replacement.service);
                 Debug.WriteLine("Replaced charact: " + fromCharacteristic + " -> " + btc_replacement.characteristic);
                 Debug.WriteLine("Replaced     cmd: " + btc_replacement.cmd);
                 break; // currently we only ever need to do one so break for speed
             }
         }
     }
     catch (Exception e)
     {
         Debug.WriteLine("Got exception in replace: ", e);
     }
 }
        public override void OnCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, GattStatus status)
        {
            base.OnCharacteristicWrite(gatt, characteristic, status);
            System.Diagnostics.Debug.WriteLine("Written to: " + characteristic.Uuid + " getvalue: " + characteristic.GetValue() + " status: " + status);


            if (status == GattStatus.Success)
            {
                if (ack_blocking())
                {
                    if (Debug)
                    {
                        System.Diagnostics.Debug.WriteLine("Awaiting ACK before next command: " + AwaitingAck + ":" + AwaitingData);
                    }
                }
                else
                {
                    Bluetooth_CMD.poll_queue();
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Got gatt write failure: " + status);
                Bluetooth_CMD.retry_last_command((int)status);
            }
        }
 public override void OnDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, GattStatus status)
 {
     base.OnDescriptorWrite(gatt, descriptor, status);
     System.Diagnostics.Debug.WriteLine("Descriptor written to: " + descriptor.Uuid + " get value: " + descriptor.GetValue() + " status: " + status);
     if (status == GattStatus.Success)
     {
         Bluetooth_CMD.poll_queue();
     }
     else
     {
         System.Diagnostics.Debug.WriteLine("Got gatt descriptor write failure: " + status);
         Bluetooth_CMD.retry_last_command((int)status);
     }
 }
        public override void OnCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
        {
            base.OnCharacteristicChanged(gatt, characteristic);

            if (characteristic.Uuid.Equals(GattMapper.UuidForType <GlucoseMeasurement>()))
            {
                try
                {
                    Consumer.Consume(characteristic);

                    Bluetooth_CMD.poll_queue();
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
        public override void OnServicesDiscovered(BluetoothGatt gatt, GattStatus status)
        {
            base.OnServicesDiscovered(gatt, status);
            if (status == GattStatus.Success)
            {
                if (!Queue.Any())
                {
                    System.Diagnostics.Debug.WriteLine("Requesting data from meter");

                    Bluetooth_CMD.read(DEVICE_INFO_SERVICE, MANUFACTURER_NAME, "get device manufacturer");
                    //Bluetooth_CMD.read(CURRENT_TIME_SERVICE, TIME_CHARACTERISTIC, "get device time");

                    Bluetooth_CMD.notify(GLUCOSE_SERVICE, GLUCOSE_CHARACTERISTIC, "notify new glucose record");
                    Bluetooth_CMD.enable_notification_value(GLUCOSE_SERVICE, GLUCOSE_CHARACTERISTIC,
                                                            "notify new glucose value");

                    Bluetooth_CMD.enable_notification_value(GLUCOSE_SERVICE, CONTEXT_CHARACTERISTIC,
                                                            "notify new context value");
                    Bluetooth_CMD.notify(GLUCOSE_SERVICE, CONTEXT_CHARACTERISTIC, "notify new glucose context");

                    Bluetooth_CMD.enable_indications(GLUCOSE_SERVICE, RECORDS_CHARACTERISTIC,
                                                     "readings indication request");
                    Bluetooth_CMD.notify(GLUCOSE_SERVICE, RECORDS_CHARACTERISTIC, "notify glucose record");
                    Bluetooth_CMD.write(GLUCOSE_SERVICE, RECORDS_CHARACTERISTIC,
                                        new[] { OPCODE_REPORT_RECORDS, ALL_RECORDS }, "request all readings");
                    Bluetooth_CMD.notify(GLUCOSE_SERVICE, GLUCOSE_CHARACTERISTIC,
                                         "notify new glucose record again"); // dummy

                    Bluetooth_CMD.poll_queue();
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("Queue is not empty so not scheduling anything.");
                }
            }
        }
        internal static void process_queue_entry(Bluetooth_CMD btc)
        {
            if (GlucoseGattCallback.mBluetoothGatt == null)
            {
                Debug.WriteLine("Bluetooth Gatt not initialized");
                return;
            }

            BluetoothGattService        service = null;
            BluetoothGattCharacteristic characteristic;

            if (btc.service != null)
            {
                service = GlucoseGattCallback.mBluetoothGatt.GetService(btc.service);
            }
            if ((service != null) || (btc.service == null))
            {
                if ((service != null) && (btc.characteristic != null))
                {
                    characteristic = service.GetCharacteristic(btc.characteristic);
                }
                else
                {
                    characteristic = null;
                }
                if (characteristic != null)
                {
                    switch (btc.cmd)
                    {
                    case "W":
                        characteristic.SetValue(btc.data);
                        if ((characteristic.GetValue().Length > 1))
                        {
                            GlucoseGattCallback.AwaitingAck  = true;
                            GlucoseGattCallback.AwaitingData = true;
                            if (GlucoseGattCallback.Debug)
                            {
                                Debug.WriteLine("Setting await ack blocker 1");
                            }
                        }


                        Task.Run(() =>
                        {
                            try
                            {
                                if (!GlucoseGattCallback.mBluetoothGatt.WriteCharacteristic(characteristic))
                                {
                                    Debug.WriteLine("Failed in write characteristic");
                                    System.Threading.Thread.Sleep(150);
                                    if (!GlucoseGattCallback.mBluetoothGatt.WriteCharacteristic(characteristic))
                                    {
                                        Debug.WriteLine("Failed second time in write charactersitic");
                                    }
                                }
                            }
                            catch (NullPointerException e)
                            {
                                Debug.WriteLine(
                                    "Got null pointer exception writing characteristic - probably temporary failure");
                            }
                        });



                        break;

                    case "R":
                        GlucoseGattCallback.mBluetoothGatt.ReadCharacteristic(characteristic);
                        break;

                    case "N":
                        GlucoseGattCallback.mBluetoothGatt.SetCharacteristicNotification(characteristic, true);
                        System.Threading.Thread.Sleep(100);
                        poll_queue();     // we don't get an event from this
                        break;

                    case "U":
                        GlucoseGattCallback.mBluetoothGatt.SetCharacteristicNotification(characteristic, false);
                        break;

                    case "D":
                        BluetoothGattDescriptor descriptor = characteristic.GetDescriptor(
                            GattMapper.UuidForType <ClientCharacteristicConfiguration>());
                        descriptor.SetValue(btc.data);
                        GlucoseGattCallback.mBluetoothGatt.WriteDescriptor(descriptor);
                        break;

                    default:
                        Debug.WriteLine("Unknown queue cmd: " + btc.cmd);
                        break;
                    } // end switch
                }
                else
                {
                    Debug.WriteLine("Characteristic was null!!!!");
                }
            }
            else
            {
                Debug.WriteLine("Got null service error on: " + btc.service);
            }
        }
        private static Bluetooth_CMD gen_item(string cmd, UUID service, UUID characteristic, byte[] data, string note)
        {
            Bluetooth_CMD btc = new Bluetooth_CMD(cmd, service, characteristic, data, note);

            return(btc);
        }
 public override void OnCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, GattStatus status)
 {
     base.OnCharacteristicRead(gatt, characteristic, status);
     System.Diagnostics.Debug.WriteLine($"Read Action for Characteristic with UUID of {characteristic.Uuid}");
     Bluetooth_CMD.poll_queue();
 }