C# последовательный терминал bluetooth с InTheHand - PullRequest
0 голосов
/ 20 июня 2020

Как?!

Все, что мне нужно, это простое последовательное соединение между моим приложением C# и чем-то еще - приложением Bluetooth-терминала на Android и, в конечном итоге, Arduino.

Однако , ничего из того, что я пробовал, не работает.

Терминальное приложение Android может подключиться к нему, и C# получает данные, но не может ничего отправить.

    public partial class Bluetooth : Form
    {
        BluetoothListener _Listener;

        public Bluetooth()
        {
            InitializeComponent();

            _Listener = new BluetoothListener(BluetoothService.SerialPort);
            _Listener.Start();
            Thread t = new Thread(new ThreadStart(Listen));
            t.Start();
        }

        private void Listen()
        {
            while(true)
            {
                if(_Listener.Pending())
                {
                    BluetoothClient c = _Listener.AcceptBluetoothClient();
                    ListenProcessor p = new ListenProcessor(c);
                }
            }
        }

        class ListenProcessor
        {
            private BluetoothClient _Client;
            public ListenProcessor(BluetoothClient c) { 
                _Client = c;
                Thread t = new Thread(new ThreadStart(Do));
                t.Start();
            }

            private void Do()
            {
                Stream s = _Client.GetStream();
                while (true)
                {
                    if (s.CanRead)
                    {
                        int a = int.Parse(s.Length.ToString());
                        byte[] buffer = new byte[a];
                        s.Read(buffer, 0, a);
                        string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
                        //if (InvokeRequired)
                        //{
                        //    BeginInvoke((MethodInvoker)delegate { textBoxReceived.AppendText(msg); });
                        //}
                        //else
                        //{
                        //    textBoxReceived.AppendText(msg);
                        //}
                        _Client.Client.Send(buffer);
                    }
                }
            }
        }


        private void textBoxInput_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                string msg = textBoxInput.Text.Trim();
                _Client.Client.Send(System.Text.ASCIIEncoding.ASCII.GetBytes(msg));
                textBoxInput.Text = string.Empty;
                textBoxReceived.AppendText("> " + msg);
                _Client.Client.Send(buffer); // System.Net.Sockets.SocketException: 'A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied'
            }
        }
    }

Итак, я попробовал наоборот, чтобы Windows подключился к Android приложению терминального сервера Bluetooth, и снова Windows не может отправлять данные.

    public partial class Bluetooth : Form
    {
        private BluetoothClient _Client;

        public Bluetooth()
        {
            InitializeComponent();
            comboBoxDevices.Enabled = false;
            buttonConnect.Enabled = false;
            textBoxReceived.Enabled = false;
            textBoxInput.Enabled = false;
            _Client = new BluetoothClient();

            BluetoothDeviceInfo di = _Client.PairedDevices.FirstOrDefault(z => z.DeviceName == "RWB");
            
            di.SetServiceState(BluetoothService.SerialPort, true);
            _Client.Connect(di.DeviceAddress, BluetoothService.SerialPort);
            if (!di.Connected)
            {
                MessageBox.Show("Connecting failed.", "Connecting failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            
            Thread t = new Thread(new ThreadStart(HandleConnection));
            t.Start();
        }


        private void textBoxInput_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                string msg = textBoxInput.Text.Trim();
                _Client.Client.Send(System.Text.ASCIIEncoding.ASCII.GetBytes(msg)); // System.Net.Sockets.SocketException: 'A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied'
                textBoxInput.Text = string.Empty;
                textBoxReceived.AppendText("> " + msg);
            }
        }

        private void HandleConnection()
        {
            Stream s = _Client.GetStream();
            while (true)
            {
                if (!_Client.Connected) { break; }

                if (s.CanRead)
                {
                    int a = int.Parse(s.Length.ToString());
                    byte[] buffer = new byte[a];
                    s.Read(buffer, 0, a);
                    string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
                    if(InvokeRequired)
                    {
                        BeginInvoke((MethodInvoker)delegate { textBoxReceived.AppendText(msg); });
                    }
                    else
                    {
                        textBoxReceived.AppendText(msg);
                    }
                }
            }
        }
    }

И что-то действительно странное, кажется, происходит внутри BluetoothClient.Client. Телефонный код всегда видит Available == 0, когда я отправляю данные из Android, а другой Доступен - >0.

[! [Введите описание изображения здесь] [1]] [1]



  [1]: https://i.stack.imgur.com/oiB5j.png

So: how to do in C# simple serial communication over Bluetooth?
Is it impossible?

1 Ответ

0 голосов
/ 21 июня 2020

После серии проб и ошибок вот кое-что, что, похоже, работает. Он демонстрирует, что C# является одновременно клиентом и сервером.

