Nanoframework 操作单片机蓝牙配置WIFI的案例

这篇具有很好参考价值的文章主要介绍了Nanoframework 操作单片机蓝牙配置WIFI的案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Nanoframework 操作单片机蓝牙配置WIFI的案例

通过Nanoframework的蓝牙配置Wifi的名称和密码

下面是基本需要的工具

  1. ESP32设备一个 需要支持蓝牙和wifi,一般情况的ESP32都支持wifi和蓝牙,当前教程使用的ESP32的接口是Type-C
    设备实物图片:
    Nanoframework 操作单片机蓝牙配置WIFI的案例

    1. 部署好的ESP32NanoFramework环境

      刷支持蓝牙的固件

      nanoff --update --target ESP32_BLE_REV0 --serialport COM5 --fwversion 1.8.1.292 --baud 1500000
      
    2. VS扩展安装好NanoFramework扩展

    3. 准备好手机下载蓝牙调试APP,我用的是这个
      Nanoframework 操作单片机蓝牙配置WIFI的案例

实现通过蓝牙配置单片机的WIFI

using nanoFramework.Device.Bluetooth;
using nanoFramework.Device.Bluetooth.GenericAttributeProfile;
using nanoFramework.Networking;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using static Gotrays.Program;

namespace Gotrays
{
    public class Program
    {
        static GattLocalCharacteristic _readCharacteristic;
        static GattLocalCharacteristic _readWriteCharacteristic;

        // Read/Write Characteristic value
        static byte _redValue = 128;
        static byte _greenValue = 128;
        static byte _blueValue = 128;

        public static void Main()
        {
            var wifi = ConfigHelper.GetWifi();

            // 如果存在wifi配置尝试链接wifi
            if (wifi.Password != null)
            {
                try
                {
                    CancellationTokenSource cs = new(60000);
                    var success = WifiNetworkHelper.ConnectDhcp(wifi.Name, wifi.Password, requiresDateTime: true, token: cs.Token);
                }
                catch (Exception)
                {
                    Debug.WriteLine("尝试链接WiFi失败");
                }

            }
            // BluetoothLEServer是一个单例对象,因此获得它的实例。对象是在您第一次访问它时创建的
            // 可以释放内存。
            BluetoothLEServer server = BluetoothLEServer.Instance;

            // 给设备命名
            server.DeviceName = "TokenIOT";

            // 定义一些自定义uid
            Guid serviceUuid = new Guid("A7EEDF2C-DA87-4CB5-A9C5-5151C78B0057");
            Guid readCharUuid = new Guid("A7EEDF2C-DA88-4CB5-A9C5-5151C78B0057");
            Guid readStaticCharUuid = new Guid("A7EEDF2C-DA89-4CB5-A9C5-5151C78B0057");
            Guid readWriteCharUuid = new Guid("A7EEDF2C-DA8A-4CB5-A9C5-5151C78B0057");

            // GattServiceProvider用于创建和发布主服务定义。
            // 将自动创建一个额外的设备信息服务。
            GattServiceProviderResult result = GattServiceProvider.Create(serviceUuid);
            if (result.Error != BluetoothError.Success)
            {
                return;
            }

            GattServiceProvider serviceProvider = result.ServiceProvider;

            // 从提供者处创建主服务
            GattLocalService service = serviceProvider.Service;

            #region Static read characteristic
            // 现在我们给服务添加一个特性

            //如果读取值不会改变,那么你可以使用Static值
            DataWriter sw = new DataWriter();
            sw.WriteString("这是蓝牙示例1");

            GattLocalCharacteristicResult characteristicResult = service.CreateCharacteristic(readStaticCharUuid,
                 new GattLocalCharacteristicParameters()
                 {
                     CharacteristicProperties = GattCharacteristicProperties.Read,
                     UserDescription = "我的静态特性",
                     StaticValue = sw.DetachBuffer()
                 });

            if (characteristicResult.Error != BluetoothError.Success)
            {
                // An error occurred.
                return;
            }
            #endregion

            #region Create Characteristic for dynamic Reads 

            // 对于变更为业务的数据,增加“读特性”
            // 我们还希望连接的客户端在值改变时得到通知,所以我们添加了notify属性
            characteristicResult = service.CreateCharacteristic(readCharUuid,
                new GattLocalCharacteristicParameters()
                {
                    CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Notify,
                    UserDescription = "我的阅读特点"
                });

            if (characteristicResult.Error != BluetoothError.Success)
            {
                // An error occurred.
                return;
            }

            // 查阅我们的read特性
            _readCharacteristic = characteristicResult.Characteristic;

            // 每次从客户端请求该值时,都会调用此事件
            _readCharacteristic.ReadRequested += ReadCharacteristic_ReadRequested;

            #endregion

            #region Create Characteristic for RGB read/write
            characteristicResult = service.CreateCharacteristic(readWriteCharUuid,
                new GattLocalCharacteristicParameters()
                {
                    CharacteristicProperties = GattCharacteristicProperties.Read | GattCharacteristicProperties.Write,
                    UserDescription = "My Read/Write Characteristic"
                });

            if (characteristicResult.Error != BluetoothError.Success)
            {
                // An error occurred.
                return;
            }

            // 查阅我们的read特性
            _readWriteCharacteristic = characteristicResult.Characteristic;

            //每次从客户端请求该值时,都会调用此事件
            _readWriteCharacteristic.WriteRequested += _readWriteCharacteristic_WriteRequested;
            _readWriteCharacteristic.ReadRequested += _readWriteCharacteristic_ReadRequested;

            #endregion

            #region Start Advertising

            // 一旦所有的特征已经创建,你需要广告的服务,所以
            // 其他设备可以看到它。这里我们也说设备也可以连接
            // 设备可以看到它。
            serviceProvider.StartAdvertising(new GattServiceProviderAdvertisingParameters()
            {
                IsConnectable = true,
                IsDiscoverable = true
            });

            #endregion 

            Thread.Sleep(Timeout.Infinite);
        }

