Xamarin displayalert not showing - c#

I have xamarin form application and i connected it signalr not running my void. I searched on internet but I can't find anything about this. And this is my code
Myhub.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client;
namespace PharmClient
{
class MyHub
{
string url = "https://webapplication11-co5.conveyor.cloud/";
HubConnection Connection;
IHubProxy ProxyOFServer;
public delegate void Error();
public delegate void MessageRecieved(string _data);
public event Error CoonectionError;
public event MessageRecieved OndataRecieved;
public delegate void Completed();
public event Completed OnCompleted;
public void Connect()
{
Connection = new HubConnection(url);
ProxyOFServer = Connection.CreateHubProxy("MuHub");
Start().ContinueWith(task => { if (task.IsFaulted) { CoonectionError?.Invoke(); } else { OnCompleted?.Invoke(); } });
}
public Task Start()
{
return Connection.Start();
}
public void SendData(string data)
{
ProxyOFServer.Invoke<string>("SendMessage", data);
}
public void Recive( )
{
ProxyOFServer.On<string>("Sentdata", data => { OndataRecieved?.Invoke(data); });
}
}
}
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using System.Threading;
namespace PharmClient
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
MyHub ConnectServer = new MyHub();
public MainPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
ConnectServer.OnCompleted += ConnectServer_OnCompleted;
ConnectServer.CoonectionError += ConnectServer_CoonectionError;
ConnectServer.Connect();
}
private void ConnectServer_OnCompleted()
{
DisplayAlert("Connected", "Good", "O");
}
private void ConnectServer_CoonectionError()
{
DisplayAlert("Failed", "Bad", "Ok");
}
private void SerchDrug_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new SearchDrug());
}
}
}
When connection failed ConnectionError event run but Connection will be successfully OnCompleted event won't run. I am student. This is part of group work. What is problem my code any Help. I can't found anything. Thanks for attention

As your title suggest, you have an issue with displaying a dialog box.
Try going through the documentation (here) once for complete understanding, you have to await the process of displaying DisplayAlert.
Add await & async to your methods.
Try this -
private async void ConnectServer_OnCompleted()
{
await DisplayAlert("Connected", "Good", "O");
}
private async void ConnectServer_CoonectionError()
{
await DisplayAlert("Failed", "Bad", "Ok");
}
If you have some issues regarding, let me know.

You should await connection not fire and forget. Example:
private HubConnection connection;
private IHubProxy proxy;
public event EventHandler<ChatMessageObject> OnMessageReceived;
public async Task Connect()
{
try
{
await connection.Start();
await proxy.Invoke("Connect"); // example method in your backend
proxy.On("messageReceived", (int userId, string name, string message, DateTime messageDateTime) => OnMessageReceived(this, new ChatMessageObject
{
FromUserId = userId,
UserName = name,
MessageText = message,
MessageDateTime = messageDateTime
}));
}
catch (Exception ex)
{
//handle exceptions
}
}

Related

Xamarin forms - can't scan BLE devices

I new in Xamarin forms and C#.
I am trying to scan BLE device using the native Xamarin forms API, the code attached. I am using the Xiomi note 5 running android 9.
using Android.Bluetooth;
using Android.Bluetooth.LE;
using Android.Runtime;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
namespace bletest
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public class MyScanCallback : ScanCallback
{
public override void OnBatchScanResults(IList<ScanResult> results)
{
base.OnBatchScanResults(results);
}
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result)
{
base.OnScanResult(callbackType, result);
}
public override void OnScanFailed([GeneratedEnumAttribute] ScanFailure errorCode)
{
base.OnScanFailed(errorCode);
}
}
public class newbtle
{
private readonly BluetoothAdapter _ba;
private readonly BluetoothLeScanner _sc;
private readonly MyScanCallback _scCb;
public newbtle()
{
_ba = BluetoothAdapter.DefaultAdapter;
_sc = _ba.BluetoothLeScanner;
_scCb = new MyScanCallback();
}
public void BleScan()
{
if (_ba.Enable() == true)
{
_sc.StartScan(_scCb);
}
}
public void BleScanStop()
{
_sc.StopScan(_scCb);
_sc.FlushPendingScanResults(_scCb);
_ba.Disable();
}
public string GetScanMode()
{
return _ba.ScanMode.ToString();
}
public string GetStateMode()
{
return _ba.State.ToString();
}
}
public partial class MainPage : ContentPage
{
newbtle bt = new newbtle();
public MainPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
bt.BleScan();
}
private void Button_Clicked_1(object sender, EventArgs e)
{
bt.BleScanStop();
}
}
}
When a call is made to bt.BleScan no call back is called, when the bt.BleScan called in the second time without turning the scanner off the OnScanFailed is called with 'already active error'.
When I run the BLE explorer utility on the same mobile in the same environment it scan few BLE devices.
Any suggestion what can be the problem?
Thanks

