I'm using Windows.Devices API in a WinForms App on Windows 10. I'm connecting to a Bluetooth Barcode scanner. The connection works fine and I'm getting an Event when the connection has been established and also when the connection has been dropped (disconnected).
But when I change the battery in the scanner and the scanner re-connects to Windows I'm getting no Event.
My question now is: if there's any possibility to get an Event when the device re-connects over Bleutooth?
My need is to reconnect the socket to the device after the device has been reconnected over Bluetooth.
EDIT: Dear admins, this is not a WinForms issue. This issue even doesn't deal with UI at all. It's just an API issue with the Windows.Devices UWP API. Please stop suggesting changing the tags.
Thanks
Sven
Some Sample Code:
_device = await BluetoothDevice.FromBluetoothAddressAsync(decimalAddress);
_device.ConnectionStatusChanged += OnDeviceConnectionStatusChanged;
Event is called only on first connect and on disconnect of device:
private void OnDeviceConnectionStatusChanged(BluetoothDevice sender, object args)
{
}
What I've found out so far is that it seems very common that the event never raises again. One has to actively create a new connection to the device, that is, for example by opening a socket for receiving data.
So the solution for my problem was to connect to the bluetooth device by calling
StreamSocket.ConnectAsync()
again to establish a new connection. Afterwards the ConnectionStatusChanged is raised with state connected.
Good luck
Sven
Related
I'm trying to build a simple MQTT application using Xamarin, and testing it on both an Android emulator and a phone. Unfortunately, I'm struggling to make a connection with CreateAsync, and at a loss how to debug it.
I've checked I can connect to my RabbitMQ server as follows:
using System.Net.Mqtt;
Console.WriteLine("Trying to connect...");
var configuration = new MqttConfiguration();
var client = MqttClient.CreateAsync("127.0.0.1", configuration).Result;
var sessionState = await client.ConnectAsync(new MqttClientCredentials(clientId: "test", userName:"mqtt", password:"mqtt"));
Console.WriteLine("...it worked.");
Console.Read();
As the code tells me... it worked. :o) RabbitMQ shows the connection. I tried it with "localhost", the hostname and IP of my PC to check they all work, and an incorrect host name to see what exception gets thrown ("Socketexception: No such host is known").
My troubles start when I try to do this in the actual app. The connection code is fundamentally the same, but run in a separate task as I read you shouldn't do it in the GUI thread:
private async Task<SessionState> Connect(string BrokerHostName, Action<MqttApplicationMessage> publishEventHandler)
{
MqttConfiguration config = new MqttConfiguration();
_client = MqttClient.CreateAsync(BrokerHostName, config).Result;
SessionState sessionState = await _client.ConnectAsync(
new MqttClientCredentials(clientId: Id, userName: "mqtt", password: "mqtt")
);
await _client.SubscribeAsync("common", MqttQualityOfService.AtMostOnce);
_client.MessageStream.Subscribe(publishEventHandler);
return sessionState;
}
Called by:
var task = Connect(BrokerHostName, publishEventHandler);
But nothing happens - the code reaches this line and just hangs. If I set a break, continuing just continues to do nothing. I've made sure the INTERNET and ACCESS_NETWORK_STATE permissions are ticked in the Android manifest (though it makes no apparent difference).
This is what I've tried after some hours of Googling:
Using the hostname or IP address of my PC with the Android device, running with and without debug, and also unplugged from PC and run on its own.
Using 10.0.2.2 and running on the emulator, as I understand this is the equivalent of localhost or 127.0.0.1.
Setting the proxy address on the emulator to the same as my PC and port 1883. Even though the 'Apply' button teases with a "Proxy status: success", it still doesn't connect.
It feels like a networking problem since I can put any old rubbish as the host address and it behaves the same, but I've totally run out of ideas for what to try next or how to see what's going on. Any advice very gratefully received!
I now have this working. Here's the steps I took, in case it helps someone else:
I wrote some test apps to check TCP communication. First a client and server in Windows to check they work, then a Xamarin client app. This worked and proved the network connections were OK.
Installed an MQTT Tester on the Android emulator to prove it was possible to connect to RabbitMQ.
Tried a different MQTT framework: MQTTnet.
Similar problem but different symptoms: the code would get stuck on the .Wait() rather than inside the task itself. Then I removed all the asynchronous code and then it connected.
My conclusion is that the problem may be my lack of understanding of asynchronous programming. System.Net.Mqtt seems to require it while MQTTnet does not, so all's well that ends well!
I am developing a windows forms application which will communicate with the Siemens S7-1200 PLC for real accessing real time data from PLC and sending data to PLC. The connection and real time communication is all working fine. But I'm facing issues when
Closing the connection to PLC.
Ethernet cable is disconnected
The PLC is powered off
1 . I have used Plc.close() method in the form.closed event. But the connection is not getting closed ,
instead throwing PLC disconnection error.
2 & 3. I expected same behavior but it is throwing different errors.
When ethernet cable was disconnected either at application side or PLC side, the ethernet socket
exception is thrown.
When the PLC power was turned off the program was still trying to write data to the PLC for some
time and then showed the ethernet socket error happened.
Can anyone help me with how to handle these errors?
As you can see on s7netplus repository on Github the PLC class is implementig IDisposeable. In your question there is no code but if you are calling the PLC class with a using statment:
using(Plc plc = new PLC(...) {
// Do some actions
}
the Close() method is called after the end of the using block (Dispose). So if you are trying to call the Close() method again an exception occurs.
If it is possible, please provide a code example.
I am Trying to run BluetoothLE code from Universal Windows Sample-->https://github.com/Microsoft/Windows-universal-samples
Initially the device gets paired successfully
But when i click the Connect button it shows error message "Device Unreachable"
I put a breakpoint at the starting of this code snippet and the result varible was not equal to GattCommunicationStatus.Success.
GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached);
gatt = (int)result.Status;
if (result.Status == GattCommunicationStatus.Success)
{
var services = result.Services;
rootPage.NotifyUser(String.Format("Found {0} services", services.Count), NotifyType.StatusMessage);
foreach (var service in services)
{
ServiceCollection.Add(new BluetoothLEAttributeDisplay(service));
}
ConnectButton.Visibility = Visibility.Collapsed;
ServiceList.Visibility = Visibility.Visible;
}
else
{
rootPage.NotifyUser("Device unreachable", NotifyType.ErrorMessage);
}
Please help
Thanks
I was struggling with exactly the same problem, but I think I've found the answer. From a post on the Microsoft Q&A website. I'm relatively inexperienced, so take my explanation with a pinch of salt, but this is my understanding of the problem:
It revolves around Bluetooth Low Energy (BLE) Privacy. To prevent the tracking of a user via the Bluetooth advertisements their smartphone is constantly emitting, the MAC address of the device is changed periodically; no more than every fifteen minutes. The randomised address is known as a Resolvable Random Private Address. For paired devices to be able to keep track of the device, a symmetric key called an Identity Resolving Key (IRK) is exchanged during pairing. This key can then be used to resolve the identity of the device from the random MAC addresses it is advertising.
Microsoft's implementation of BLE on Windows doesn't include all aspects of BLE Privacy. Specifically, it only supports Random Private Addresses while advertising. This means that, after you pair a device with a Windows PC, Windows doesn't randomise it's MAC address or provide the paired device with an Identity Resolving Key. Modern implementations of BLE, specifically on smartphones, seemingly do not allow connections with devices that don't implement Resolvable Random Private Addresses, such as Windows PCs. This could be because it is seen as suspicious behaviour.
Therefore, when using BLE to connect a Windows PC to another device, Android in my case, you can connect to the device and read the BLE services from the device while not paired. As soon as you pair the two devices however, the second device rejects the connection and the Windows device will always return "Device Unreachable" when trying to read the Gatt services.
This issue may be caused by your device or the Bluetooth environment, you can try to turn off your Bluetooth device then turn on it again on your devices to test it again. You can open and close the Bluetooth on your device Settings app => Devices => Bluetooth & other devices.
See the MSDN thread Problem with BluetoothLE code, GattCommunicationStatus.Success is not working
I've created an asynchronous server in C# to go along with my Android application. The server is similar to this: http://msdn.microsoft.com/en-us/library/fx6588te.aspx
It works well and I can have many clients connect and receive data from the server at the same time. One problem that I've found is that in my Android app if you are already connected over Wifi and press the connect button again, the server spawns a new socket. The server should kill the old connection first and then create a new connection. On the Android side I make sure to call close() and even set it to null afterwards. I also send a disconnect control signal to the server so that it can also call close() on the socket. For example, here's how I do it in the server:
if (state.storage.parseJson(content) == JsonStorage.DISCONNECT)
{
Console.WriteLine("Disconnect2!");
state.workSocket.Shutdown(SocketShutdown.Both);
state.workSocket.Close();
return;
}
When I inspect my server process in a program called "CurrPorts" it shows several connections open to my Android device on different ports. I send data to my clients using a Timer object, and I also check to see if the connection is active otherwise I close it. For example, my TimerCallback method:
public void TimeCallBack(object input)
{
StateObject state = (StateObject)input;
if (state.workSocket.Connected)
{
Send(state.workSocket, state.storage.getJson());
}
else
{
Console.WriteLine("Dispose!");
state.timer.Dispose();
state.workSocket.Close();
}
}
I can't think of why my server isn't closing old connections. There should only be as many connections open as devices connected to the server. If this were a threaded blocking server then it would be easy to just close the thread down, but I'm not sure what to do in this case.
edit: so I just refreshed the CurrPorts program after letting it sit for a while and it dropped down to one established connection. Is my solution right and it just takes a while for Windows to actually clear the old socket connections that were created?
Yes, Windows will keep around the information about the socket for a while. You can see this with netstat, closed sockets will show a state of TIME_WAIT after they are closed and even after the application that hosted the socket has terminated.
If a detach a serial device which is still being used by windows, SerialPort.GetPortNames() will return that same detached device as actually still being attached. I also can't close the serial port without an unhandeled exception error stating that the port does not exist (which is true).
I can confirm that the device map for SERIALCOMM in the registry is not being updated either, which is where SerialPort.GetPortNames() gets the port names I presume. The hardware manager detects the right COMM ports.
Is there a way around this? Can I simply delete the SERIALCOMM registry entry?
I looked at this potential workaround, but I think that will just let me catch the exception.
I'm not an expert but my experience is that as long as you have any (SW-)object connected to the com-port it will be visible.
When I tested this some years ago I got the same result and not until I did lose my SerialPort object the port disappeared from the GetPortNames list (and presumable also the registry).
I think this is the way Windows handles this driver. If a serial port gets unplugged while in use in SW the system continues to have a place-holder for the serial port until it is released by SW.
In my SW I solved this by having a timeout for the function I needed (the other end could stop working as well) and before every new start of program-loop (normally once every 5min-1h) I just released the COM-port and reconnected to it, if reconnect failed the port was detected as lost...
Hope this helps you.