        /// <summary>
        /// 读取特性的事件处理程序。
        /// </summary>
        /// <param name="sender">GattLocalCharacteristic object</param>
        /// <param name="ReadRequestEventArgs"></param>
        private static void ReadCharacteristic_ReadRequested(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs)
        {
            GattReadRequest request = ReadRequestEventArgs.GetRequest();

            // Get Buffer with hour/minute/second
            //request.RespondWithValue(GetTimeBuffer());
        }

        /// <summary>
        /// 读/写特性的读事件处理程序。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ReadRequestEventArgs"></param>
        private static void _readWriteCharacteristic_ReadRequested(GattLocalCharacteristic sender, GattReadRequestedEventArgs ReadRequestEventArgs)
        {
            GattReadRequest request = ReadRequestEventArgs.GetRequest();

            DataWriter dw = new DataWriter();
            dw.WriteByte((Byte)_redValue);
            dw.WriteByte((Byte)_greenValue);
            dw.WriteByte((Byte)_blueValue);

            request.RespondWithValue(dw.DetachBuffer());

            Debug.WriteLine($"RGB read");
        }

        /// <summary>
        /// 读写特性的写处理程序。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="WriteRequestEventArgs"></param>
        private static void _readWriteCharacteristic_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs WriteRequestEventArgs)
        {
            GattWriteRequest request = WriteRequestEventArgs.GetRequest();
            var size = request.Value.Length;
            // 从缓冲区解包数据
            DataReader rdr = DataReader.FromBuffer(request.Value);
            var buffer = new byte[request.Value.Length];
            rdr.ReadBytes(buffer);

            // 如果Write需要响应,则响应
            if (request.Option == GattWriteOption.WriteWithResponse)
            {
                request.Respond();
            }

            // 定义设置密码格式 n:wifi名称;p:dd666666
            var value = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            SetWifi(value);
        }

