I'm trying to write an app that reads all MAC addresses around on Windows 10 IoT. These lines of code is returning all paired devices even if they aren't turn on.
var selector = BluetoothDevice.GetDeviceSelector();
var devices = await DeviceInformation.FindAllAsync(selector);
listBox.Items.Add(devices.Count);
foreach (var device in devices)
{
listBox.Items.Add(device.Id);
}
And I also found this line of code
await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
This returning null though. Is there any way to scan for all MAC addresses in a Windows 10 universal app?
You are very close to finding the answer of your question. You might try getting a BluetoothDevice instance from the DeviceId property. You will then be able to get all the specific Bluetooth information including the Bluetooth address
var selector = BluetoothDevice.GetDeviceSelector();
var devices = await DeviceInformation.FindAllAsync(selector);
foreach (var device in devices)
{
var bluetoothDevice = await BluetoothDevice.FromIdAsync(device.Id);
if (bluetoothDevice != null)
{
Debug.WriteLine(bluetoothDevice.BluetoothAddress);
}
Debug.WriteLine(device.Id);
foreach(var property in device.Properties)
{
Debug.WriteLine(" " + property.Key + " " + property.Value);
}
}
There is a new approach using BluetoothLEAdvertisementWatcher to scan for all Bluetooth LE device around.
Here is a piece of code I use in my project:
var advertisementWatcher = new BluetoothLEAdvertisementWatcher()
{
SignalStrengthFilter.InRangeThresholdInDBm = -100,
SignalStrengthFilter.OutOfRangeThresholdInDBm = -102,
SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000)
};
advertisementWatcher.Received += AdvertisementWatcher_Received;
advertisementWatcher.Stopped += AdvertisementWatcher_Stopped;
advertisementWatcher.Start();
and later
advertisementWatcher.Stop();
advertisementWatcher.Received -= AdvertisementWatcher_Received;
advertisementWatcher.Stopped -= AdvertisementWatcher_Stopped;
private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
//MessAgeChanged(MsgType.NotifyTxt, "FR_NAME:"+ eventArgs.Advertisement.LocalName + "BT_ADDR: " + eventArgs.BluetoothAddress);
string sDevicename = setup.Default.BLEName.Text;
BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress).Completed = async (asyncInfo, asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Completed)
{
if (asyncInfo.GetResults() == null)
{
if (!FailMsg)
{
MessAgeChanged(MsgType.NotifyTxt, "None");
}
}
else
{
BluetoothLEDevice currentDevice = asyncInfo.GetResults();
Boolean contain = false;
foreach (BluetoothLEDevice device in DeviceList.ToArray())/
{
if (device.DeviceId == currentDevice.DeviceId)
{
contain = true;
}
}
if (!contain)
{
byte[] _Bytes1 = BitConverter.GetBytes(currentDevice.BluetoothAddress);
Array.Reverse(_Bytes1);
// The received signal strength indicator (RSSI)
double rssi = eventArgs.RawSignalStrengthInDBm;
DeviceList.Add(currentDevice);
MessAgeChanged(MsgType.NotifyTxt, currentDevice.Name + " " + BitConverter.ToString(_Bytes1, 2, 6).Replace('-', ':').ToLower() + " " + rssi);
DeviceWatcherChanged(MsgType.BleDevice, currentDevice);
}
}
}
};
}
Related
I am trying to get IP address from android device using .NET MAUI. (Current android framework net6.0-android)
With the below code, I can get the IP with the first launch of the application. And it does not work with following launch of the application unless I reboot my phone.(Tested on Samsung S10+ Android 12)
private void GetIPAddressClicked(object sender, EventArgs e)
{
string interfaceDescription = string.Empty;
var result = new List<IPAddress>();
try
{
var upAndNotLoopbackNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback
&& n.OperationalStatus == OperationalStatus.Up);
foreach (var networkInterface in upAndNotLoopbackNetworkInterfaces)
{
var iPInterfaceProperties = networkInterface.GetIPProperties();
var unicastIpAddressInformation = iPInterfaceProperties.UnicastAddresses.FirstOrDefault(u => u.Address.AddressFamily == AddressFamily.InterNetwork);
if (unicastIpAddressInformation == null) continue;
result.Add(unicastIpAddressInformation.Address);
interfaceDescription += networkInterface.Description + "---";
}
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to find IP: {ex.Message}");
}
finally
{
string allIpInfo = string.Empty;
foreach (var item in result)
{
allIpInfo += item.ToString() + "---";
}
IPAddress.Text = allIpInfo;
InterfaceName.Text = interfaceDescription;
}
When it works,
interfaceDescription = "------"
allIpInfo = "192.168.50.112---127.0.0.1---"
When it does not work,
interfaceDescription ---> rmnet_data0
allIpInfo ---> 192.0.0.2
I am not sure what is wrong here. How can I fix this? Or is there a better way to get the IP address?
Thanks.
I am trying to convert a working UWP app to a WPF one using .NET 6 with Target framework monikers.
I can scan BLE devices with no issues and connect to them, however I get an AccessDenied status at the next GetCharacteristicsAsync's call
I have checked characteristics properties and they all have the flag corresponding to the operation I am doing.
My OS version is 1943 and my target version is net6.0-windows10.0.19041.0
I have tried using BLuetoothCacheMode.Cached and Uncached: same result.
Edit:I have tried to call RequestAccessAsync and it does not seem to do anything. However this same method returns Allowed.
Here is a piece of code I use, it is inpired by the microsoft docs.
public async Task<byte[]> ReadAsync(string serviceUuid, string characteristicUuid)
{
using var bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(_device.DeviceId);
GattDeviceServicesResult result1 = await bluetoothLEDevice.GetGattServicesAsync(BluetoothCacheMode.Cached);
if (result1.Status == GattCommunicationStatus.Success)
{
foreach (var service in result1.Services)
{
if (service.Uuid.ToString() == serviceUuid)
{
GattCharacteristicsResult result2 = await service.GetCharacteristicsAsync(BluetoothCacheMode.Cached);
if (result2.Status == GattCommunicationStatus.Success)
{
foreach (var characteristic in result2.Characteristics)
{
if (characteristic.Uuid.ToString() == characteristicUuid)
{
var result = await characteristic.ReadValueAsync();
if (result.Status == GattCommunicationStatus.Success)
{
var reader = DataReader.FromBuffer(result.Value);
byte[] contents = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(contents);
return contents;
}
else
{
throw new Exception("Read: Cannot read characteristic: " + characteristic + " " + Enum.GetName(typeof(GattCommunicationStatus), result.Status));
}
}
}
}
else
{
// This exception is thrown
throw new Exception("Read: Cannot get characteristics for service: " + service.Uuid + " " + Enum.GetName(typeof(GattCommunicationStatus), result2.Status));
}
}
}
}
bluetoothLEDevice.Dispose();
return null;
}
In my Xamarin Forms application, I am trying to discover all devices on the local network that I am connected to. My approach is to first get the device IP address, and use to first 3 numbers to know what the gateway is (first number is always 192). And then, ping every address on that gateway. Here is my code:
public partial class MainPage : ContentPage
{
private List<Device> discoveredDevices = new List<Device>();
public MainPage()
{
InitializeComponent();
Ping_all();
}
private string GetCurrentIp()
{
IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
string ipAddress = string.Empty;
if (addresses != null && addresses[0] != null)
{
ipAddress = addresses[0].ToString();
}
else
{
ipAddress = null;
}
return ipAddress;
}
public void Ping_all()
{
string ip = GetCurrentIp();
if (ip != null)
{
//Extracting and pinging all other ip's.
string[] array = ip.Split('.');
string gateway = array[0] + "." + array[1] + "." + array[2];
for (int i = 2; i <= 255; i++)
{
string ping_var = $"{gateway}.{i}";
//time in milliseconds
Ping(ping_var, 4, 4000);
}
}
}
public void Ping(string host, int attempts, int timeout)
{
for (int i = 0; i < attempts; i++)
{
new Thread(delegate ()
{
try
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
ping.SendAsync(host, timeout, host);
// PingCompleted never gets called
}
catch(Exception e)
{
// Do nothing and let it try again until the attempts are exausted.
// Exceptions are thrown for normal ping failurs like address lookup
// failed. For this reason we are supressing errors.
}
}).Start();
}
}
private void PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
string hostname = GetHostName(ip);
string macaddres = GetMacAddress(ip);
var device = new Device()
{
Hostname = hostname,
IpAddress = ip,
MacAddress = macaddres
};
discoveredDevices.Add(device);
}
}
public string GetHostName(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
if (entry != null)
{
return entry.HostName;
}
}
catch (SocketException)
{
}
return null;
}
public string GetMacAddress(string ipAddress)
{
string macAddress = string.Empty;
System.Diagnostics.Process Process = new System.Diagnostics.Process();
Process.StartInfo.FileName = "arp";
Process.StartInfo.Arguments = "-a " + ipAddress;
Process.StartInfo.UseShellExecute = false;
Process.StartInfo.RedirectStandardOutput = true;
Process.StartInfo.CreateNoWindow = true;
Process.Start();
string strOutput = Process.StandardOutput.ReadToEnd();
string[] substrings = strOutput.Split('-');
if (substrings.Length >= 8)
{
macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2))
+ "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6]
+ "-" + substrings[7] + "-"
+ substrings[8].Substring(0, 2);
return macAddress;
}
else
{
return "OWN Machine";
}
}
}
I get to the part where I try to ping:
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
ping.PingCompleted += new PingCompletedEventHandler(PingCompleted);
ping.SendAsync(host, timeout, host);
But PingCompleted never gets called. No exception is thrown either. Any idea why? I'm running this on a physical Android device.
EDIT
PingCompleted started getting called for me now, not sure why it wasn't working before. But it now crashes in my GetMacAddress function on the line Process.Start(); because it can not find the resource.
I ended up using this really robust and easy to use library:
https://github.com/Yortw/RSSDP
It doesn't actually find all devices on the network, instead it uses SSDP (Simple Search Discovery Protocol) to quickly find all devices that are broadcasting a service with this protocol on the network. I filtered it to only scan devices running my app, which is what I actually needed. It takes only a second to discover my devices, which is much faster than pinging 255 addresses.
In the documentation you will see:
var deviceDefinition = new SsdpRootDevice()
{
CacheLifetime = TimeSpan.FromMinutes(30), //How long SSDP clients can cache this info.
Location = new Uri("http://mydevice/descriptiondocument.xml"), // Must point to the URL that serves your devices UPnP description document.
DeviceTypeNamespace = "my-namespace",
DeviceType = "MyCustomDevice",
FriendlyName = "Custom Device 1",
Manufacturer = "Me",
ModelName = "MyCustomDevice",
Uuid = GetPersistentUuid() // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc.
};
For the Location I set it as my device's IP. So that another device that discovers it can have the IP too. I don't think it's meant to be used this way, but it worked for me and I don't see why not.
I tested it on 2 physical Android devices.
How do I discover a paired Bluetooth device that's currently disconnected?
I've attempted the following code using the Windows 10 SDK:
using Windows.Devices.Enumeration;
using Windows.Devices.Bluetooth.Rfcomm;
var serviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
I've also tried the following:
using System;
using System.Diagnostics;
using System.Management;
public class Win32_UsbDriveWatcher
{
ManagementEventWatcher m_watcher;
public delegate void DeviceInsertedEventHandler(object sender, Win32_UsbDriveInsertEventArgs e);
public event DeviceInsertedEventHandler DeviceInserted;
public event EventHandler DeviceRemoved;
public void Start(int pollingInterval)
{
try
{
var queryString =
"SELECT * " +
" FROM __InstanceOperationEvent" +
" WITHIN " + pollingInterval +
" WHERE TargetInstance ISA 'Win32_PnPEntity'";
var processQuery = new EventQuery(queryString);
m_watcher = new ManagementEventWatcher(processQuery);
m_watcher.EventArrived += EventArrived;
m_watcher.Start();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
void EventArrived(object sender, EventArrivedEventArgs e)
{
var instance = ((PropertyData)(e.NewEvent.Properties["TargetInstance"]));
var obj = (ManagementBaseObject)instance.Value;
var args = new Win32_UsbDriveInsertEventArgs();
if ((string)obj["InterfaceType"] == "BLUETOOTH")
{
args.IsCreated = (obj.ClassPath.ClassName == "__InstanceCreationEvent");
args.DriveName = GetDriveLetterFromDisk((string)obj["Name"]);
if (args.IsCreated)
{
DeviceInserted?.Invoke(this, args);
}
else
{
DeviceRemoved?.Invoke(this, EventArgs.Empty);
}
}
}
static string GetDriveLetterFromDisk(string name)
{
name = name.Replace("\\", "\\\\");
var query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + name + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
var queryDrive = new ObjectQuery(query);
using (var searcherDrive = new ManagementObjectSearcher(queryDrive))
{
foreach (ManagementObject drive in searcherDrive.Get())
{
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" +
drive["DeviceID"] +
"'} WHERE AssocClass = Win32_LogicalDiskToPartition";
var queryPartition = new ObjectQuery(query);
using (var searcherPartition = new ManagementObjectSearcher(queryPartition))
{
foreach (ManagementObject disk in searcherPartition.Get())
{
return (string)disk["Name"];
}
}
}
return string.Empty;
}
}
}
public class Win32_UsbDriveInsertEventArgs : EventArgs
{
public bool IsCreated;
public string DriveName;
}
Regardless of the code snippets that I've attempted, I'm still unable to discover paired disconnected devices.
Any suggestions?
There are few way:
Use WM_DEVICE_CHANGE message to know when device connected and disconnected.
Once you found all paired devices query each for its services. Not available (disconnected) device reports error.
Try to connect to device's SDP service using DeviceIOControl (the best way).
I manage to enumerate my USB device as below. How can I add the enumerateDevices into DeviceWatcher?
I have referred to the following examples but still not getting any progress.
The watcher did trigger once during the startup subsequently any changes in my usb devices doesn't show anything.
[How to get notifications if devices are added, removed, or changed (XAML)][1]
[Device Enumeration Samples][2] Any idea how to constantly monitoring the changes on my USB port to prompt if any of the USB device has been removed or connected?
private void StartWatcher()
{
usbStorageWatcher = DeviceInformation.CreateWatcher(DeviceClass.PortableStorageDevice);
audioCaptureWatcher = DeviceInformation.CreateWatcher(DeviceClass.AudioCapture);
audioRenderWatcher = DeviceInformation.CreateWatcher(DeviceClass.AudioRender);
usbStorageWatcherAdded = new TypedEventHandler<DeviceWatcher, DeviceInformation>(async (watcher, deviceInfo) =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, async () =>
{
var usbDevices = await DeviceInformation.FindAllAsync(DeviceClass.PortableStorageDevice);
if (usbDevices.Count > 0)
{
for (var i = 0; i < usbDevices.Count; i++)
{
usbDeviceList.Add(usbDevices[i]);
}
usbList.SelectedItem = usbDevices[0];
usbDeviceCount.Text = usbDevices.Count.ToString();
GeneralMessage.Text = String.Format("{0} USB Storage found.", usbDevices.Count);
}
});
});
usbStorageWatcher.Added += usbStorageWatcherAdded;
usbStorageWatcherRemoved = new TypedEventHandler<DeviceWatcher, DeviceInformationUpdate>(async (watcher, deviceInfoUpdate) =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, async () =>
{
var usbDevices = await DeviceInformation.FindAllAsync(DeviceClass.PortableStorageDevice);
if (usbDevices.Count > 0)
{
for (var i = 0; i < usbDevices.Count; i++)
{
usbDeviceList.Add(usbDevices[i]);
}
usbList.SelectedItem = usbDevices[0];
usbDeviceCount.Text = usbDevices.Count.ToString();
GeneralMessage.Text = String.Format("{0} USB Storage found.", usbDevices.Count);
}
});
});
usbStorageWatcher.Removed += usbStorageWatcherRemoved;