I have a Windows Mobile/CE 6 device that needs to read RFID data from a bluetooth RFID wand in a custom .NET 3.5 CF application. Tried many different solutions and trying to make 32Feet's InTheHand bluetooth library work. I can get the device to pair and connect just fine, but when I send commands to the unit and try to read from the stream, it always results in an exception of "Operation time-out". Any tips or help is much appreciated.
var endpoint = new BluetoothEndPoint(device.DeviceAddress, BluetoothService.SerialPort);
var client = new BluetoothClient();
client.Connect(endpoint); // Connects just fine!
var stream = client.GetStream();
using (var sw = new StreamWriter(stream))
{
sw.Write("l");
}
if (stream.CanRead) // Always False
{
using (var sr = new StreamReader(stream))
{
var exi = sr.Peek();
var p = sr.ReadToEnd();
var pp = sr.ReadLine();
}
}
1.
I would first check, if there is any communication possible using the standard tools. Possibly the RFID does not work as you think.
Connect the BT RFID using the BT applet and add a new outgoing Serial Port also in the BT applet. Then use PocketPuTTY or another serial terminal tool to communicate with the RFID module. If that works, you can go on and start using 32feet.
2.
Will the RFID answer on a simple char or does it need a CR/LF on received data?
3.
Test the communication from a PC following 1. usning a Hyperterminal like app.
Related
The following console app works fine on Windows but when I run it in WSL or as a Linux Docker container I get a timeout from the server.
using System;
using System.IO;
using System.Net.Sockets;
namespace ClientTest
{
class Program
{
static void Main(string[] args)
{
const string server = "inbound-smtp.us-west-2.amazonaws.com";
const int port = 25;
Console.WriteLine($"Connecting to: {server}");
using (var client = new TcpClient(server, port))
{
using (NetworkStream stream = client.GetStream())
using (StreamReader clearTextReader = new StreamReader(stream))
using (StreamWriter clearTextWriter = new StreamWriter(stream) { AutoFlush = true })
{
// read connection response
var connectResponse = clearTextReader.ReadLine();
Console.WriteLine(connectResponse);
// send command
Console.WriteLine($"HELO domain.com");
clearTextWriter.WriteLine("HELO domain.com");
// read command response
var commandResponse = clearTextReader.ReadLine();
Console.WriteLine(commandResponse);
}
}
}
}
}
Output on Windows with 250 success...
Output on Linux with 451 Timeout...
However, If I change the server address to ASPMX.L.GOOGLE.com for example then the app works as expected on Windows and Linux.
The console app is targeting .net5.0 but have also tried it with .net3.1 and got the same results. I have also tried running it on a Linux VM with Docker in the cloud but also got the same results.
Are there differences with StreamWriter/NetworkStream on Linux (compared to Windows) and more specifically why do I not get the same issue when using the Google server?
I wonder... is this as simple as a line-ending delta? Windows and Linux have different Environment.NewLine values. Perhaps try adding \r\n explicitly (since Windows seems to work), rather than relying on the local OS line-ending?
clearTextWriter.Write("HELO domain.com\r\n");
Also: try adding an explicit flush - clearTextWriter.Flush();.
As for why the Google server works: perhaps it is more forgiving in what it accepts, where-as the first server is following a specification more precisely, and that specification presumably says that messages are terminated by \r\n. Or the specification may be ambiguous, and Google just chose to be permissive.
BTW: for similar reasons, it would be a good idea to explicitly specify an Encoding here, presumably UTF8.
I want to connect to a cisco switch via telnet in c#.I want to send commands in cmd with c# and when it asks for password I want to enter it with my program. But my problem is that I can’t send password when it is connected to telnet.And when I used StreamWriter it throws an exception.
Here is my code:
class Program
{
static void Main(string[] args)
{
string data = "";
StreamReader reader = new StreamReader(#"C:\Windows\System32");
StreamWriter writer = new StreamWriter(#"C:\Windows\System32");
IPAddress address = IPAddress.Parse("172.16.0.110");
IPEndPoint ipe = new IPEndPoint(address, 23);
Socket telnetSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
telnetSocket.Connect(ipe);
NetworkStream NsStream = new NetworkStream(telnetSocket, true);
if (telnetSocket.Connected)
{
NsStream = new NetworkStream(telnetSocket, true);
reader = new StreamReader(NsStream);
}
while (!reader.EndOfStream)
{
data = reader.ReadLine();
if (data.Contains("Password:"))
{
//I want to enter password in cmd here
}
}
reader.Close();
if (NsStream == null)
NsStream.Close();
}
}
You're going to need to talk Telnet. Telnet rfcs will give you an idead what you're dealing with. https://www.rfc-editor.org/rfc/rfc854
If you want to hand-roll this, a few suggestions that might help. Or else show why it might be a good idea to use a telnet library.
TcpClient will reduce your work a little. At least it will create the NetworkStream for you.
You can probably ignore much of the protocol details, but not the initial option negotiation. You probably want to deal with the raw NetworkStream initially, because telnet sessions start with 'option' negotiation. A quick search for telnet option negotiation turns this up: How to deal with the telnet negotiation
There are two problems using the reader/writer above:
They will be using UTF8 encoding by default, so the telnet option negotiation data (which isn't 7 bit ASCII) will likely get mutated.
Readline() will probably hang anyway, as it will read the telnet options, which are the first thing sent by the server, but then keeping trying to read until the first end of line ... which will never arrive because the server is waiting for a response to the options it sent. i.e. you need to finish the telnet option negotiation.
If you use a lib like SSH.NET you get all these problems solved for you and no need to reinvent the wheel again!
I am currently trying to build a library for using the Serial Port Profile (SPP) on an Universal App.
As far as I have discovered, SPP runs on top of RFCOMM. The basics for RFCOMM are outlined in the MSDN which is fine. I was also able to "find" my device and "connect" to it. I was also able to create a StreamReader and StreamWriter for the RFCOMM.
Now the troubles arise. I understand that RFCOMM provides some kind of channels for various features/tasks, one of them being probably SPP (I know the device features SPP and it even works when done via a "normal" serial connection).
I would like to know if there was an example which bytes I have to send through that channel to get a single byte output on the other side. Is there some kind of connection setup required (bi-directional exchange)? Are there examples for these data packets, what are their names and is there a specific specification for it. I think I would be happy even with some of the correct terms to search for.
Alright, what I assumed was basically wrong. Here is the minimalistic code for a very simple (no error handling, no tasks, ...) communication.
This goes into the Package.appxmanifest:
<Capabilities>
<m2:DeviceCapability Name="bluetooth.rfcomm">
<m2:Device Id="any">
<m2:Function Type="name:serialPort" />
</m2:Device>
</m2:DeviceCapability>
</Capabilities>
And this to a method of your choice (make sure your Bluetooth device has been paired, my device has the name "HC-06").
// Find the device
var bluetoothDevicesSpp = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
var bluetoothDeviceHc06 = bluetoothDevicesSpp.SingleOrDefault(d => d.Name == "HC-06");
var serviceRfcomm = await RfcommDeviceService.FromIdAsync(bluetoothDeviceHc06.Id);
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(serviceRfcomm.ConnectionHostName, serviceRfcomm.ConnectionServiceName, SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
DataWriter writer = new DataWriter(socket.OutputStream);
DataReader reader = new DataReader(socket.InputStream);
To read, use this:
await reader.LoadAsync(1);
byte b = reader.ReadByte();
Debug.WriteLine((char)b);
To write, use this:
writer.WriteString("MaM\r\n");
writer.StoreAsync();
The bytes will be transferred as they are, no additional protocol or similar is necessary. Enjoy.
I'm trying to write a Bluetooth PC client that can do some simple interactive behavior with a Android device over Bluetooth. Then I learned that it is possible to use Windows Socket programming to achieve, however, when I'm trying to create a new socket, this link tells me to use AF_BTH as the address parameter, which is in a C++ struct as clarified in this link.
Here are my codes with errors:
Socket tempSocket = new Socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
So here is my question: Does it mean that I have to use C++ to achieve this? If not, how do I create a new Bluetooth-typed socket under C#?
you can use http://32feet.codeplex.com/ for bluetooth connection
here is simple demo for discovering new devices:
List<Device> devices = new List<Device>();
BluetoothClient bc = new BluetoothClient();
BluetoothDeviceInfo[] array = bc.DiscoverDevices();
int count = array.Length;
for (int i = 0; i < count; i++)
{
Device device = new Device(array[i]);
devices.Add(device);
}
refrence : http://blogs.microsoft.co.il/shair/2009/06/21/working-with-bluetooth-devices-using-c-part-1/
32feet documentation is good enough to look at (samples are in vb language but its .net - easy to convert to c#)
Update: This may not be "Pairing". This may just need to have a service started and bound to a port. However, this code is not storing it either. I need the device to be stored even after the application is closed.
I am building a program specifically suited for Zebra RW 420's on a Windows Mobile 6 Handheld device. The application needs to allow a mobile device to pair with the printer on COM1. I believe I am very close to getting it, but I can't get the pair request to work.
I am able to communicate with the printer and even print by directly connecting and printing, but I can't get the mobile device to actually pair with it. I've tried a variation of pins to include null, "1", "0000", and "1234". No matter what, the method always returns false. Any suggestions or ideas why this might be failing? I can pair the device just find in the WM6 Bluetooth menu, but not in my application.
It might be important to note that the little light bulb icon on the printer comes on when the program says it is attempting to pair, but after about 5 to 10 seconds, it fails.
BluetoothSecurity.PairRequest(device, "1"))
Additional Information:
I've successfully paired with my Android phone using this code.
I then logged in and set a PIN on the Zebra printer. However, this code still fails to pair with the printer even when I know the pin is correct / set in the printer.
From https://km.zebra.com/kb/index?page=answeropen&type=open&searchid=1336682809706&answerid=16777216&iqaction=5&url=https%3A%2F%2Fkm.zebra.com%2Fkb%2Findex%3Fpage%3Dcontent%26id%3DSO8031%26actp%3Dsearch%26viewlocale%3Den_US&highlightinfo=6292341,26,43#
Zebra Bluetooth enabled mobile printers are 'slave' devices only. The printers will pair with any 'master' device that tries to make a valid connection. Since only a master device can initiate a connection, the printer does not store pairing data, that function is always done on the master device. The printer can only be connected to one master device at a time, but any number of master devices that have stored pairing information for the printer would be able to initiate a connection to the printer without having to rediscover it.
I'm guessing that this means the InTheHand.Net BluetoothSecurity.PairRequest might not work for this type of pairing?
In the Bluetooth section of the WM handheld, under the "Devices" tab, I can add the device. I need to essentially do that. I need to register the device in that list and then set it to use COM 1 in the "COM Ports" section. The application I am using doesn't actually print. It's sole purpose is to prepare the printer for other applications.
The quote from Zebra make it sounds as pairing is actually not required at all. Are you printing from your app? If so just connect to the SPP service and send the text.
BluetoothAddress addr = ...
Guid serviceClass;
serviceClass = BluetoothService.SerialPort;
var ep = new BluetoothEndPoint(addr, serviceClass);
var cli = new BluetoothClient();
cli.Connect(ep);
Stream peerStream = cli.GetStream();
peerStream.Write ...
(From General Bluetooth Data Connections)
The Zebra Mobile Printer needed to be properly configured before pairing with this method will work. Here is what I did:
First, I ran the following commands on the printer:
.
! U1 setvar "bluetooth.authentication" "setpin"
! U1 getvar "bluetooth.authentication"
! U1 getvar "bluetooth.enable"
! U1 getvar "bluetooth.discoverable"
! U1 setvar "bluetooth.bluetooth_pin" "0000"
! U1 getvar "bluetooth.bluetooth_pin"
Then, the application with this code ran successfully.
.
int pair_req = 0;
try
{
if (BluetoothSecurity.SetPin(device, "0000")) {
while (status == false && pair_req < 3)
{
++pair_req;
status_box.Text = status_box.Text + '\n' + "Attempt " + pair_req.ToString();
status_box.Update();
if (BluetoothSecurity.PairRequest(device, "0000"))
{
status = true;
client.Refresh();
status_box.Text = "Paired Successfully.";
status_box.Update();
Thread.Sleep(5000);
}
else
{
status = false;
}
}
}
}
catch (ArgumentNullException e)
{
status_box.Text = "Pair failed.";
status_box.Update();
Thread.Sleep(5000);
}
status_box.Update();
Thread.Sleep(400);