        /// <summary>
        /// 设置Wifi持久化
        /// </summary>
        /// <param name="value"></param>
        public static void SetWifi(string value)
        {
            var wifiValue = value.Split(';');
            if (wifiValue.Length > 1)
            {
                // 如果不是wifi配置则跳过
                if (wifiValue[0].StartsWith("n:"))
                {
                    var name = wifiValue[0].Substring(2);
                    var password = wifiValue[1].Substring(2);
                    if (password.Length > 0)
                    {
                        ConfigHelper.SetWifi(value);

                        try
                        {
                            CancellationTokenSource cs = new(60000);
                            var success = WifiNetworkHelper.ConnectDhcp(name, password, requiresDateTime: true, token: cs.Token);

                            Debug.WriteLine("链接WIFI成功");
                        }
                        catch (Exception)
                        {
                            Debug.WriteLine("尝试链接WiFi失败");
                        }
                    }
                }


            }

        }


        public struct WifiModule
        {
            public string Name { get; set; }

            public string Password { get; set; }
        }
    }

    public class ConfigHelper
    {
        private const string WifiName = "I:\\Wifi.ini";

        public static void SetWifi(string value)
        {
            var buffer = Encoding.UTF8.GetBytes(value);
            var file = File.Exists(WifiName) ? new FileStream(WifiName, FileMode.Open, FileAccess.Write) : File.Create(WifiName);
            file.Write(buffer, 0, buffer.Length);
            file.Close();
        }

        public static WifiModule GetWifi()
        {
            if (File.Exists(WifiName))
            {
                var file = new FileStream(WifiName, FileMode.Open, FileAccess.Read);
                if (file.Length > 0)
                {

                    var bytes = new byte[file.Length];
                    file.Read(bytes, 0, bytes.Length);
                    file.Close();
                    var value = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                    var wifiValue = value.Split(';');
                    if (wifiValue.Length > 1)
                    {
                        var name = wifiValue[0].Substring(2);
                        var password = wifiValue[1].Substring(2);
                        return new WifiModule
                        {
                            Name = name,
                            Password = password,
                        };
                    }
                }
                file.Close();
            }

            return new WifiModule { Name = null, Password = null };
        }
    }
}

上面是所有的代码,下面将一步一步的讲解

当我们接收到信息的时候会触发_readWriteCharacteristic_WriteRequested的事件_readWriteCharacteristic_WriteRequested的代码如下,第一步先读取数据,然后接收读,在得到数据转换字符串,通过调用SetWifi方法去解析设置WIFI

            GattWriteRequest request = WriteRequestEventArgs.GetRequest();
            var size = request.Value.Length;
            // 从缓冲区解包数据
            DataReader rdr = DataReader.FromBuffer(request.Value);
            var buffer = new byte[request.Value.Length];
            rdr.ReadBytes(buffer);

            // 如果Write需要响应,则响应
            if (request.Option == GattWriteOption.WriteWithResponse)
            {
                request.Respond();
            }

            // 定义设置密码格式 n:wifi名称;p:dd666666
            var value = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            SetWifi(value);

SetWifi,这里是用于解析数据格式并且处理持久化和链接WIFI,wifi的格式也是规范好的n:wifi名称;p:WiFi密码,不使用json格式从而减少包的依赖。

        /// <summary>
        /// 设置Wifi持久化
        /// </summary>
        /// <param name="value"></param>
        public static void SetWifi(string value)
        {
            var wifiValue = value.Split(';');
            if (wifiValue.Length > 1)
            {
                // 如果不是wifi配置则跳过
                if (wifiValue[0].StartsWith("n:"))
                {
                    var name = wifiValue[0].Substring(2);
                    var password = wifiValue[1].Substring(2);
                    if (password.Length > 0)
                    {
                        ConfigHelper.SetWifi(value);

                        try
                        {
                            CancellationTokenSource cs = new(60000);
                            var success = WifiNetworkHelper.ConnectDhcp(name, password, requiresDateTime: true, token: cs.Token);

                            Debug.WriteLine("链接WIFI成功");
                        }
                        catch (Exception)
                        {
                            Debug.WriteLine("尝试链接WiFi失败");
                        }
                    }
                }


            }

        }

