I am trying to provide a "click to dial" solution for someone to a bluetooth device such as a mobile phone. I have been trying to do so using the 32feet.net bluetooth api.
I haven't really done anything with bluetooth (since the days of at commands via a bluetooth serial port) but I have paired the device in question, which supports the handsfree service with the pc. I have the following code to attempt to connect and send a dial command.
String deviceAddr = "11:11:11:11:11:11";
BluetoothAddress addr = BluetoothAddress.Parse(deviceAddr);
BluetoothEndPoint rep = new BluetoothEndPoint(addr, BluetoothService.Handsfree);
BluetoothClient cli = new BluetoothClient();
cli.Connect(rep);
Stream peerStream = cli.GetStream();
String dialCmd = "ATD 0000000000\r\n";
Byte[] dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd);
peerStream.Write(dcB, 0, dcB.Length);
// Begin Edit ------------------------------------------------------------
Byte[] sResponse = new Byte[100];
peerStream.Read(sResponse, 0, 99);
TextBox1.Text = System.Text.Encoding.ASCII.GetString(sResponse);
// End Edit --------------------------------------------------------------
peerStream.Close();
cli.Close();
MessageBox.Show("Done");
Since it seems to run through these lines of code, taking an appropriate time to connect at the relevant spot or crashing out if the device address is wrong and it can't connect. Obviously the AT command is not the right thing to be sending it.
Can anyone enlighten me as to what I might need to send to a bluetooth device via the handsfree profile to get it to dial?
Begin Edit -------------------------------------------
I decided to read from the stream and see if there was a response of any sort after sending the AT command through. Since I am just testing to see if I can make it work I am just dumping the response into a textbox.
The response I read from the stream is :
ERROR
There doesn't seem to be an error codes or anything.
End Edit ---------------------------------------------
Edit --------------------------------------------------
Sent command : AT+CMER\r
Result : OK
then
Sent command : AT+CIND=?\r
Result :
+CIND: ("service",(0-1)),("call",(0-1)),("callsetup",(0-3)),("battchg",(0-5)),("signal",(0-5)),("roam",(0-1)),("callheld",(0-2))
then
Send command : ATD 0000000000\r
Result:
OK
D: ("service",(0-1)),("call",(0-1)),("callsetup",(0-3)),("battchg",(0-5)),("signal",(0-5)),("roam",(0-1)),("callheld",(0-2))
Still it doesn't actually dial :(
End Edit ----------------------------------------------
Solution ----------------------------------------------
The following code now works to dial via my iPhone. It's really rough at the moment, as I have just been testing to see if I could make it work. It's enough to get started for anyone else wanting to do a similar thing.
String deviceAddr = "00:00:00:00:00:00";
BluetoothAddress addr = BluetoothAddress.Parse(deviceAddr);
BluetoothEndPoint rep = new BluetoothEndPoint(addr, BluetoothService.Handsfree);
BluetoothClient cli = new BluetoothClient();
cli.Connect(rep);
Stream peerStream = cli.GetStream();
String dialCmd1 = "AT+CMER\r";
String dialCmd2 = "AT+CIND=?\r";
String dialCmd3 = "AT+BRSF=\r";
String dialCmd4 = "ATD 0000000000;\r";
Byte[] dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd1);
peerStream.Write(dcB, 0, dcB.Length);
Byte[] sRes = new Byte[200];
peerStream.Read(sRes, 0, 199);
textBox1.Text = textBox1.Text + "\n\r----------\n\r" + System.Text.Encoding.ASCII.GetString(sRes);
dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd2);
peerStream.Write(dcB, 0, dcB.Length);
peerStream.Read(sRes, 0, 199);
textBox1.Text = textBox1.Text + "\n\r----------\n\r" + System.Text.Encoding.ASCII.GetString(sRes);
dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd3);
peerStream.Write(dcB, 0, dcB.Length);
peerStream.Read(sRes, 0, 199);
textBox1.Text = textBox1.Text + "\n\r----------\n\r" + System.Text.Encoding.ASCII.GetString(sRes);
dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd4);
peerStream.Write(dcB, 0, dcB.Length);
peerStream.Read(sRes, 0, 199);
textBox1.Text = textBox1.Text + "\n\r----------\n\r" + System.Text.Encoding.ASCII.GetString(sRes);
peerStream.Close();
cli.Close();
Try to find what is the response for AT\r (or) ATH\r.
If the response is "OK\r\n", try your dial command with no space after ATD and number.
As maintainer of 32feet.NET I'd love to find the answer to this. Hopefully someone with knowledge of HSP/HFP will explain why this doesn't work. My only general guess is that since we're not accepting/creating the SCO channel for the audio channel the phone refuses the connection.
Once thing in your case however... AT commands are terminated by a CR (0Dh); or does the semicolon act the same??
Related
I'm trying to send an array of bytes from android (client) to Linux (server), I can send around 17kB but then the socket send an client socket timeout exception. At the server side I'm using netcat with the next command:
nc -l -p 55000 > out.txt
This works ok because I'm capable of sending files from other computer, for this reason I think the problem is at the client side (Android).
I'm using Visual Studio 2015 with Xamarin to compile the project and I tried many methods to send thought socket with the same result, between 15~20kB sended. Of course the permissions on Android to send through internet and other rights are ok.
This is the first mode I tried:
byte[] data = new byte[200000];
TcpClient client = new TcpClient("192.168.0.245", 55000);
client.SendBufferSize = 8192;
NetworkStream ns = client.GetStream();
ns.ReadTimeout = 1000;
ns.WriteTimeout = 1000;
ns.Write(data, 0, data.Length);
ns.Flush();
ns.Close();
client.Close();
With this method only around 17kB are received and the socket is not closed, but the close methods are executed (I tested it with the debugger placing MessageBox to test in release).
Other method I've tested is this:
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.245"), 55000);
System.Net.Sockets.Socket sender = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sender.ExclusiveAddressUse = true;
sender.LingerState = new LingerOption(true, 1);
sender.NoDelay = true;
sender.SendBufferSize = 8192;
sender.ReceiveBufferSize = 8192;
sender.SendTimeout = 1000;
sender.ReceiveTimeout = 1000;
sender.Ttl = 42;
try{
byte[] data = new byte[200000];
sender.Connect(remoteEP);
for (int a = 0; a < data.Length;)
{
int len = (data.Length - a) > 8192 ? 8192 : data.Length - a;
a += sender.Send(data, a, len, SocketFlags.None);
}
}
catch (Exception e)
{
string a = e.ToString();
}
The program send the first 8192 bytes and in the second round an socket timeout exception is trowed. If I try to send all the bytes is one time the program executes the send method the returned bytes are the total length of the array, this mean all bytes are sent to the socket but only received 17kB.
I've tested other methods to do the same thing with the same results in two phones. The android version for compiler I'm using is 4.2. For VS and Xamarin the latest.
Also I tried to download an app from the market to send files throught TCP to see if the problem is in Netcat, firewalls, SO or other and the files was sended ok.... I'm very frustated, I think I'm doing well all the things.
Thanks in advance
I have tried the following:
(This "whatever" is a 4 digit pin asked to enter after sending a AT+STGR=3,1 to the port)
1. this.port.WriteLine("whatever\0x1A");
2. this.port.WriteLine("whatever"+ char.ConvertFromUtf32(26));
3. this.port.WriteLine("whatever\u0001");
4. this.port.WriteLine("whatever"+(char)26);
5. this.port.WriteLine("whatever");
SendKeys.Send("^(z)");
6. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x1A }, 0, 1);
7. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x26}, 0, 1);
None of them works, but when using putty and entering the code followed by ctrl+z key everything works perfectly, so can anyone tell me exactly how does putty sends this ctrl+z to the serial port? Or if possible give a solution to this problem in c#?
The reply back from the modem every time I try the c# codes given above is:
+CME ERROR: 100
Serial Port Initialization:
port.PortName = "COM3";
port.BaudRate = 115200;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReadTimeout = 300;
port.WriteTimeout = 300;
port.Encoding = Encoding.GetEncoding("iso-8859-1");
port.DataReceived += new SerialDataReceivedEventHandler(this.port_DataReceived);
port.Open();
port.DtrEnable = true;
port.RtsEnable = true;
Find a ASCII map like this for the ctrl codes. Looks like for ctrl Z you need an ASCII 0x26. I would define it something like
char CtrlZ = (char)26;
char CR = (char)13;
serialport1.WriteLine(string.Format("whatever{0}{1}",CtrlZ, CR));
Try "whatever\u001A" or "whatever" Sleep "\u001A".
Also check the whole sequence of commands/responses you're sending/receiving through the connection.
This is an example, to be adapted to your specific case.
//TODO initialize the serialConnection and open it
//TODO specific commands...
serialConnection.WriteLine("AT+CPIN=\"1234\""); // replace according to your real situation
var response = serialConnection.ReadExisting();
Console.WriteLine("pin resp: " + response);
Thread.Sleep(200);
//TODO other specific commands?
serialConnection.Write("whatever");
//Thread.Sleep(200); uncomment this if it helps
serialConnection.Write(new byte[]{26}, 0, 1); // or Write("\u001A")
response = serialConnection.ReadExisting();
Console.WriteLine("ctrl-z resp: {0}", response);
//closing stuff, etc...
I am trying to write a program that makes a phone call via bluetooth
and return my balance (money). I am using the 32feet.net bluetooth api.
BluetoothAddress addr = device.DeviceAddress;
BluetoothEndPoint rep = new BluetoothEndPoint(addr, BluetoothService.Handsfree);
BluetoothClient cli = new BluetoothClient();
cli.Connect(rep);
Stream peerStream = cli.GetStream();
String dialCmd4 = "ATD*100#;\r";
Byte[] sRes = new Byte[200];
Byte[] dcB = System.Text.Encoding.ASCII.GetBytes(dialCmd4);
peerStream.Write(dcB, 0, dcB.Length);
peerStream.Read(sRes, 0, 199);
string t4 = "\n\r----------\n\r" + System.Text.Encoding.ASCII.GetString(sRes);
peerStream.Close();
cli.Close();
This code make a regular call but doesn't return a message containing my balance,
and in the phone I can see this message "number not assigned".
Using ATD to send SS (supplementary service) USSD (Unstructured Supplementary Service Data) commands will in the very, very, very best case only work for a small subset (or not at all. When you enter those number using the MMI they are parsed by a completely different entity than the one parsing AT commands).
What you really want to do is to use those AT commands that have specifically been written to support sending SS or USSD. For USSD you use
AT+CUSD=[<n>[,<str>[,<dcs>]]]
See the 3GPP 27.007 specification for details.
I have been working with Monodroid for a few days and still can't figure out how to send a command through Bluetooth.
This is my scenario: I have a Tablet/Cellphone working with Android 2.1+ and need to send and receive data to a Bluetooth printer (in bytes).
What i managed so far:
using Android.Bluetooth; // library necessary
BluetoothAdapter bth = BluetoothAdapter.DefaultAdapter;
if (!bth.IsEnabled)
bth.Enable();
ICollection<BluetoothDevice> bthD = bth.BondedDevices;
foreach (BluetoothDevice d in bthD)
{
if (d.Name == "DPP-350")
{
Java.Util.UUID UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
// Get the BLuetoothDevice object
BluetoothSocket s = d.CreateRfcommSocketToServiceRecord(UUID);
s.Connect();
// Try to send command
...
s.Close()
}
}
The program asks for the pairing info, with is done correctly.
I have tried many ways to send the command:
// the command
// Self_Test = Chr(27) + Chr(84) = ESC T
byte[] dBytes = System.Text.Encoding.GetEncoding(1252).GetBytes(Self_Test);
// wont work
new Java.IO.ObjectOutputStream(s.OutputStream).Write(dBytes);
// wont work
System.IO.Stream st = s.OutputStream;
if (st.CanWrite)
{
st.Write(dBytes, 0, dBytes.Length);
st.Flush();
}
// wonk work
s.OutputStream.Write(dBytes, 0, dBytes.Length);
s.OutputStream.Flush();
No error is raised. I'm running out of options here...
Thanks in advance!
I know this is a very old thread, but I wanted to post a reply so others will know the answer. I too searched hard with no luck.
s.OutputStream.BeginWrite(buffer, 0, buffer.Length,new AsyncCallback(delegate {}), State.Connected);
Thanks.
I've written the following code to (successfully) connect to a socks5 proxy.
I send a user/pw auth and get an OK reply (0x00), but as soon as I tell the proxy to connect to whichever ip:port, it gives me 0x01 (general error).
Socket socket5_proxy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint proxyEndPoint = new IPEndPoint(IPAddress.Parse("111.111.111.111"), 1080); // proxy ip, port. fake for posting purposes.
socket5_proxy.Connect(proxyEndPoint);
byte[] init_socks_command = new byte[4];
init_socks_command[0] = 0x05;
init_socks_command[1] = 0x02;
init_socks_command[2] = 0x00;
init_socks_command[3] = 0x02;
socket5_proxy.Send(init_socks_command);
byte[] socket_response = new byte[2];
int bytes_recieved = socket5_proxy.Receive(socket_response, 2, SocketFlags.None);
if (socket_response[1] == 0x02)
{
byte[] temp_bytes;
string socks5_user = "foo";
string socks5_pass = "bar";
byte[] auth_socks_command = new byte[3 + socks5_user.Length + socks5_pass.Length];
auth_socks_command[0] = 0x05;
auth_socks_command[1] = Convert.ToByte(socks5_user.Length);
temp_bytes = Encoding.Default.GetBytes(socks5_user);
temp_bytes.CopyTo(auth_socks_command, 2);
auth_socks_command[2 + socks5_user.Length] = Convert.ToByte(socks5_pass.Length);
temp_bytes = Encoding.Default.GetBytes(socks5_pass);
temp_bytes.CopyTo(auth_socks_command, 3 + socks5_user.Length);
socket5_proxy.Send(auth_socks_command);
socket5_proxy.Receive(socket_response, 2, SocketFlags.None);
if (socket_response[1] != 0x00)
return;
byte[] connect_socks_command = new byte[10];
connect_socks_command[0] = 0x05;
connect_socks_command[1] = 0x01; // streaming
connect_socks_command[2] = 0x00;
connect_socks_command[3] = 0x01; // ipv4
temp_bytes = IPAddress.Parse("222.222.222.222").GetAddressBytes(); // target connection. fake ip, obviously
temp_bytes.CopyTo(connect_socks_command, 4);
byte[] portBytes = BitConverter.GetBytes(3333);
connect_socks_command[8] = portBytes[0];
connect_socks_command[9] = portBytes[1];
socket5_proxy.Send(connect_socks_command);
socket5_proxy.Receive(socket_response);
if (socket_response[1] != 0x00)
MessageBox.Show("Damn it"); // I always end here, 0x01
I've used this as a reference: http://en.wikipedia.org/wiki/SOCKS#SOCKS_5
Have I completely misunderstood something here? How I see it, I can connect to the socks5 fine. I can authenticate fine. But I/the proxy can't "do" anything?
Yes, I know the proxy works.
Yes, the target ip is available and yes the target port is open/responsive.
I get 0x01 no matter what I try to connect to.
Any help is VERY MUCH appreciated!
Thanks,
Chuck
You might be getting bitten by endianness. Is BitConverter.GetBytes returning you the right bytes, for instance? Did you step through it and check if your byte arrays contain what you expect them to?
That looks like little endian, and networking-related things usually use big endian. BitConverter always uses system endianness, so you'll have to reverse bytes by hand if you're running on a little endian system (which you would seem to be doing). BitConverter.IsLittleEndian will tell you whether your system is little endian or not.
Also, it'd be a good idea to cast your value to short, e.g. BigConverter.GetBytes((short)3333). That way you'll get just the two bytes you need.