Is it possible to show DisplayAlert on startup (Xamarin.Forms)

In my mobile application (xamarin forms), I'm getting data from internet so it needs internet connection. Since I have a dictionary which I initialize in App.xaml.cs and I use data from internet, I need to check for internet connection. I have seen this question where OP asks for something similar, but the answer doesn't work for me since I need to check for internet connection whenever app launches, not after MainPage is launched. For example, Clash of Clans. Whenever the app launches, the app checks for internet connection and if there's no connection, it displays a alert to user repetitively until there's a connection.
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Collections.Generic;
using HtmlAgilityPack;
using System.Text.RegularExpressions;
using System;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Multi
{
public partial class App : Application
{
static GroupStage groupstage = new GroupStage();
public static HtmlWeb web = new HtmlWeb();
public static HtmlDocument doc = LoadUrlAndTestConnection();
//The reason why I have put a method is because I wanted to try if I can use try-catch to display alert, however this didn't work.
public static HtmlDocument LoadUrlAndTestConnection()
{
bool con = true;
while (con)
{
try
{
doc = web.Load(someURL);
}
catch (Exception ex)
{
var sth = new ErrorPage();
sth.InternetErrorDisplay();
con = true;
continue;
}
con = false;
}
return docSK;
}
public static Dictionary<string, Country> _countries = new Dictionary<string, Country>
{
["Australia"] = new Country(1, "Australia", false, "AU", "ausFlag.png", 3, groupstage, GetScore("Australia", 3)),
public static string[] GetScore(string name, int GroupID)
{
//Gets the score data from internet
}
public App()
{
InitializeComponent();
TwitchClass.MainAsync().Wait();
MainPage = new OpeningPage();
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
//GetScore method requires internet connection as it gets the score data from internet.
and the InternetErrorDisplay method is,
public void InternetErrorDisplay() => DisplayAlert("Connection Error", "Could not detect internet connection. This application requires access to internet.", "Retry");
Is it possible to have this behaviour in xamarin forms app? How can I achieve it?
Yes, why should it not be possible?
Here is an example which uses async/await
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Threading.Tasks;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace LoadingSample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
//MainPage = new MainPage();
}
protected override async void OnStart()
{
// shows Loading...
MainPage = new LoadPage();
await Task.Yield();
// Handle when your app starts
// Just a simulation with 10 tries to get the data
for (int i = 0; i < 10; i++)
{
await Task.Delay(500);
// await internet_service.InitializeAsync();
await MainPage.DisplayAlert(
"Connection Error",
"Unable to connect with the server. Check your internet connection and try again",
"Try again");
}
await Task.Delay(2000);
// after loading is complete show the real page
MainPage = new MainPage();
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}

UWP Bluetooth Low Energy Application Disconnects Early

So I am designing an application for windows laptops to connect to a custom designed pressure sensor. The application pairs to the device and then receives notifications from the device every 10 ms. Then for some reason the communication stops. I know it is a problem with my application and not with the device, because when I connect to my phone, I do not have this problem.
Here is the main page where I create the devicewatcher and discover the device:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Bluetooth;
using Windows.Devices.Enumeration;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace BLEInterfaceTest
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private DeviceWatcher deviceWatcher;
private ObservableCollection<DeviceInformation> deviceList = new ObservableCollection<DeviceInformation>();
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.DataContext = deviceList;
deviceListView.ItemsSource = deviceList;
deviceWatcher = DeviceInformation.CreateWatcher(
"System.ItemNameDisplay:~~\"Button\"",
new string[] {
"System.Devices.Aep.DeviceAddress",
"System.Devices.Aep.IsConnected" },
DeviceInformationKind.AssociationEndpoint);
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Removed += DeviceWatcher_Removed;
deviceWatcher.Start();
base.OnNavigatedTo(e);
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Collapsed;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
deviceWatcher.Stop();
base.OnNavigatedFrom(e);
}
private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
var toRemove = (from a in deviceList where a.Id == args.Id select a).FirstOrDefault();
if (toRemove != null)
{
await this.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { deviceList.Remove(toRemove); });
}
}
private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
await this.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() => { deviceList.Add(args); });
}
private void deviceListView_ItemClick(object sender, ItemClickEventArgs e)
{
this.Frame.Navigate(typeof(DevicePage), e.ClickedItem);
}
}
}'
This next code is the page where the pressure sensor is connected to and where data is read from the device.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Popups;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Bluetooth;
using Windows.Devices.Enumeration;
using Windows.Storage.Pickers;
using Windows.Storage;
using Windows.Storage.Streams;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace BLEInterfaceTest
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class DevicePage : Page
{
private DeviceInformation device { get; set; }
private PressureSensor pSensor { get; set; }
public static DateTime startTime { get; set; }
public ObservableCollection<DataPoint> PressureData = new ObservableCollection<DataPoint>();
public static ObservableCollection<DataPoint> inbetween;
private static TextBox txtP;
private BluetoothLEDevice leDevice;
private DispatcherTimer timer = new DispatcherTimer();
private int packetNum = 0;
public DevicePage()
{
this.InitializeComponent();
SystemNavigationManager.GetForCurrentView().BackRequested += DevicePage_BackRequested;
txtP = txtValue1;
inbetween = PressureData;
}
public static void ChangeText(string text)
{
txtP.Text = text;
}
private async void InitializePressureSensor(GattDeviceService service)
{
pSensor = new PressureSensor(service, SensorUUIDs.PressureSensorUuid);
await pSensor.EnableNotifications();
btnStart.IsEnabled = true;
}
private async void StartRecievingData()
{
try
{
leDevice = await BluetoothLEDevice.FromIdAsync(device.Id);
string selector = "(System.DeviceInterface.Bluetooth.DeviceAddress:=\"" +
leDevice.BluetoothAddress.ToString("X") + "\")";
var services = await leDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached);
foreach (var service in services.Services)
{
if (service.Uuid.ToString() == SensorUUIDs.ButtonSensorServiceUuid)
{
InitializePressureSensor(service);
}
}
timer.Interval = new TimeSpan(0, 0, 0, 0, 1);
timer.Tick += Timer_Tick1;
startTime = DateTime.Now;
timer.Start();
}
catch (Exception ex)
{
var messageDialog = new MessageDialog("An error has occured Please try again. \n" + ex.Message, "Error!");
}
}
public async void UpdateAllData()
{
while (pSensor != null && pSensor.MorePacketsAvailable)
{
int[] values = await pSensor.GetPressure();
int packetNumber = values[0];
if (packetNumber > packetNum)
{
packetNum = packetNumber;
txtValue1.Text = Convert.ToString(values[1]);
txtValue2.Text = Convert.ToString(values[5]);
for (int i = 1; i < 5; i++)
{
PressureData.Add(new DataPoint(DateTime.Now - startTime, packetNumber, ((i-1)*2.5 + 10*packetNumber), values[i], values[i + 4]));
}
}
}
}
private void Timer_Tick1(object sender, object e)
{
UpdateAllData();
}
private async void PairToDevice()
{
if (device.Pairing.CanPair)
{
var customPairing = device.Pairing.Custom;
customPairing.PairingRequested += CustomPairing_PairingRequested;
var result = await customPairing.PairAsync(DevicePairingKinds.ConfirmOnly);
customPairing.PairingRequested -= CustomPairing_PairingRequested;
if ((result.Status == DevicePairingResultStatus.Paired) || (result.Status == DevicePairingResultStatus.AlreadyPaired))
{
/*while (device.Pairing.IsPaired == false)
{
device = await DeviceInformation.CreateFromIdAsync(device.Id);
}*/
StartRecievingData();
}
}
else if (device.Pairing.IsPaired)
{
StartRecievingData();
}
}
private void CustomPairing_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
args.Accept();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
btnSave.Content = "Save";
btnStop.IsEnabled = false;
btnStart.IsEnabled = false;
this.DataContext = PressureData;
device = (DeviceInformation)e.Parameter;
PairToDevice();
//StartRecievingData();
base.OnNavigatedTo(e);
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack)
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Visible;
}
}
private void DevicePage_BackRequested(object sender, BackRequestedEventArgs eventArgs)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
return;
}
// Navigate back if possible, and if the event has already been handled
if (rootFrame.CanGoBack && eventArgs.Handled ==false)
{
eventArgs.Handled = true;
rootFrame.GoBack();
}
}
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
timer.Stop();
var picker = new FileSavePicker();
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
picker.FileTypeChoices.Add("CSV", new List<string>() { ".csv" });
StorageFile file = await picker.PickSaveFileAsync();
if (file != null)
{
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
using (IOutputStream outputStream = stream.GetOutputStreamAt(0))
{
using (var writer = new DataWriter(outputStream))
{
foreach (DataPoint p in PressureData)
{
string text = p.TimeStamp.ToString() + "," + p.PacketNumber.ToString() + "," + p.InternalTimestamp.ToString() + "," + p.PressureValue1.ToString() + "," + p.PressureValue2.ToString() + "\n";
writer.WriteString(text);
}
await writer.StoreAsync();
await writer.FlushAsync();
}
}
stream.Dispose();
}
}
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
if (pSensor != null)
{
btnStop.IsEnabled = true;
btnStart.IsEnabled = false;
startTime = DateTime.Now;
if (pSensor != null)
{
await pSensor.BeginCollecting();
}
}
}
private async void btnStop_Click(object sender, RoutedEventArgs e)
{
btnStart.IsEnabled = true;
btnStop.IsEnabled = false;
if (pSensor != null)
{
await pSensor.StopCollecting();
}
}
}
}
Here is where I define my SensorBase and PressureSensor class that handles the device connection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Storage.Streams;
using Windows.Devices.Enumeration;
namespace BLEInterfaceTest
{
public static class SensorUUIDs
{
private static readonly string _packetUuid = "0000a043-0000-1000-8000-00805f9b34fb";
private static readonly string _buttonSensorServiceUuid = "0000a042-0000-1000-8000-00805f9b34fb";
private static readonly string _sensorStateUuid = "0000a044-0000-1000-8000-00805f9b34fb";
public static string PressureSensorUuid
{
get { return _packetUuid; }
}
public static string ButtonSensorServiceUuid
{
get { return _buttonSensorServiceUuid; }
}
public static string SensorStateUuid
{
get { return _sensorStateUuid; }
}
}
public class SensorBase : IDisposable
{
protected GattDeviceService deviceService;
protected string sensorDataUuid;
protected Queue<byte[]> fifoBuffer;
protected bool isNotificationSupported = false;
public bool newData = false;
private GattCharacteristic dataCharacteristic;
public SensorBase(GattDeviceService dataService, string sensorDataUuid)
{
this.deviceService = dataService;
this.sensorDataUuid = sensorDataUuid;
fifoBuffer = new Queue<byte[]>(20);
}
public bool MorePacketsAvailable
{
get
{
if (fifoBuffer.Count > 0)
{
return true;
}
else
{
return false;
}
}
}
public virtual async Task EnableNotifications()
{
GattCharacteristicsResult result = await deviceService.GetCharacteristicsAsync();
foreach (var test in result.Characteristics)
{
string t = test.Uuid.ToString();
}
isNotificationSupported = true;
dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
new Guid(sensorDataUuid))).Characteristics[0];
dataCharacteristic.ValueChanged += dataCharacteristic_ValueChanged;
GattCommunicationStatus status = await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
var currentDescriptorValue = await dataCharacteristic.ReadClientCharacteristicConfigurationDescriptorAsync();
if (currentDescriptorValue.Status != GattCommunicationStatus.Success
|| currentDescriptorValue.ClientCharacteristicConfigurationDescriptor != GattClientCharacteristicConfigurationDescriptorValue.Notify)
{
GattCommunicationStatus status2 = await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
}
}
public virtual async Task DisableNotifications()
{
newData = false;
isNotificationSupported = false;
dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
new Guid(sensorDataUuid))).Characteristics[0];
dataCharacteristic.ValueChanged -= dataCharacteristic_ValueChanged;
GattCommunicationStatus status = await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.None);
}
protected async Task<byte[]> ReadValue()
{
if (!isNotificationSupported)
{
if (dataCharacteristic == null)
{
dataCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
new Guid(sensorDataUuid))).Characteristics[0];
}
GattReadResult readResult = await dataCharacteristic.ReadValueAsync();
byte[] data = new byte[readResult.Value.Length];
DataReader.FromBuffer(readResult.Value).ReadBytes(data);
fifoBuffer.Enqueue(data);
}
return fifoBuffer.Dequeue();
}
protected async Task WriteByteArray(string characteristicUuid, byte[] value)
{
GattCharacteristic writeCharacteristic = (await deviceService.GetCharacteristicsForUuidAsync(
new Guid(characteristicUuid))).Characteristics[0];
var writer = new DataWriter();
writer.WriteBytes(value);
var res = await writeCharacteristic.WriteValueAsync(writer.DetachBuffer(), GattWriteOption.WriteWithoutResponse);
}
private void dataCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
byte[] data = new byte[args.CharacteristicValue.Length];
DataReader.FromBuffer(args.CharacteristicValue).ReadBytes(data);
fifoBuffer.Enqueue(data);
newData = true;
}
public async void Dispose()
{
await DisableNotifications();
}
}
public class PressureSensor: SensorBase
{
public PressureSensor(GattDeviceService dataService, string sensorDataUuid)
: base(dataService, sensorDataUuid)
{
}
public async Task BeginCollecting()
{
await WriteByteArray(SensorUUIDs.SensorStateUuid, new byte[] { 0x01 });
}
public async Task<int[]> GetPressure()
{
byte[] data = await ReadValue();
if (data != null)
{
int[] values = new int[9];
values[0] = (int)BitConverter.ToInt32(data, 0);
for (int i = 1; i < values.Length; i++)
{
values[i] = (int)BitConverter.ToInt16(data, 2 * i + 2);
}
return values;
}
else
{
return new int[] { 0 };
}
}
public async Task StopCollecting()
{
await WriteByteArray(SensorUUIDs.SensorStateUuid, new byte[] { 0x00 });
}
}
}
Here is the DataPoint Class that I use to organize the data received from the pressure sensor:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace BLEInterfaceTest
{
public class DataPoint : INotifyPropertyChanged
{
private TimeSpan _timestamp;
private int _packetNumber;
private double _internalTimestamp;
private int _pressure1;
private int _pressure2;
public event PropertyChangedEventHandler PropertyChanged;
public TimeSpan TimeStamp
{
get { return _timestamp; }
set
{
_timestamp = value;
this.NotifyPropertyChanged();
}
}
public int PacketNumber
{
get { return _packetNumber; }
set
{
_packetNumber = value;
this.NotifyPropertyChanged();
}
}
public double InternalTimestamp
{
get { return _internalTimestamp; }
set
{
_internalTimestamp = value;
this.NotifyPropertyChanged();
}
}
public int PressureValue1
{
get { return _pressure1; }
set
{
_pressure1 = value;
this.NotifyPropertyChanged();
}
}
public int PressureValue2
{
get { return _pressure2; }
set
{
_pressure2 = value;
this.NotifyPropertyChanged();
}
}
public DataPoint(TimeSpan time,int packetNumber, double internalTimestamp, int pressure1, int pressure2)
{
_timestamp = time;
_packetNumber = packetNumber;
_internalTimestamp = internalTimestamp;
_pressure1 = pressure1;
_pressure2 = pressure2;
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (!string.IsNullOrEmpty(propertyName))
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
I have researched this extensively, and all I could find was help on how to initiate a disconnection. I have the opposite problem. One page I found stated that the problem might be caused by the device not properly storing the bonding state, but I have checked that and I did initialize the device to save the bonding state.
Interestingly if I do not pair the device to the computer before trying to read information from it then I do not have the problem. The connection never randomly stops. But when I do this, the computer does not receive every packet of data sent from the sensor device. It will receive one or two packets and then skip five or six packets. If I pair the device then I will receive every packet but the connection will randomly cut off.
So my question is two fold, I guess. How do I stop the connection from cutting off when the device is paired? Or alternatively, is there a way to allow the application to receive every packet of data when it is not paired?
UPDATE
I realized I should include more information on my sensor peripheral in case the error is in that code. I am currently designing a rapid prototyping of this sensor before I move on to designing the embedded version. To do this, I am using the BLE Nano 1 from RedBearLabs as a user friendly prototype. I am programing this device with the online MBED compiler. I have included the nRF51822 and BLE_API libraries to handle the bluetooth low energy communication.
UPDATE 2
So after more research into what is causing the problem, I have found that the disconnection occurs when a connection interval and a generation 2 garbage collection occur at the same time. In UWP the garbage collector can pause the UI Thread for generation 2 collections. (see here)
My thought is that if the thread is paused at the beginning of a connection interval, then the central is not able to initiate the connection with the peripheral and the peripheral therefore thinks the client is no longer listening (see more about how BLE connections work).
I discovered this by finding out exactly what is necessary to get the connection back once it has randomly stopped. I started with the entire connection process and reduced it down to this:
public async Task ReconnectDevice()
{
GattCommunicationStatus status = await dataCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
GattClientCharacteristicConfigurationDescriptorValue.Notify);
await WriteByteArray(SensorUUIDs.SensorStateUuid, new byte[] { 0x01 });
}
Because my BluetoothLEDevice, GattService, and GattCharacteristic objects are not disposed, all I need to do is resubscribe to notifications and write a 1 to the device so that it begins collecting data again.
I have reduced my memory allocations in my application significantly since discovering this, and the time for a gen2 collection has decreased to an average of 5 ms. Also, the amount of time before the connection disconnects has increased to around 4-5 sec.
UWP has a GattCharacteristicNotificationTrigger for receiving notifications in a BackgroundTask, but I have never had much success at incorporating background tasks in UWP.
I think I will try next to incorporate the windows.devices into a WPF application where I think I will have a better chance at getting it working.
So, after a while of trying different ideas I have finally stumbled across a solution to my problem. I had to make 2 changes:
Used the unpaired connection instead of the paired connection. This solved the problem of the connection dropping suddenly.
Increased the connection interval to 40 ms. For some reason when I did this, I received all of the data and no longer had any problems. Anything below 40 ms causes information to be lost when communicating to a Windows device (I had to make this change on the C code running on my sensors.)
I have used the devices for about 2 months now after making this change and have had no problems at all.
I seems to me that these problems are related to the BluetoothCacheMode Enum.
This indicates whether certain Bluetooth API methods should operate on values cached in the system or
retrieve those values from the Bluetooth device.
Using BluetoothCacheMode.Uncached attribute allows the service to update the attributes when needed.
If the device is paired then the BluetoothCacheMode is not needed(I think BluetoothCacheMode.Cached is default).
In your code the line:
var services = await leDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached);
Can be the cause of the connection lost if paired.
GetGattServicesAsync(), GetCharacteristicsAsync() and ReadValueAsync()
must have the attribute BluetoothCacheMode.Uncached when not paired, when paired default or BluetoothCacheMode.Cached.
See https://msdn.microsoft.com/en-us/library/windows/apps/dn263758.aspx.

Why I can't recieved messages from Chat Server?

Why I can't recieved messages from Chat Server ?
I developed Chat Client in Visual Studio C# with mono for android.
I want to receive mesagens from Chat server they are sent but he Chat Client may be receiving them and i can not seem to show in Text1.Text
The Source Code Chat Client for receiving messages:
//Criado por EcoDuty, Frederico Vaz
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
//
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
namespace ChatClient_Android
{
[Activity(Label = "ChatClient_Android", MainLauncher = true, Icon = "#drawable/icon")]
public class MainChat : Activity
{
public delegate void OnRecievedMessage(string message);
public MainChat form;
const int WM_VSCROLL = 0x115;
const int SB_BOTTOM = 7;
TextView text1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button ligar = FindViewById<Button>(Resource.Id.btligar);
text1 = FindViewById<TextView>(Resource.Id.text1);
//Conexão com o servidor
ligar.Click += delegate
{
Connect();
ligar.Enabled = false;
};
}
//Função Actualizar a Caixa de Entrada de Mensagens
private void UpdateTextbox(string text)
{
text1.Text += "\r\n";
text1.Text += text;
}
//Recieved Mesages
public void RecievedMessage(string message)
{
UpdateTextbox(message);
}
//TCP Connection
public StreamWriter Outgoing;
private StreamReader Incoming;
private TcpClient Connection;
private Thread Messages;
private IPAddress IP;
//public string host;
//public string nick;
//MainChat m_ParentForm;
bool isConnected;
//Função Conectar
public void Connect()
{
try
{
IP = IPAddress.Parse("10.0.2.2");
Connection = new TcpClient();
Connection.Connect(IP, 1986);
Outgoing = new StreamWriter(Connection.GetStream());
Outgoing.WriteLine("EcoDuty");
Outgoing.Flush();
//m_ParentForm.Vis(true);
Messages = new Thread(new ThreadStart(this.Communication));
Messages.Start();
}
catch (Exception e) { Disconnected(e.Message); }
}
private void Communication()
{
Incoming = new StreamReader(Connection.GetStream());
string check = Incoming.ReadLine();
if (check[0] == '1')
{
//Vis(true);
isConnected = true;
}
else
{
string Reason = "Disconnected: ";
Reason += check.Substring(2, check.Length - 2);
Disconnected(Reason);
return;
}
while (isConnected == true)
{
try
{
ServerMessage(Incoming.ReadLine());
}
catch (Exception e)
{
if (isConnected == true)
{
Disconnected("Connection to server lost");
Console.WriteLine("Connection Lost: " + e.ToString());
}
break;
}
}
}
private void ServerMessage(string message)
{
try
{
RecievedMessage(message);
}
catch { }
}
public void CloseConnection()
{
isConnected = false;
Incoming.Close();
Outgoing.Close();
Connection.Close();
Messages.Abort();
}
public void SendMessage(string message)
{
Outgoing.WriteLine(message);
Outgoing.Flush();
}
}
}
You seem to be trying to update the text from a non UI thread (if you follow the calls stack you see that the method is triggered from a dedicated thread you spawn):
private void UpdateTextbox(string text)
{
text1.Text += "\r\n";
text1.Text += text;
}
Instead use RunOnUiThread() to schedule the text change to run on the UI thread:
private void UpdateTextbox(string text)
{
RunOnUiThread(() =>
{
text1.Text += "\r\n";
text1.Text += text;
});
}
Also you should get rid of the empty exception catching you do along the way - this most likely masked the problem.
Also always check the catlog for exceptions they usually are a good indicator.