ConfigHelper则是操作文件将wifi的配置持久化,nanoframework的文件系统默认是I,文件路径则是I:\\Wifi.ini这样就可以将数据持久化了。

    public class ConfigHelper
    {
        private const string WifiName = "I:\\Wifi.ini";

        public static void SetWifi(string value)
        {
            var buffer = Encoding.UTF8.GetBytes(value);
            var file = File.Exists(WifiName) ? new FileStream(WifiName, FileMode.Open, FileAccess.Write) : File.Create(WifiName);
            file.Write(buffer, 0, buffer.Length);
            file.Close();
        }

        public static WifiModule GetWifi()
        {
            if (File.Exists(WifiName))
            {
                var file = new FileStream(WifiName, FileMode.Open, FileAccess.Read);
                if (file.Length > 0)
                {

                    var bytes = new byte[file.Length];
                    file.Read(bytes, 0, bytes.Length);
                    file.Close();
                    var value = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

                    var wifiValue = value.Split(';');
                    if (wifiValue.Length > 1)
                    {
                        var name = wifiValue[0].Substring(2);
                        var password = wifiValue[1].Substring(2);
                        return new WifiModule
                        {
                            Name = name,
                            Password = password,
                        };
                    }
                }
                file.Close();
            }

            return new WifiModule { Name = null, Password = null };
        }
    }

下面是程序运行的效果

效果

Nanoframework 操作单片机蓝牙配置WIFI的案例

Nanoframework 操作单片机蓝牙配置WIFI的案例

这样就可以动态配置WIFI了,也可以用蓝牙做设备的初始化。

介绍Nanoframework

.NET nanoFramework是一个免费且开源的平台,可以用于编写针对受限嵌入式设备的托管代码应用程序。它适用于多种类型的项目,包括物联网传感器、可穿戴设备、学术概念验证、机器人技术、爱好者/创客创作甚至复杂的工业设备。它通过为嵌入式开发人员提供桌面应用程序开发人员使用的现代技术和工具,使这些平台的开发更加简单、快速和成本更低。

开发人员可以利用强大且熟悉的Microsoft Visual Studio集成开发环境和他们对.NET C#的了解,快速编写代码,无需担心微控制器的底层硬件细节。桌面.NET开发人员将感到“如在家中”,并能够在嵌入式系统开发中运用他们的技能,扩大合格的嵌入式开发人员的队伍。

它包括了.NET通用语言运行时(CLR)的精简版本,并配备了.NET基类库的子集,以及包含在.NET IoT中的最常用API,允许从.NET IoT应用程序中重用代码、数以千计的代码示例和开源项目。使用Microsoft Visual Studio,开发人员可以直接在真实硬件上部署和调试代码。

.NET nanoFramework平台在.NET Micro Framework的基础上进行了扩展,并使用了其中的一些构建模块。许多原始组件被完全重写,其他组件得到改进,还有一些组件被简单地重用。进行了大量的代码清理和改进,使.NET nanoFramework适应未来发展!

技术交流

如果你也对Nanoframework感兴趣的话可以联系wx:wk28u9123456789并且备注Nanoframework就可以加入Nanoframework中文社区交流群,由于群人数过多不能使用二维码加入敬请谅解!

来自token的分享文章来源地址https://www.toymoban.com/news/detail-478359.html