using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Can
{
    public partial class Bluetooth : Form
    {
        BluetoothListener _Listener;
        private BluetoothClient _ConnectedClient;
        private bool _Go;
        private Thread _ListenForConnection;
        private Thread _ListenToConnected;

        public Bluetooth()
        {
            InitializeComponent();
            _Go = true;
            comboBoxDevices.Enabled = false;
            buttonConnect.Enabled = false;
            textBoxReceived.Enabled = false;
            textBoxInput.Enabled = false;
            BluetoothClient c = new BluetoothClient();

            foreach (BluetoothDeviceInfo di in c.PairedDevices)
            {
                comboBoxDevices.Items.Add(di.DeviceName ?? di.DeviceAddress.ToString());
            }
            comboBoxDevices.Enabled = true;
            buttonConnect.Enabled = comboBoxDevices.Items.Count > 0;

            _Listener = new BluetoothListener(BluetoothService.SerialPort);
            _Listener.Start();
            _ListenForConnection = new Thread(new ThreadStart(ListenForConnection));
            _ListenForConnection.Start();
        }

        private void AppendText(string text)
        {
            BeginInvoke((MethodInvoker)delegate
            {
                textBoxReceived.AppendText(text + Environment.NewLine);
            });
        }

        /// <summary>
        /// Server mode: listen for devices that want to connect.
        /// </summary>
        private void ListenForConnection()
        {
            while (_Go)
            {
                if (_Listener.Pending())
                {
                    if (_ConnectedClient != null)
                    {
                        BluetoothClient c = _Listener.AcceptBluetoothClient();
                        c.GetStream().Write(ASCIIEncoding.ASCII.GetBytes("Go away."), 0, 8);
                        c.Close();
                        c.Dispose();
                        AppendText($"Refused connection from {c.RemoteMachineName} because already connected to {_ConnectedClient.RemoteMachineName}.");
                        continue;
                    }

                    _ConnectedClient = _Listener.AcceptBluetoothClient();
                    BluetoothDeviceInfo di = _ConnectedClient.PairedDevices.FirstOrDefault(z => z.DeviceName == _ConnectedClient.RemoteMachineName);

                    if(di == null)
                    {
                        AppendText($"Refused connection from unpaired device {_ConnectedClient.RemoteMachineName}.");
                        _ConnectedClient.Dispose();
                        _ConnectedClient = null;
                        continue;
                    }

                    AppendText("Connection incoming from " + di.DeviceName + "...");

                    _ListenToConnected = new Thread(new ThreadStart(ListenToConnected));
                    _ListenToConnected.Start();

                    AppendText("Connected.");
                    BeginInvoke((MethodInvoker)delegate
                    {
                        textBoxReceived.Enabled = true;
                        textBoxInput.Enabled = true;
                    });
                }
            }
        }

        /// <summary>
        /// Client mode: conect to a paired device.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonConnect_Click(object sender, EventArgs e)
        {
            if(_ConnectedClient != null)
            {
                _ConnectedClient.GetStream().Write(ASCIIEncoding.ASCII.GetBytes("Go away."), 0, 8);
                _ConnectedClient.Close();
                _ConnectedClient.Dispose();
                _ConnectedClient = null;
            }

            _ConnectedClient = new BluetoothClient();
            BluetoothDeviceInfo di = _ConnectedClient.PairedDevices.FirstOrDefault(z => z.DeviceName == comboBoxDevices.SelectedItem.ToString());
            if (di == null)
            {
                AppendText($"No such device: {comboBoxDevices.SelectedItem.ToString()}.");
                return;
            }

            di.SetServiceState(BluetoothService.SerialPort, true);
            _ConnectedClient.Connect(di.DeviceAddress, BluetoothService.SerialPort);
            if (!di.Connected)
            {
                AppendText("Connecting failed.");
            }
            AppendText($"Connected to {di.DeviceName} @ {di.DeviceAddress}.");
            textBoxReceived.Enabled = true;
            textBoxInput.Enabled = true;

            Thread t = new Thread(new ThreadStart(ListenToConnected));
            t.Start();
        }

        private void ListenToConnected()
        {
            Stream s = _ConnectedClient.GetStream();
            while (_Go)
            {
                if (!_ConnectedClient.Connected) { break; }

                if (s.CanRead && s.Length > 0)
                {
                    int a = int.Parse(s.Length.ToString());
                    byte[] buffer = new byte[a];
                    s.Read(buffer, 0, a);
                    string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
                    AppendText("> " + msg);
                }
            }
            _ConnectedClient.Close();
            _ConnectedClient.Dispose();
        }

        private void textBoxInput_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
            {
                string msg = textBoxInput.Text.Trim() + Environment.NewLine;
                byte[] buffer = ASCIIEncoding.ASCII.GetBytes(msg);
                try
                {
                    _ConnectedClient.GetStream().Write(buffer, 0, buffer.Length);
                    textBoxInput.Text = string.Empty;
                    textBoxReceived.AppendText("< " + msg);
                }
                catch (Exception ex)
                {
                    AppendText(ex.Message);
                }
            }
        }

        private void Bluetooth_FormClosing(object sender, FormClosingEventArgs e)
        {
            textBoxInput.Enabled = false;
            textBoxReceived.Enabled = false;
            _Go = false;
            _ListenForConnection.Join();
            _ListenToConnected.Join();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...