C#通过树莓派(3B+)蓝牙来扫描设备

最近用C#写个一个通过树莓派(Raspberry Pi)3B+的蓝牙模块来扫描电子设备。当时实现的时候也是花了些时间。现在把代码整理一下,给需要的人参考一下!

目录

NuGet Packages

NetworkPinger

SshCommunication

BTDevice

BTDeviceParser

BTDevicesExtensions

BTScanExecutor

ResultDirectoryService

BTDeviceScanner

TopProcessor

Console App


NuGet Packages

首先从NuGet上装几个package

  • log4net - 用来记录日志,实在太好用了!
  • SSH.NET - 用这个来实现通过SSH和树莓派进行通讯
  • System.ValueTuple - 这个是比较新的特新,VS2017默认不支持

 

接下里,我们就直接看代码。


NetworkPinger

这个class是用来检测能不能ping上树莓派。

    public interface INetworkPinger
    {
        bool CanPing(IPAddress ipAddress, int timeoutMilliseconds = 2000);
    }

    public class NetworkPinger : INetworkPinger
    {
        private readonly ILog _logger = LogManager.GetLogger(typeof(NetworkPinger));

        public bool CanPing(IPAddress ipAddress, int timeoutMilliseconds = 2000)
        {
            try
            {
                _logger.Info($"Try to ping {ipAddress}...");

                var ping = new Ping();
                var pingReply = ping.Send(ipAddress, timeoutMilliseconds);

                if (pingReply == null)
                    throw new Exception($"PingReply is null.");

                if (pingReply.Status != IPStatus.Success)
                    throw new Exception($"The status of PingReply \"{pingReply.Status}\" is not \"{IPStatus.Success}\".");

                _logger.Info($"Succeed in pinging {ipAddress}");
                return true;
            }
            catch (Exception exception)
            {
                _logger.Warn($"Some error happened while pinging {ipAddress}.\n{exception}");
                return false;
            }
        }
    }

 

SshCommunication

这个class就是调用用Renci.SshNet实现SSH通讯的。

  • 在调用参数中,有Func委托,委托也是实现松耦合的一种常用方式
    public interface ISshCommunicator : IDisposable
    {
        void Open();
        void Close();

        string WriteAndRead(
            string command,
            int timeoutMilliseconds = SshCommunicator.DefaultReadTimeoutMilliseconds);
        string WriteAndRead(
            string command,
            Func<string, bool> canStopEarlier,
            int timeoutMilliseconds = SshCommunicator.DefaultReadTimeoutMilliseconds);

        string ReadExistingString();
        string Read(
            Func<string, bool> canStopEarlier,
            int timeoutMilliseconds = SshCommunicator.DefaultReadTimeoutMilliseconds);
    }

    public class SshCommunicator : ISshCommunicator
    {
        public const int DefaultReadTimeoutMilliseconds = 5000;

        private bool _disposed = false;
        private SshClient _sshClient = null;
        private ShellStream _shellStream = null;
        private readonly ILog _logger = LogManager.GetLogger(typeof(SshCommunicator));
        private readonly ConnectionInfo _connectionInfo;

        public SshCommunicator(string ipAddress, string userName, string password)
        {
            _connectionInfo =
                new ConnectionInfo(
                ipAddress,
                userName,
                new PasswordAuthenticationMethod(userName, password))
                {
                    Encoding = Encoding.ASCII
                };
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;

            if (disposing)
                Close();

            _disposed = true;
        }

        public void Open()
        {
            Close();

            _sshClient = new SshClient(_connectionInfo);
            _sshClient.Connect();

            _shellStream = _sshClient.CreateShellStream("BluetoothctlShell", 512, 128, 1920, 1080, 1024 * 10);
        }

        public void Close()
        {
            if (_sshClient == null)
                return;

            try
            {
                _logger.Info("Close SSH client...");

                _shellStream.Close();
                _sshClient.Disconnect();
            }
            catch (Exception exception)
            {
                _logger.Warn($"Some error happened while closing SSH client.\n{exception}");
            }
            finally
            {
                _shellStream = null;
                _sshClient = null;
            }
        }

        public string WriteAndRead(string command, int timeoutMilliseconds = DefaultReadTimeoutMilliseconds)
        {
            IgnoreExistingStringBeforeWrite();
            Write(command);
            return Read(timeoutMilliseconds);
        }

        private void IgnoreExistingStringBeforeWrite()
        {
            var existingString = ReadExistingString();
            if (!string.IsNullOrEmpty(existingString))
                _logger.Warn($"Ignore the below existing string before write.\n{existingString}");
        }

        public string WriteAndRead(
            string command,
            Func<string, bool> canStopEarlier,
            int timeoutMilliseconds = DefaultReadTimeoutMilliseconds)
        {
            IgnoreExistingStringBeforeWrite();
            Write(command);
            return Read(canStopEarlier, timeoutMilliseconds);
        }

        private void Write(string command)
        {
            _logger.Info($"Write \"{command}\"...");
            _shellStream.WriteLine(command);
        }

        public string Read(int timeoutMilliseconds = DefaultReadTimeoutMilliseconds)
        {
            _logger.Info($
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值