到了这里,关于Nanoframework 操作单片机蓝牙配置WIFI的案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 蓝牙模块(HC-05)与手机连接,蓝牙与蓝牙互联,电脑通过蓝牙控制单片机

    HC-05蓝牙模块,USB TO TTL手机APP为SPP蓝牙串口 第一章:蓝牙模块配置 一:HC-05与USB TO TTL连接 EN:为使能引脚,一般不接 VCC:接USB TO TTL模块的5v脚(3.3v不亮) GND:接USB TO TTL模块的GND脚 TXD:接USB TO TTL模块的RXD脚 RXD:接USB TO TTL模块的TXD脚 STATE:状态引脚,一般不接 二:进入

    2024年02月12日
    浏览(46)
  • 51单片机蓝牙模块(HC05)运行原理

    在所有工作进行之前首先看一看自己的蓝牙模块是否是正常的,这一步很重要。一块正常的蓝牙模块是所有后续工作的基础! 首先把蓝牙模块链接到51单片机上 这时需要注意!!!我们需要将 蓝牙模块的RXD和单片机上的P30(RXD)引脚连接,将蓝牙模块的TXD和单片机上的P31(

    2023年04月08日
    浏览(51)
  • 0234-基于单片机的蓝牙温度调控电路设计

    1、采用51/52单片机作为主控; 2、采用18B20传感器检测温度; 3、采用1602显示温度、报警上下限; 4、通过蓝牙模块将温度数据发送至手机APP并显示; 5、当温度超过上限时,红灯亮,相应继电器吸合(可接散热风扇); 6、当温度低于下限时,绿灯亮,相应继电器吸合(可接加

    2024年02月20日
    浏览(31)
  • 0231-基于单片机的心率监测(蓝牙)电路设计

    1、采用51/52单片机(通用)作为主控芯片; 2、采用1602液晶显示:当前心率、报警上限、报警下限; 3、采用ST188红外对管检测心率,当单片机检测到大约第5次信号时,开始显示这5次信号算出的平均心率,当超过大约3秒没有检测到信号,清除心率; 4、当测试心率超出报警上下

    2024年02月19日
    浏览(31)
  • 基于51单片机的智能小车(循迹、避障、蓝牙控制)

    文章目录 前言 一、功能 二、主要模块 1.L298N模块 2.循迹模块 3.红外避障模块 4.超声波避障模块 5..蓝牙模块 代码 三、其余模块 四、总结   本项目可实现小车红外循迹,L298N电机驱动,红外避障,超声波避障,蓝牙控制等功能的切换。   红外循迹,L298N电机驱动,PWM电机调速

    2024年02月04日
    浏览(51)
  • 【Proteus仿真】【Arduino单片机】HC05蓝牙通信

    本项目使用Proteus8仿真Arduino单片机控制器,使用PCF8574、LCD1602液晶、HC05蓝牙传感器等。 主要功能: 系统运行后,LCD1602显示蓝牙接收数据。 B站演示视频:https://space.bilibili.com/444388619 视频地址:https://space.bilibili.com/444388619/video 专注于51单片机、STM32、国产32、DSP、Proteus、ardu

    2024年04月16日
    浏览(39)
  • 基于单片机的蓝牙音乐喷泉的设计与实现

     功能介绍 以51单片机作为主控系统; 通过HM-18蓝牙音频模块进行无线传输;  通过LM386功放模块对音频信号进行放大; 手机端可以直接控制音频播放,并且最远距离可达20米; 手机端可以进行任意音乐切换,播报、暂停; 通过PWM脉冲电路改变水泵水柱随着音乐强度变化而变

    2024年02月16日
    浏览(30)
  • 【单片机毕业设计】基于STM32单片机蓝牙app遥控语音控制老年轮椅车GSM位置定位报警系统--物联网 单片机 嵌入式

            这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉小洪学长自己做的项目系统达不到老师的要求。为了大家能够顺利以及最少的精力通过毕设,小洪学长分享优质毕业

    2024年01月22日
    浏览(82)
  • 【单片机毕设选题】单片机远程wifi红外无接触体温测量系统 - 物联网 stm32

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月20日
    浏览(42)
  • C51单片机利用HC-05蓝牙模块实现手机点灯

    蓝牙通信,实现手机端远程(15米)控制单片机,这听起来对于初学者的我来说,是那么不可思议,经过不断地实验,阅读其他大佬的文章,终于实现了。 在有基础的通信原理知识的前提下,知,HC-05蓝牙模块与51的通信其实很简单,就是蓝牙模块的RXD(接收端)接单片机的TXD(发送

    2024年02月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包