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
Related
I am having trouble trying to pair & bond a Bluetooth LE device using btframework (www.btframework.com), specifically the Nonin Wristox 3150 BLE
The documentation for the device states...
The 3150 BLE uses the Just Works
pairing method with bonding support. Upon successful pairing, the collector should initiate bonding, and the 3150 BLE will save the long term bonding key associated with the collector. The 3150 BLE requires the
collector to be bonded in order to encrypt the connection. When bonding is complete, the collector should
encrypt the connection.
I'm trying to work out what I should be doing to get connected. I've actually managed to get it connected once, which is how I've done all my development, but what I've done does not seem to have worked when I try it again. Using the BTFramework demo application, their "GattClient" - I can discover my device no problem, but when I click on "Connect", it connects to the device with a 0 error code (indicates success) , but the device disconnects a second later. I'm guessing this is because I haven't done all the pairing above.
So I've used their "Bluetooth Manager" to try pairing. I set the MITM to "ProtectionRequiredBonding", IOCap to "DisplayOnly" and BLE Protection to "Encryption", and click "Pair".
This actually worked once - I was paired, and then I was able to use the GattClient to Connect and get the services, characteristics and see the characteristic changes.
However I haven't been able to repeat the exercise. When I use Windows to remove the device, I'm back to the previous state where I can connect but get disconnected by the device, and I tried the above again. It doesn't seem to work now though. I usually get error 0x005105C (device not found) when I try to connect now. In the Window settings devices page, the status seems to change between "Connected" and "Paired" at random, and sometimes the device itself just starts reporting a connection error. (The device is not very forthcoming about what's causing the error). It always reports the pairing itself to be a success though
There is also this:
If the encryption process fails, it is likely that either the collector or 3150 BLE has deleted its bond key. When this occurs, the 3150 BLE will delete its bond key if present. It is recommended that the collector also delete its bond key if present.
Is this something I need to be doing? How is this done with btframework?
It appeared becasue your device has random MAC which changes each time you connect.disconnect.
So the correct sequence is:
Discover device.
Pair with it.
Connect.
Do what you need.
Disconnect.
Unpair (through your code, not through Windows device manager.)
If need connect to it once again go to step 1 so the device will be found with new MAC.
Should you have any questions it faster to get answered if you contact us by e-mail (support#btframework.com).
Just to follow up on this, it turned out to be a quirk specific to my device. It only allows pairing for the first 2 minutes after putting in you're batteries. If I remove the batteries and put them back in, I can pair with the device.
I have a windows form application in C# and I'm trying to get the host name of all the clients that I have in a list. Given below is a code example by ra00l from this link: GetHostEntry is very slow (I have a similar code made but this one is cleaner)
private delegate IPHostEntry GetHostEntryHandler(string ip);
public string GetReverseDNS(string ip, int timeout)
{
try
{
GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry);
IAsyncResult result = callback.BeginInvoke(ip,null,null);
if (result.AsyncWaitHandle.WaitOne(timeout, false))
{
return callback.EndInvoke(result).HostName;
}
else
{
return ip;
}
}
catch(Exception)
{
return ip;
}
}
When it's given an IP of a Windows Machine in the network, it shows the correct host name given that you enter a reasonable timeout. After the tests that I made, I didn't get any response for the host names of android and apple devices. For example, the picture below is the DHCP Client List of the router that I have. It shows android, apple and laptop devices. I'm using the laptop 'Nathu-Laptop' giving me an IP address of '192.168.1.106'.
If I enter '192.168.1.105' in the C# function, the result is 'Nandwani-PC' but if I input '192.168.1.103', '192.168.1.104', '192.168.1.101', '192.168.1.100', I don't get any hostname.
I also tried using nbtstat but it only gets the laptops in the network.
When trying this out on my iPod, I ensure that there is a network activity going on. This is to keep the connection alive because it disconnects from the network when it's on standby.
EDIT:
So I found out that DNS.GetHostEntry calls getaddrinfo if IPv6 is enabled, otherwise, call gethostbyaddr and these functions may access the data from \System32\drivers\etc\hosts or maybe from the NETBIOS. The thing is that the NETBIOS is legacy right? but how about for mobile devices?
About NetBIOS:
In order to answer your specific questions about NetBIOS, and name resolution on network, I'll give more details. If you don't have dns server running on your network, name resolution will rely only on NetBIOS resolution.
It is a standard and implemented on several operating systems. However, it's not very fast.
Even if we're old, we're not legacy from the past and obsolete
You can check on Microsoft support the way names are resolved on Windows and NetBIOS is the last one.
However, NetBios name resolution is not always fully functional (like this bug on Android which was fixed in 2014) on all mobile platforms (depends on Android version for example).
If you want to improve the performance, I suggest you to install a DNS server in the network.
Did you try ping -a <IP address> or nslookup <IP address> to check if the results are in line with your expectations ?
If your problem still persist, then you may investigate the .Net implementation, thanks to the above links. You can also check a more up to date version of .Net DNS implementation here
I got a little problem with a USB Barcode Scanner.
I am using the Scanner with the "SerialPort" class:
this._barcodeScanner = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One) { Handshake = Handshake.None, ReadTimeout = 500, WriteTimeout = 500 };
this._barcodeScanner.Open();
this._barcodeScanner.DataReceived += BarcodeScannerCallback;
If I unplug the USB Device while it´s opened via the "SerialPort" class, I can´t close the software properly and the virtual port stays open for all eternity or till I reboot the whole computer.
So my question is, is there any way to close the virtual port after I unplugged the device via C# code?
Greetings
[edit #1]
Alrighty, some more code:
This way I am checking every 10 seconds if the device is plugged in:
private bool CheckUsbDeviceAvailability()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI",
"SELECT * FROM MSSerial_PortName WHERE PortName = '" + this.PortName + "'");
if (searcher.Get().Count > 0)
return true;
return false;
}
Thats the Callback-Event of the Serial Port:
void BarcodeScannerCallback(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = this._barcodeScanner.ReadExisting().Replace(Convert.ToChar(2), Convert.ToChar(32)).Trim();
if (data.StartsWith("AX"))
{
string[] arrData = data.Split('\n');
this._barcodeScanner.StopAvailabilityThread();
Barcode code = new Barcode(arrData[0].Replace("\r", ""));
if (CheckIfBarcodeExists(code))
this.UpdateBarcodeNode(code);
else
this.CreateBarcodeNode(code);
BarcodeScannerCallbackEvent(sender, e, code);
this._barcodeScanner.StartAvailabilityThread();
}
this._barcodeScanner.ComDevicePluggedIn = ScannerDevice.ComAvailabilityState.Available;
}
if it doesnt answer anymore it will fire the "DeviceNotAvailableEvent()":
void BarcodeScannerDeviceNotAvailableEvent()
{
this._barcodeScanner.Close();
this._barcodeScanner.Dispose();
}
I have overriden the Dispose Event of the "SerialPort" class so that it´s going to abort the Thread:
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
this._deviceAvailableThread.Abort();
}
base.Dispose(isDisposing);
}
Serial ports date from the stone age of computing. That's where you plugged in your ASR-33 teletype to start typing in your Fortran program. The electrical interface is very simple. So is the Windows API to use a serial port from your own code. Practically any runtime environment supports them.
USB has replaced serial port hardware completely. It has a much more advanced logical interface to the machine, supporting many different type of devices. And it supports Plug and Play, allowing the operating system to detect when a device is attached or removed as well as automatically installing the device driver, etcetera.
This flexibility comes at a price however, a USB device always needs a device driver to become usable. Device drivers are not created equal. Different drivers require different ways to talk to the device. Usually done through DeviceIoControl() or Read/WriteFile() but those are very opaque API functions. In the early days of USB, device manufacturers would supply a DLL that provided a rich API to hide the implementation details.
That did not work so well, manufacturers are not very good at writing good APIs and they sure don't like to support them. So a good solution would be to support a standard API, one that's available on any machine, supported by any runtime, documented and maintained by somebody else. Like the serial port API.
That did not work so well, manufacturers are not very good at writing device drivers that emulate serial ports. The biggest hang-up with the API is that it doesn't have any support for Plug and Play. The core support for it is missing, after all serial port hardware doesn't have the logical interface to support it. There is some support for detecting that a device is attached through the DTR hardware handshake line, but no support whatsoever for detecting that the port is no longer there.
Detaching the USB device is the problem. In an ideal world, the emulator built into the device driver would simply pretend that the serial port is still there until the last handle on the device is closed. That would be the logical implementation, given that there's no way to trigger a Plug and Play event. For some strange reason that seems to be difficult to implement. Most USB drivers take the crummy shortcut, they simply make the device disappear even while it is in use.
This plays havoc on any user mode code that uses the device. Which is typically written to assume it is a real serial port and real serial ports don't suddenly disappear. At least not without drawing a bright blue spark. What goes wrong is pretty unpredictable because it depends on how the driver responds to requests on a device that's no longer there. An uncatchable exception in a worker thread started by SerialPort was a common mishap. Sounds like your driver really gets it wrong, it generates an error return code on the MJ_CLOSE driver request. Which is kind of a logical thing to do for a driver, after all the device isn't there anymore, but quite unsolvable from your end. You have a handle and you can't close it. That's up a creek with no paddle.
Every major release of .NET had a small patch to the SerialPort classes to try to minimize the misery a bit. But there's a limited amount that Microsoft can do, catching all errors and pretending they didn't happen ultimately leads to class that provides no good diagnostic anymore, even with a good driver.
So practical approaches are:
always use the Remove Hardware Safely tray icon in Windows
use the latest version of .NET
contact the vendor and ask for a driver update
ditch vendors that supply lousy drivers
tell your users that, just because it is the only thing you can do with a USB device, that unplugging it doesn't solve any problems
make closing the port easy and accessible in your UI
glue the USB connector to the port so it can't be removed
The 5th bullet is also what gets programmers in trouble. Writing serial port code isn't easy, it is heavily asynchronous and the threadpool thread that runs the DataReceived event is difficult to deal with. When you can't diagnose the software problem you tend to blame the hardware. There's very little you can do with the hardware but unplug it. Bad Idea. Now you have two problems.
This Problem Exists in .Net 2 , 3 , 3.5 you can use framework 4 (problem does not exist in .net 4)
My goal is to use c++/c# to poll a usb port to see if power is flowing through from the out to in.
I have a infared detector led connected to the usb output and then back to the input. I basically want to know how I could do something like this:
USBDevice usb = LoadUSBDevice(port1);
boolean detected = usb:isPowerFlowingOutToIn();
if(detected){
double amount = usb:getVoltage();
if(amount > somenumber){
//do stuff
}
}
This setup can't work as-is. USB devices have to respond per the USB specs, or they won't get an address assigned. Since your device isn't behaving properly (e.g. it fails to establish Vendor ID, Product ID, device class, ...) it won't get an address. Therefore, the hypothetical LoadUSBDevice(port1); won't work.
Raymond Chen summarized this nicely as "a fork is a non-standard USB device, too". The Windows USB drivers are reasonably forgiving, but you can't just expect anything to work when plugged into a USB port.
Hi Is there any way to connecting to computers via Dial Modem without internet?
Like windows Hyper terminal.
making connection sending files between computers.
Just Connection Between two Computers Directly and sending FIle.
Yes.
Assuming the modems are connected via a serial port (or emulate being connected via a serial port): you'll need one modem set up (learn your AT commands!) to listen for and answer incoming calls, and the other to dial the first.
You can then treat the pair as a rather long serial link.
However getting everything to work reliably is more of an art than a science, and something that is so rarely done today that much of it is forgotten. The last time I worked with modems in this way was more than fifteen years ago.
The way we used to do it back in the olden days was with a null-modem cable. We even used to do "networked" gaming that way, back in the day.
This is bascially an RS-232 cable with the receive and transmit pins crosswired. I still see some adapters around, so it shouldn't be too tough to get hold of one.
Much later some people created SLIP (Serial Line IP) to enable a serial line to act as a carrier for the entire TCP/IP stack. A bit later PPP was introduced as an improvement. I think SLIP is still available for most platforms, and PPP exists on every platform that can do dial-up internet.
So if the question basically boils down to wanting to network two computers via PPP without going through somebody else's dial-up server (like Earthlink), what you need is to install a PPP server on one of the two machines. They come with most Linux distros. For Windows you will have to go look. I'd help, but my corporate blocker is being overexuberant again.
Someone has written an XModem implementation in C# here: http://trackday.cc/b2evo/blog2.php/2007/08/02/net-xmodem It may help with what you're after.
One thing that's not clear from your question is whether you are attempting to directly connect two machines in the same physical location with a cable, or if you are attempting to dial in to one from the other over a PSTN.
If they are in the same place, eliminate the modem from the equation. This reduces complexity significantly.
If they are in separate locations (ie, dialing over an honest-to-God dial-up connection), there is some code here that might help you. The article talks about a Bluetooth or GPRS modem, but the core of it is about sending AT commands which can be used to talk to any AT-command set-compatible device. It might get you going in the right direction.
Update
See http://msdn2.microsoft.com/en-us/system.io.ports.serialport(VS.80).aspx
Since a modem should be attached to a COM port (COM1-COM12) even it is an internal modem, you should be able to use the .NET framework's SerialPort class to open the port, send AT commands, etc. Once you have an open connection, you could use the XModem library to transfer files, or straight serial for regular communications.
Do you need an IP stack, or are you happy with a straight serial protocol?
You can quite easily setup dial-up network connections within Windows that require the use of a modem (its under the option for setting up a VPN, but you can set it for just a dial up).
So I would assume that you can then map a network location to it for use by your C# code.
As already stated at least one of the modems must be on and listening for a connection.
* edit *
I believe that the following code will trigger a dial-up connection that has been placed within Network Connections
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(#"c:\Local Area Connection 2 - Shortcut");
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
For link placed at c:\ drive and named "Local Area Connection 2 - Shortcut"
You could then ping the destination to see if its connected.
Ultimately though I think that your best solution may be to use RAS.
Have a look here at Codeplex: DotRAS
You can then use the following code:
RasDialer dialer = new RasDialer();
bool connected = false;
foreach (RasConnection connection in dialer.GetActiveConnections())
{
if (connection.EntryName == "MyFriendsPC")
{
connected = true;
break;
}
}
if (!connected) {
dialer.EntryName = "MyFriendsPC";
dialer.Dial();
// If you need to provide credentials, use the Dial(NetworkCredential) overload that's available.
}
This example assumes you already have an entry named MyFriendsPC in the default phone book. If you do not and need to create this connection programmatically, you can use the RasPhoneBook component for that.
RasPhoneBook pbk = new RasPhoneBook();
pbk.Open(); // This will open the phone book in the All Users profile.
RasEntry entry = new RasEntry("MyFriendsPC");
If you'd rather use the default settings for the connection you can use one of the static methods on the RasEntry class, or manually configured the connection here.
pbk.Entries.Add(entry);
Once the entry has been added to the collection, it will immediately be added into the phone book.
I recently wanted to connect a dial-up POS terminal to an analog modem. This is not difficult, but you need to introduce a 9-volt battery and a 200mA resistor in parallel for the modems to connect. https://www.youtube.com/watch?v=luarFqislIc describes the approach (skip to 11:30 to see the circuit). Without the battery and resistor to provide the loop current (about 18mA), the modems will not negotiate a connection (you'll hear the modem after entering ATA to answer, but you won't hear the final part of the modem negotiation). With the loop current, the modems will connect. The video even shows ZModem being used to transfer a file from one PC to the other.
One final item not mentioned in the video is with this circuit, there is no dial tone. To get around this, enable blind dialing (ATX1) on the calling modem. Also, since there are no rings with this approach, setting the receiving modem to auto-answer (ATS0=1) won't work. You have to enter ATA on the receiving modem to answer.