I have a Bluetooth OBDII dongle for my car (the brand is Veepeak), and I'm trying to write a Windows app that can communicate with it. So far it seems that I'm able to connect to the device from my laptop, send commands, and receive some sort of response, but the responses I receive are not what I expect. I am using the 32feet communication library to handle the Bluetooth stuff.
Here is the code I am using to connect and also the functions I am using to send messages:
BluetoothClient client;
Stream stream;
client = new BluetoothClient();
Guid uuid = new Guid("00001101-0000-1000-8000-00805f9b34fb");
client.BeginConnect(SelectedDevice.DeviceAddress, uuid, bluetoothClientConnectCallback, client);
private void bluetoothClientConnectCallback(IAsyncResult result)
{
client = (BluetoothClient)result.AsyncState;
client.EndConnect(result);
clientConnected = true;
stream = client.GetStream();
UIWriteLine("Client connected");
}
private string sendMessage(string message)
{
byte[] encodedMessage = Encoding.ASCII.GetBytes(message);
stream.Write(encodedMessage, 0, encodedMessage.Length);
Thread.Sleep(100);
int count = 0;
byte[] buffer = new byte[1024];
string retVal = string.Empty;
count = stream.Read(buffer, 0, buffer.Length);
retVal += Encoding.ASCII.GetString(buffer, 0, count);
return retVal.Replace("\n", "");
}
private string getValue(string pid)
{
byte[] encodedMessage = Encoding.ASCII.GetBytes(pid + "\r");
stream.Write(encodedMessage, 0, encodedMessage.Length);
Thread.Sleep(100);
bool cont = true;
int count = 0;
byte[] buffer = new byte[1024];
string retVal = string.Empty;
while (cont)
{
count = stream.Read(buffer, 0, buffer.Length);
retVal += Encoding.ASCII.GetString(buffer, 0, count);
if (retVal.Contains(">"))
{
cont = false;
}
}
return retVal.Replace("\n", "");
}
I use the sendMessage method to send AT commands, and the getValue method to get a specific PID (these methods are borrowing code from an OBDII library I found here).
When I send AT commands, I seem to only get an echo of whatever I send, and when I send PIDs, I get a response of a single question mark, which to my understanding means the command is invalid.
Is it possible that my dongle does not have an ELM327? Am I doing something wrong with my Bluetooth communication or is my UUID wrong? Thanks.
I also have a Veepeak. It comes quite highly recommended in the relevant reviews and works very well with the available trial apps and my android phone. I'm struggling with initialization in my own python app, however.
On the python based application that I'm developing on the raspi, I have to open a 'virtual' serial port that is mapped to the previously paired device by it's mac address. The pairing and noting of the mac address is done at the operating system level with generic bluetooth tools.
Related
The server is written in c# and works correctly with a client I made in c#, now i'm trying to make an android client but the server doesn't get the real message, it gets just a lot of question marks.
Here is the server
TcpListener listen = new TcpListener(IPAddress.Any, 1200);
TcpClient client;
listen.Start();
client = listen.AcceptTcpClient();
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
int data = stream.Read(buffer, 0, client.ReceiveBufferSize);
string message = Encoding.Unicode.GetString(buffer, 0, data);
Console.WriteLine(message);
this is the Android client
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString()
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
For example if I send the message "Hello", the server prints "???????????" and it happens the same for any message I send, even just 1 letter
I also tried with different methods like this one but the result is the same:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes(str);
Change:
string message = Encoding.Unicode.GetString(buffer, 0, data);
into:
string message = Encoding.UTF8.GetString(buffer, 0, data);
Try also UTF16. I think java uses this encoding now.
So my server and chat client are made from 2 different C# TCP tutorials.You may recognize 1 if not both of them and I have made my own modifications to them to fit my own style. When I tried both they worked perfectly fine with 0 loss, but my version has exactly a 50% loss rate.
For instance:
1. A client connects: Data received
2. A client sends text: No Data
3. A client sends text: Data received
4. A client sends text: No Data
The server code is as follows:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsFormsApplication2
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Hashtable clientsList = new Hashtable();
private System.Windows.Forms.TextBox output;
private delegate void ObjectDelegate(String text);
private ObjectDelegate del;
public Server(System.Windows.Forms.TextBox setOut)
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.IsBackground = true;
this.listenThread.Start();
output = setOut;
del = new ObjectDelegate(outputTextToServer);
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
addClient(client);
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.IsBackground = true;
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
String text = getData(clientStream);
del.Invoke(text); //Used for Cross Threading & sending text to server output
//if filter(text)
sendMessage(tcpClient);
//System.Diagnostics.Debug.WriteLine(text); //Spit it out in the console
}
tcpClient.Close();
}
private void outputTextToServer(String text)
{
if (output.InvokeRequired)
{
// we then create the delegate again
// if you've made it global then you won't need to do this
ObjectDelegate method = new ObjectDelegate(outputTextToServer);
// we then simply invoke it and return
output.Invoke(method, text);
return;
}
output.AppendText(Environment.NewLine + " >> " + text);
}
private String getData(NetworkStream stream)
{
int newData;
byte[] message = new byte[4096];
ASCIIEncoding encoder = new ASCIIEncoding();
newData = stream.Read(message, 0, 4096);
String text = encoder.GetString(message, 0, newData); //Translate it into text
text = text.Substring(0, text.IndexOf("$")); //Here comes the money
return text;
}
private void addClient(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
String dataFromClient = getData(clientStream);
if (clientsList.Contains(dataFromClient))
{
Console.WriteLine(dataFromClient + " Tried to join chat room, but " + dataFromClient + " is already in use");
//broadcast("A doppleganger of " + dataFromClient + " has attempted to join!", dataFromClient, false);
}
else
{
clientsList.Add(dataFromClient, tcpClient);
//broadcast(dataFromClient + " Joined ", dataFromClient, false);
del.Invoke(dataFromClient + " Joined chat room ");
//handleClinet client = new handleClinet();
//client.startClient(clientSocket, dataFromClient, clientsList);
}
}
private Boolean connectionAlive(NetworkStream stream)
{
byte[] message = new byte[4096];
int bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = stream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
return false;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
//clientsList.Remove
return false;
}
return true;
}
private void sendMessage(TcpClient client)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
}
And here's my client code
using System;
using System.Windows.Forms;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public delegate void newDelegate();
public newDelegate myDelegate;
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
newMsg();
}
private void newMsg()
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
textBox2.Text = "";
}
private void button2_Click(object sender, EventArgs e)
{
readData = "Connecting to Chat Server ...";
msg();
clientSocket.Connect(txtIP.Text, int.Parse(txtPort.Text));
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
myDelegate = new newDelegate(disconnect);
Thread ctThread = new Thread(getMessage);
ctThread.IsBackground = true;
ctThread.Start();
button2.Enabled = false;
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
buffSize = clientSocket.ReceiveBufferSize;
try
{
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
catch
{
Invoke(myDelegate);
return;
}
}
}
private void disconnect()
{
button2.Enabled = true;
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textBox1.AppendText(Environment.NewLine + " >> " + readData);
//textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + readData;
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
newMsg();
}
}
private void cmdHost_Click(object sender, EventArgs e)
{
Server serv = new Server(txtLog);
}
}
}
This code is obviously a work in progress and sorry in advance for messiness. Any other suggestions to the code are also welcome.
Okay, this is starting to get a bit long.
There's multiple errors in your code. Starting with the server code:
As Damien noted, you're trying to read each "message" twice - first in HandleClientComm, then again in getData. The stream no longer has the original data, so you're just throwing one of the reads away completely (thus the suspicious 50% "packet" loss)
Later, in getData, you discard all the data in the stream after the first $. While this is obviously an attempt at handling message framing (since TCP is a stream-based protocol, not a message-based protocol), it's a silly one - you're throwing the data away. The reason this didn't show in your testing is that 1) Windows treats local TCP very differently from remote TCP, 2) You'd need to be actually able to send two messages fast enough to make them "blend" together in the stream. That means either sending two messages in about 200ms (default TCP buffering) or blocking on reads.
You keep Flushing the network stream. This doesn't actually do anything, and even if it did, you wouldn't want to do that.
connectionAlive reads from the shared socket - this is always a bad idea. Never have more than one reader - multiple readers don't work with stream-based protocols. It doesn't seem you're using it in your sample code, but beware of trying to.
The commented out clientList.Remove would of course be a cross-thread access of a shared field. If you want to do it like this, you'll have to ensure the concurrent access is safe - either by using ConcurrentDictionary instead of HashSet, or by locking around each write and read of clientList.
You're expecting to get the whole message in one Read. That may be fine for a simple chat client, but it's bad TCP anyway - you need to read until you find your message terminator. If I send a message big enough, your code will just drop dead on text.IndexOf("$").
There's a lot of "style" issues as well, although this isn't code review, so let me just list some: using ancient technology, synchronous sockets for the server, mixing multi-threaded code with GUI at will. This is mostly about maintainability and performance, though - not correctness.
Now, the client is a bit simpler:
Again, don't Flush the network stream.
Don't use background threads if you don't have to. Simply make sure to terminate the connections etc. properly.
Disconnect should actually disconnect. It's not that hard, just close the TcpClient.
What is readData = "" + returndata supposed to do? That's just silly.
You're ignoring the return value of Read. This means that you have no idea how many bytes of data you read - which means your returnData string actually contains the message followed by a few thousand \0 characters. The only reason you don't see them in output is because most of Windows uses \0 as the string terminator ("it made sense at the time"). .NET doesn't.
Again, the Read expects the whole message at once. Unlike the server, this isn't going to crash the client, but your code will behave differently (e.g. an extra \r\n >> even though it's not a separate message.
The style issues from the server also apply here.
As a side-note, I've recently made a simplified networking sample that handles a simple chat client-server system using more modern technologies - using await-based asynchronous I/O instead of multi-threading, for example. It's not production-ready code, but it should show the ideas and intent quite clearly (I also recommend having a look at the first sample, "HTTP-like TCP communication"). You can find the full source code here - Networking Part 2.
I'm running a c# program and I need to play a video on vlc on another process and feed it with commands.
I'm not looking for something like axVLCPlugin21
I only need basic play/pause/volume commands.
What is the easiest way to achieve this?
I tried this, but the stdin writing failed
Process p = Process.Start(#"C:\...\a.mp4");
p.StandardInput.Write("comand");
I also found the console Std In redirection didn't work to the VLC process. The only way I could get the VLC console interface to work is with SendKeys, which isn't a very nice way of doing it.
VLC also supports socket connections for the same interface though, and this seems to work quite well. Here's an example of how to connect and send/receive commands and responses.
static void Main()
{
IPEndPoint socketAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 54165);
var vlcServerProcess = Process.Start(#"C:\Program Files (x86)\VideoLAN\VLC\vlc.exe", "-I rc --rc-host " + socketAddress.ToString());
try
{
Socket vlcRcSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
vlcRcSocket.Connect(socketAddress);
// start another thread to look for responses and display them
Task listener = Task.Factory.StartNew(() => Receive(vlcRcSocket));
Console.WriteLine("Connected. Enter VLC commands.");
while(true)
{
string command = Console.ReadLine();
if (command.Equals("quit")) break;
Send(vlcRcSocket, command);
}
Send(vlcRcSocket, "quit"); // close vlc rc interface and disconnect
vlcRcSocket.Disconnect(false);
}
finally
{
vlcServerProcess.Kill();
}
}
private static void Send(Socket socket, string command)
{
// send command to vlc socket, note \n is important
byte[] commandData = UTF8Encoding.UTF8.GetBytes(String.Format("{0}\n", command));
int sent = socket.Send(commandData);
}
private static void Receive(Socket socket)
{
do
{
if (socket.Connected == false)
break;
// check if there is any data
bool haveData = socket.Poll(1000000, SelectMode.SelectRead);
if (haveData == false) continue;
byte[] buffer = new byte[socket.ReceiveBufferSize];
using (MemoryStream mem = new MemoryStream())
{
while (haveData)
{
int received = socket.Receive(buffer);
mem.Write(buffer, 0, received);
haveData = socket.Poll(1000000, SelectMode.SelectRead);
}
Console.WriteLine(Encoding.UTF8.GetString(mem.ToArray()));
}
} while (true);
}
You have to redirect the standard input of the process you are creating. See the sample on this page for details.
I am trying to send a request to an existing server solution and write out the results. The server is sending a total of 4 messages with my particular request but the number of messsages back can vary depending on the initial query.
I am able to successfully send the query to the server but when it comes to reading the response i can only read one message. The server logs show that 4 were sent back.
Please help.
IPHostEntry hostEntry = Dns.GetHostEntry(server_textbox.Text);
IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
string data = String.Empty;
testclient = new TcpClient(server_textbox.Text, port);
testclient.ReceiveBufferSize = 1024;
testclient.SendBufferSize = 1024;
NetworkStream netStream = testclient.GetStream();
Byte[] message_byte = new System.Text.ASCIIEncoding().GetBytes(msg2);
netStream.Write(message_byte, 0, message_byte.Length);
Byte[] returnMessage = new byte[1024];
Int32 totalBytesReceived = 0;
Int32 bytesReceived = 0;
try
{
while ((bytesReceived = netStream.Read(returnMessage, totalBytesReceived, returnMessage.Length)) > 0)
{
totalBytesReceived += bytesReceived;
data += "\n" + ASCIIEncoding.ASCII.GetString(returnMessage);
bytesReceived = 0;
}
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
result_box.Text += data;
netStream.Close();
testclient.Close();
}
My guess is that all your messages are read in the first Read. When the server replies, all the data gets stuck in the windows receive buffer and gets read all at once.
I would recommend using Wireshark, which is more or less mandatory when doing network programming. You'll be able to see the 4 messages coming back from the server as at least 4 different tcp packets.
I'm creating an RCON web application for Call of Duty Black Ops. COD uses rcon and udp packets to send and receive information. Using the following code, I've been able to send and receive information with a COD4 server. Now that COD7 is out, I'm no longer receiving responses back.
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.Connect(IPAddress.Parse(gameServerIP), gameServerPort);
string command;
command = password + " " + rconCommand;
byte[] bufferTemp = Encoding.ASCII.GetBytes(command);
byte[] bufferSend = new byte[bufferTemp.Length + 5];
//intial 5 characters as per standard
bufferSend[0] = byte.Parse("255");
bufferSend[1] = byte.Parse("255");
bufferSend[2] = byte.Parse("255");
bufferSend[3] = byte.Parse("255");
bufferSend[4] = byte.Parse("02");
int j = 5;
for (int i = 0; i < bufferTemp.Length; i++)
{
bufferSend[j++] = bufferTemp[i];
}
//send rcon command and get response
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
client.Send(bufferSend, SocketFlags.None);
//big enough to receive response
byte[] bufferRec = new byte[65000];
client.Receive(bufferRec);
Does anyone have any ideas? Black Ops ships with its own Rcon tool that I've tried using Wireshark to capture the outgoing packets to copy. The outgoing packets between my application and theirs are next to identical, except I get no replies back when I use mine.
i knwo why cause i make a tool myself.
What's wrong in your code is that : bufferSend[4] = byte.Parse("02");
the good one is : bufferSend[4] = byte.Parse("00");
Try it, works for me!
Here my piece of code, i use a thread to run it:
how to do:
in your class set the private command, then call the worker, when thread finish, just read the private response.
private IPEndPoint ipendpoint;
private string command;
private string response;
private void worker()
{
UdpClient client = new UdpClient();
var result1 = string.Empty;
var result2 = string.Empty;
bool sent = false;
bool DoubleTrame = false;
Byte[] bufferTemp = Encoding.ASCII.GetBytes(this.command);
Byte[] bufferSend = new Byte[bufferTemp.Length + 5];
Byte[] bufferRec;
Byte[] bufferRec2;
bufferSend[0] = Byte.Parse("255");
bufferSend[1] = Byte.Parse("255");
bufferSend[2] = Byte.Parse("255");
bufferSend[3] = Byte.Parse("255");
bufferSend[4] = Byte.Parse("00");
for (int i = 0; i < bufferTemp.Length; i++)
{
bufferSend[i + 5] = bufferTemp[i];
}
while (!sent)
{
client.Send(bufferSend, bufferSend.Length, ipendpoint);
Thread.Sleep(200);
if (client.Available > 0)
{
sent = true;
if (client.Available > 1200)
{
DoubleTrame = true;
}
}
}
bufferRec = client.Receive(ref ipendpoint);
if (DoubleTrame)
{
bufferRec2 = client.Receive(ref ipendpoint);
result2 = Encoding.ASCII.GetString(bufferRec2);
if (result2.Contains("\n\n"))
{
result2 = result2.Remove(result2.IndexOf("\n\n"));
}
result2 = result2.Substring(12);
}
result1 = Encoding.ASCII.GetString(bufferRec);
this.response = result1 + result2;
}
I am doing a similar thing using vb.net
I have written rcon tools for COD MW and COD WW no problem however so far I have not been able to get a response back from my black ops server.
In fact, i have done the saame thing as you, i used WireShark to look the byte sent and received with the default rconTool provide in steam for Black Ops.
Other tip:
The command "status" give you many information about the current players but not the team of each.
You better use "teamstatus" instead, this one give you the same information but with the team of each player.
I have trouble right now to perfectly parse the response, but to give a readeable answer use this:
replace :
byte[] bufferRec = new byte[65000];
client.Receive(bufferRec);
by:
byte[] bufferRec;
while (client.Available == 0)
{
Thread.Sleep(10);
}
client.Receive(bufferRec);
string response=Encoding.ASCII.GetString(bufferRec);
var list= response.Split('\n');
This way you'll have an array with each player separate in a row.
Btw: i'm mack, i'm now registered, wasn't this night
Edit: oups, i didn't notice you've already tried the teamstatus command.
You need to look at the number return by client.Avalaible, because the server only send 1168 byte at once, so if client.Avalaible>1168, you need a second buffer to get the second flow with client.receive.
In fact there's only two possible number for client.avalaible : 1168 and 2336 (yes, the double) i don't know why, but they didn't managed to send the exact number of data, the buffer is always full or empty.
I noticed also that the second receive() is like "paste" on the first buffer.
YOu'll have at hte begginig the complementary information of the first Receive(), then the "noise" of the old one.
Just take a look, you will see what i mean.
I'm at work now, but this evening i will post my code to help.