How I do a function C# for i can receive messages from Server Chat in PC and Chat Client in Android device?

In my C # application Chat Client I don`t not know how to do a function to receive messages from the Chat Server in C # and presents them in a TextView Chat Client
I'm programming in Visual Studio in C # using Mono for Android.
The question is... How I do a function for i can receive messages from Chat Server in PC and Chat Client in Android device? When i use Chat Client in windows 7 works good but when i make for a android device i can`t receive mensages from Server Chat to Chat Client.
I think the problem as in public void RecievedMessage and private void UpdateTextbox.
Sorry, my bad english.
Thanks your atention.
The Source Code, Chat Client:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Widget.EditText;
using Android.Widget.Button;
using Android.Widget.TextView;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
namespace ChatClient_Android
{
[Activity(Label = "ChatClient_Android", MainLauncher = true, Icon = "#drawable/icon")]
public class MainChat : Activity
{
public delegate void OnRecievedMessage(string message);
public MainChat form;
const int WM_VSCROLL = 0x115;
const int SB_BOTTOM = 7;
string msgrecebida;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button enviar = FindViewById<Button>(Resource.Id.btenviar);
Button ligar = FindViewById<Button>(Resource.Id.btligar);
TextView text1 = FindViewById<TextView>(Resource.Id.text1);
EditText text2 = FindViewById<EditText>(Resource.Id.text2);
//Conexão com o servidor
ligar.Click += delegate
{
Connect();
ligar.Enabled = false;
text1.Text = "Connected";
};
enviar.Click += delegate
{
if (text2.Text != "")
{
if (text2.Text.ToLower().StartsWith("/"))
{
text2.Text = "";
}
else
{
SendMessage("MSG :" + text2.Text);
text2.Text = "";
}
}
};
}
private void Invoke(OnRecievedMessage onRecievedMessage, string message)
{
throw new NotImplementedException();
}
public bool InvokeRequired { get; set; }
public void RecievedMessage(string message)
{
if (InvokeRequired)
{
this.Invoke(new OnRecievedMessage(RecievedMessage), message);
}
else
{
UpdateTextbox(message);
}
}
private void UpdateTextbox(string text)
{
msgrecebida += "\r\n";
msgrecebida += text;
}
//Interligações Classes MainChat & Connection
public void Disconnected(string reason)
{
form.Disconnected(reason);
}
//TCP Connection
public StreamWriter Outgoing;
private StreamReader Incoming;
private TcpClient Connection;
private Thread Messages;
private IPAddress IP;
//public string host;
//public string nick;
//MainChat m_ParentForm;
bool isConnected;
//Função Conectar
public void Connect()
{
try
{
IP = IPAddress.Parse("10.0.2.2");
Connection = new TcpClient();
Connection.Connect(IP, 1986);
Outgoing = new StreamWriter(Connection.GetStream());
Outgoing.WriteLine("EcoDuty");
Outgoing.Flush();
//m_ParentForm.Vis(true);
Messages = new Thread(new ThreadStart(this.Communication));
Messages.Start();
}
catch (Exception e) { Disconnected(e.Message); }
}
private void Communication()
{
Incoming = new StreamReader(Connection.GetStream());
string check = Incoming.ReadLine();
if (check[0] == '1')
{
//m_ParentForm.Vis(true);
isConnected = true;
}
else
{
string Reason = "Disconnected: ";
Reason += check.Substring(2, check.Length - 2);
Disconnected(Reason);
return;
}
while (isConnected == true)
{
try
{
ServerMessage(Incoming.ReadLine());
}
catch (Exception e)
{
if (isConnected == true)
{
Disconnected("Connection to server lost");
Console.WriteLine("Connection Lost: " + e.ToString());
}
break;
}
}
}
private void ServerMessage(string message)
{
try
{
RecievedMessage(message);
}
catch { }
}
public void CloseConnection()
{
isConnected = false;
Incoming.Close();
Outgoing.Close();
Connection.Close();
Messages.Abort();
}
public void SendMessage(string message)
{
Outgoing.WriteLine(message);
Outgoing.Flush();
}
}
}
It looks to me like (one) problem is that you are trying to access text1 as if it is a field or property when it is a local variable declared in onCreate. You either need to push text1 up a level in scope, or grab a new reference to it in RecievedMessage. This is not a problem with Android, specifically, but is a difference with how the code is set up with Mono for Android.
Typically, when working with Winforms in Windows, you'll be working in a partial class with all your controls defined in the designer.cs file as fields. But in your Mono code, you are binding to TextViews instead, and in your OnCreate instead of at instance scope. When you copy/pasted your code, you likely didn't account for that difference.
As an aside, I highly doubt that the user32.dll function you are importing is going to do anything useful on Android. Unless the Mono folks are doing something magical, the win32 API will not be available on Android.

Categories