I am attempting to create a proof of concept app that will connect a Windows 8.1 Pro tablet to an embedded Linux device over Bluetooth but I am having trouble getting it to work. The Bluetooth service on the Linux device is written with Python using the pybluez library. The Windows 8.1 app is written using C# and the windows Bluetooth stack as described in this example.
I was wondering if anyone has had any experience in connecting a Linux device with a Windows 8.1 pro store app and could point me in the right direction. This is what I have so far:
Windows 8.1 C# Bluetooth code:
private async void runButton_Click(object sender, RoutedEventArgs e)
{
// Find all paired instances of the Rfcomm chat service
serviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(rfcommServiceUuid)));
if (serviceInfoCollection.Count > 0)
{
List<string> items = new List<string>();
var serviceInfo = serviceInfoCollection.First();
foreach (var chatServiceInfo in serviceInfoCollection)
{
items.Add(chatServiceInfo.Name);
// if (chatServiceInfo.Name.StartsWith("system"))
NotifyStatus(chatServiceInfo.Name + ": " + chatServiceInfo.Id + "\n");
}
NotifyStatus("---Found " + serviceInfo.Name + ": " + serviceInfo.Id + "\n");
try
{
service = await Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService.FromIdAsync(serviceInfo.Id);
}
catch (Exception ex)
{
NotifyStatus("Here1");
NotifyError(ex);
return;
}
if (service == null)
{
NotifyStatus("Error: Access denied, application did not give permission");
return;
}
var attributes = await service.GetSdpRawAttributesAsync();
if (!attributes.ContainsKey(sdpServiceNameAttributeId))
{
NotifyStatus("Error: Service is not advertising the Service Name attribute");
return;
}
var attributeReader = DataReader.FromBuffer(attributes[sdpServiceNameAttributeId]);
var attributeType = attributeReader.ReadByte();
if (attributeType != sdpServiceNameAttributeType)
{
NotifyStatus("Error: Service is using an unexpected format for the Service Name Attribute");
return;
}
var serviceNameLength = attributeReader.ReadByte();
attributeReader.UnicodeEncoding = UnicodeEncoding.Utf8;
var serviceName = attributeReader.ReadString(serviceNameLength);
NotifyStatus("Service Name: " + serviceName + "\n");
try
{
/* lock (this)
{
socket = new StreamSocket();
} */
StreamSocket mySocket = new StreamSocket();
NotifyStatus("3 " + service.ConnectionHostName + " - " + service.ConnectionServiceName + " - " +service.ProtectionLevel+"\n");
await mySocket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);
NotifyStatus("4");
writer = new DataWriter(mySocket.OutputStream);
reader = new DataReader(mySocket.InputStream);
}
catch (Exception ex)
{
NotifyError(ex);
return;
}
try
{
String sendingStr = "Hello from Windows 8.....";
writer.WriteUInt32((uint)sendingStr.Length);
writer.WriteString(sendingStr);
await writer.StoreAsync();
ReceiveDataLoop(reader);
NotifyStatus("Going to sleep");
await Task.Delay(TimeSpan.FromSeconds(5));
NotifyStatus("Sending data");
writer.WriteByte(0x41);
writer.WriteByte(0x4b);
NotifyStatus("Done");
}
catch(Exception ex)
{
NotifyError(ex);
}
}
else
{
NotifyStatus("No services found");
}
NotifyStatus("This is the end of the list");
}
Here is the capabilities code for my Windows manifest file
<Capabilities>
<Capability Name="internetClientServer" />
<Capability Name="privateNetworkClientServer" />
<m2:DeviceCapability Name="bluetooth.rfcomm">
<m2:Device Id="any">
<m2:Function Type="serviceId:34B1CF4D-1069-4AD6-89B6-E161D79BE4D8" />
</m2:Device>
</m2:DeviceCapability>
</Capabilities>
And finally the code for my Python Service:
from bluetooth import *
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(2)
port = server_sock.getsockname()[1]
uuid = "34B1CF4D-1069-4AD6-89B6-E161D79BE4D8"
advertise_service( server_sock, "SampleServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ]
)
print("Waiting for connection on RFCOMM channel %d" % port)
client_sock, client_info = server_sock.accept()
print("Accepted connection from ", client_info)
try:
while True:
data = client_sock.recv(1024)
if len(data) == 0: break
print("received [%s]" % data)
except IOError:
pass
print("disconnected")
client_sock.close()
server_sock.close()
print("all done")
When I run all these together, the windows client successfully finds the service but when it tries to open the socket it throws the following error:
System.Exception: Element not found. (Exceptiion from HRESULT: 0x80070490
At System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
At System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
At System.Runtime.CompilerServices.TaskAwaiter.GetResult()
At TestBluetoothRFCOMMClient.MainPage.<runButton_click>d__0.MoveNext()
I did install python and pybluez on the tablet as well and was able to successfully connect to the Python service using the following python client:
from bluetooth import *
import sys
if sys.version < '3':
input = raw_input
addr = None
if len(sys.argv) < 2:
print("no device specified. Searching all nearby bluetooth devices for")
print("the SampleServer service")
else:
addr = sys.argv[1]
print("Searching for SampleServer on %s" % addr)
# search for the SampleServer service
uuid = "34B1CF4D-1069-4AD6-89B6-E161D79BE4D8"
service_matches = find_service( uuid = uuid, address = addr )
if len(service_matches) == 0:
print("couldn't find the SampleServer service =(")
sys.exit(0)
first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]
print("connecting to \"%s\" on %s" % (name, host))
# Create the client socket
sock=BluetoothSocket( RFCOMM )
sock.connect((host, port))
print("connected. type stuff")
while True:
data = input()
if len(data) == 0: break
sock.send(data)
sock.close()
However I am unable to get the Windows 8.1 store app written in C# to connect. Any help or advice would be greatly appreciated. Thanks
EDIT: The code below fixes the errors that I found in the code that Nate link too if anyone needs it or if I made a mistake in the code, please let me know:
// This App requires a connection that is encrypted but does not care about
// whether its authenticated.
bool SupportsProtection(RfcommDeviceService service)
{
switch (service.ProtectionLevel)
{
case SocketProtectionLevel.PlainSocket:
if ((service.MaxProtectionLevel == SocketProtectionLevel.BluetoothEncryptionWithAuthentication)
|| (service.MaxProtectionLevel == SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication))
{
// The connection can be upgraded when opening the socket so the
// App may offer UI here to notify the user that Windows may
// prompt for a PIN exchange.
return true;
}
else
{
// The connection cannot be upgraded so an App may offer UI here
// to explain why a connection won’t be made.
return false;
}
case SocketProtectionLevel.BluetoothEncryptionWithAuthentication:
return true;
case SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication:
return true;
}
return false;
}
async Task<bool> IsCompatibleVersion(RfcommDeviceService service)
{
var attributes = await service.GetSdpRawAttributesAsync(
BluetoothCacheMode.Uncached);
var attribute = attributes[sdpServiceNameAttributeId];
var reader = DataReader.FromBuffer(attribute);
// The first byte contains the attribute's type
byte attributeType = reader.ReadByte();
if (attributeType == sdpServiceNameAttributeType)
{
// The remainder is the data
uint version = reader.ReadUInt32();
return version >=200;
}
return false;
}
User contributions licensed under CC BY-SA 3.0