使用.Net nanoFramework为ESP32进行蓝牙配网

news2024/12/27 15:02:50

通过前面的介绍,我们已经学会了如何使用 .NET nanoFramework 为 ESP32 设备连接 Wi-Fi 网络。然而,在实际的物联网环境中,我们往往需要使用更便捷的式来满足配网需求。这篇文章将带你了解一些常见的配网方案,并以 ESP32 为例,介绍如何使用 .NET nanoFramework 实现为 ESP32 蓝牙配网。

1. 引言

经过前面的介绍,我们已经学会了如何 为 ESP32 设备连接 Wi-Fi 网络,然后这种代码中硬编码的方式,虽然简单,但在实际的物联网环境中,我们往往需要使用更便捷的方式来满足配网需求。而且,也不适合于产品化的物联网设备。今天,我们就来看看如何使用 .NET nanoFramework 实现为 ESP32 蓝牙配网。

2. 常见配网方案

为了能让我们的物联网设备连接到网络,配网的方式也有很多种,每种方式都有其特定的应用场景和优缺点。在这里我们不再详细的描述其原理,只是带大家做一个简单的了解,如果你感兴趣,可以自行搜索。下面是一些常见的配网方式的总结:

  1. softAP:在这种模式下,待配网设备会创建一个热点,用户可以通过手机或其他设备连接到这个热点,然后通过特定的接口设置网络信息。这种方式的优点是兼容性较好,不需要额外的硬件支持,但缺点是但手机端需要做两次 Wi-Fi 连接设置的切换,步骤较复杂,用户体验较差。

  2. Sniffer模式:Sniffer模式也被称为混杂模式,待配网设备在这种模式下可以接收所有的数据包,不进行过滤。例如,SmartConfig、AirKiss、simpleConfig 等这些协议就是使用这种方式,通过监听特定的数据包来获取网络信息。这种方式的优点是不需要用户进行复杂的操作,但一般为各厂商采用私有协议,兼容性和互操作性较差。

  3. 蓝牙配网:待配网设备在这种模式下会开启蓝牙接口,用户可以通过手机或其他设备的蓝牙连接到待配网设备,然后通过蓝牙传输网络信息。这种方式的优点是操作简单,用户体验好,但缺点是需要蓝牙硬件支持。

  4. 二维码配网:如果待配网设备有摄像头,可以通过扫描二维码来获取网络信息。这种方式的优点是操作简单,用户体验好,但缺点也是非常明显,需要摄像头硬件支持,而且摄像头聚焦,用户二维码放置的远近都需要提示好用户,影响用户体验。

  5. 声波配网:如果待配网设备有麦克风,可以通过声音编码来获取网络信息。这种方式的优点是不需要额外的硬件支持,但缺点是可能会受到环境噪音的干扰,影响配网的成功率。

3. 蓝牙配网的实现

虽然方案有很多,但是针对这一款 ESP32-S3-Zero 开发板,其拥有蓝牙模块,刷写 ESP32_S3_BLE 固件后,我们可以使用蓝牙配网的方式来为其配网。

3.1. 蓝牙配网协议 Improv

使用蓝牙配网我们处理可以自己定义进行私有的实现外,也可以使用开源的协议快速完成开发。除了不用自己造轮子外,配网的工具也不需要自己设计了。Improv 是一个免费且开放的标准,它允许设备通过蓝牙进行安全的 Wi-Fi 配网,这个过程可以通过以下步骤完成:

  1. 打开设备
  2. 客户端使用Improv协议将Wi-Fi凭据发送到待配网设备
  3. 设备连接到Wi-Fi网络并返回一个URL。
  4. 客户端使用该URL连接到设备并继续设置设备。

Improv协议可以通过蓝牙低功耗(Bluetooth Low Energy)或通过串行端口使用。这两种协议都可以从浏览器中使用。不过,串口就需要连线了,我们这里使用的是蓝牙低功耗的方式。

关于 Improv 协议的详细信息,可以参考其官方文档。

3.2 依赖准备

首先我们需要安装以下三个包:

  • nanoFramework.System.Device.Wifi:用于连接 Wi-Fi 网络
  • nanoFramework.Device.Bluetooth:用于实现蓝牙配网
  • nanoFramework.System.Net.Http:用于演示联网后的网络服务

对于 Improv 协议的实现,没有依赖包,但是在官方的 Samples 仓库中有一个ImprovWifi示例,我们可以参考其实现,直接使用其 Improv.cs,然后 using ImprovWifi; 即可。

3.3 编码实现

ImprovWifi 已经实现了 Improv 协议,我们只需要在 Program.cs 中实现一些简单的代码。

这里我们在完成配网后,启动一个简易的网络服务,用于演示配网成功后的网络服务。这里我们使用 HttpListener 来实现一个简易的网络服务,当然你也可以使用其他的方式,比如 WebServer 等等。

static Improv _imp;

public static void Main()
{
    Console.WriteLine("蓝牙配网 Improv 协议示例");

    _imp = new Improv();
    // 配网完成后的回调
    _imp.OnProvisioningComplete += Imp_OnProvisioningComplete;
    // 开始配网服务,设备名称这里可以自定义,中文也是支持的,在搜索设备时会显示该名称
    _imp.Start("ESP32 桑榆肖物");
    // 纯演示,这里直接授权
    _imp.Authorise(true);
 
    Console.WriteLine("等待设备配网...");

    while (_imp.CurrentState != Improv.ImprovState.provisioned)
    {
        Thread.Sleep(500);
    }

    Console.WriteLine("设备配网完成,IP地址:" + _imp.GetCurrentIPAddress());
    // 停止配网服务
    _imp.Stop();
    _imp = null;

    Console.WriteLine("启动一个简易的网络服务,用于演示配网成功后的网络服务");
    SimpleWebListener();

    Thread.Sleep(Timeout.Infinite);
}

private static void Imp_OnProvisioningComplete(object sender, EventArgs e)
{
    SetProvisioningURL();
}

private static void SetProvisioningURL()
{
    _imp.RedirectUrl = "http://" + _imp.GetCurrentIPAddress() + "/start.htm";
}

private static void SimpleWebListener()
{
    string responseString =
        "<html><head><meta charset='utf-8'>" +
        "<title>Hello from ESP32</title></head>" +
        "<body><h2>Hello from ESP32</h2>" +
        "<p>It works!</p>" +
        "<p>这里可以根据需求继续进行更多的设备配置信息</p>" +
        "</body></html>";
    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
    HttpListener listener = new("http", 80);
    listener.Start();

    while (true)
    {
        try
        {
            HttpListenerContext context = listener.GetContext();
            Console.WriteLine("Request received");
            HttpListenerResponse response = context.Response;
            response.ContentLength64 = buffer.Length;
            response.OutputStream.Write(buffer, 0, buffer.Length);
            context.Response.Close();
            Console.WriteLine("Response sent");
            context.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message + "\nSack = " + ex.StackTrace);
        }
    }
}

注意:以上代码只是功能的演示,在实际项目中,需要根据自己的需求进行修改,比如我们需要在验证连接后下次也自动完成连接,再者为了安全性,我们还需要进行验证等等。后面我会有一个实际的开源项目演示,介绍如何使用近期介绍的相关功能,敬请关注。

4. 配网测试

编译并刷写完成后,通过调试的数据输出,我们可以看设备成功进入等待配网状态。这时我们通过网页打开 Improv 的 web 配网客户端,也就是之前的 Improv 官方介绍站点。当然,站点和协议都是开源的,你可以自己搭建一个。

这里我们直接使用官方的进行测试使用即可,不过,需要注意的是,因为使用了蓝牙配网,所以这里需要你的电脑也支持蓝牙,否则无法搜索到设备。如果你的电脑没有蓝牙,也可以使用手机的 Chrome 或 Egde 浏览器打开该网页进行配网。

请添加图片描述

这里可以看到,设备列表中已经搜索到了我们的设备,点击配对即可。配对成功后,我们可以会弹出下面的对话框,这里我们可以设置 Wi-Fi 的 SSID 和密码,然后点击 Connect 按钮即可。

请添加图片描述

连接成功后,我们可以看到设备的状态已经变成了 Provisioned,这时我们就可以访问到设备启动的网络服务了。

请添加图片描述

5. 总结

通过这篇文章,我们学习了如何使用 .NET nanoFramework 为 ESP32 设备进行蓝牙配网。虽然这里我们使用的是 Improv 协议,但是其实现原理都是类似的,只是协议不同而已。在实际的项目中,我们可以根据自己的需求,选择合适的配网方式,或者自己实现一个配网协议,这里就不再赘述了。

对于 Improv 协议的配网客户端,我们也可以通过微信小程序来实现,或者通过集成SDK到自己的应用中方便的实现配网,有兴趣的同学可以自行了解实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1364290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构入门到入土——链表(2)

目录 一&#xff0c;与链表相关的题目&#xff08;2&#xff09; 1.输入两个链表&#xff0c;找出它们的第一个公共节点 2.给定一个链表&#xff0c;判断链表中是否有环 3.给定一个链表&#xff0c;返回链表开始入环的第一个节点&#xff0c;若无则返回null 一&#xff0c;…

【好书推荐】ReactJS实践入门

作者简介 Chris Minnick是一位多产的作家、博主、培训师、演说家和Web工程师。他创立的WatzThis&#xff1f;公司&#xff0c;一直致力于寻找更好的方法向初学者教授计算机和编程技能。 Chris拥有超过25年的全栈开发经验&#xff0c;他也是一名教龄超过10年的培训师&#xff0c…

科学的摇篮 - 贝尔实验室

AT&T贝尔实验室&#xff08;AT&T Bell Laboratories&#xff09;是美国电信公司AT&T的研究与开发部门&#xff0c;成立于1925年。它在20世纪的许多年里一直是科学与技术创新的重要中心&#xff0c;做出了众多重大贡献&#xff0c;并为多项科技成就奠定了基础。以下…

Java Swing手搓坦克大战遇到的问题和思考

1.游戏中的坐标系颇为复杂 像素坐标系还有行列坐标&#xff0c;都要使用&#xff0c;这之间的互相转化使用也要注意 2.游戏中坦克拐弯的处理&#xff0c;非常重要 由于坦克中心点是要严格对齐到一条网格线&#xff0c;并沿着这条线前进的&#xff0c;如果拐弯不做处理&#…

动态卡尺胶路检测

动态卡尺胶路检测 1. 示例效果2. 代码 1. 示例效果 使用了三个卡尺工具、一个线段工具。这种方法可以检测胶路最常见的缺陷&#xff1a;断胶和胶宽等 2. 代码 #region namespace imports using System; using System.Collections; using System.Drawing; using System.IO; …

【开发日记】IDEA“找不到或无法加载主类”问题

记录一个研究了两个小时的“玄学”问题找不到或无法加载主类。 ​1、问题 使用IDEA启动SpringBoot项目显示找不到或无法加载主类。 2、解决经历 尝试了很多种解决方法都没有解决&#xff0c;下面是我网上查询后尝试的一些方法。这些方法我都没有解决问题&#xff0c;是因为…

双十一的祈祷【算法赛】

问题描述 双十一&#xff0c;不仅是购物狂欢节&#xff0c;更有 "光棍节" 之称。这源于 11:1111:11 由四个 11 构成&#xff0c;象征着单身。 作为大学生的小蓝也想经历甜甜的校园恋爱&#xff0c;于是他找到了爱神丘比特&#xff0c;向他祈祷能为自己带来一段邂逅…

微软开源时空预测Fost的使用和解读

一、引言 时空预测是指对未知系统状态在时间和空间上的预测&#xff0c;它是地球系统科学、交通运输、智慧城市等领域的重要技术和工具。时空预测的目的是利用历史数据和当前信息&#xff0c;通过建立时空依赖关系&#xff0c;来推断未来的变化趋势和可能的情景。时空预测的应…

《PySpark大数据分析实战》-24.数据可视化图表介绍

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

强化学习4——动态规划初探

动态规划具体指的是在某些复杂问题中&#xff0c;将问题转化为若干个子问题&#xff0c;并在求解每个子问题的过程中保存已经求解的结果&#xff0c;以便后续使用。实际上动态规划更像是一种通用的思路&#xff0c;而不是具体某个算法。 在强化学习中&#xff0c;被用于求解值函…

CAN总线基础详解以及stm32的CAN控制器

目录 CAN简介 CAN总线拓扑图 CAN总线特定 CAN应用场景 CAN的物理层 CAN的协议层 CAN数据帧介绍 CAN位时序介绍 数据同步过程 硬件同步 再同步 CAN总线仲裁 stm32的CAN控制器 CAN控制器介绍 CAN控制器模式 CAN控制器框图 接收过滤器 CAN控制器波特率计算 CAN相…

基于SSM的图书商城(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的图书商城&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMv…

libexif库介绍

libexif是一个用于解析、编辑和保存EXIF数据的库。它支持EXIF 2.1标准(以及2.2中的大多数)中描述的所有EXIF标签。它是用纯C语言编写的&#xff0c;不需要任何额外的库。源码地址&#xff1a;https://github.com/libexif/libexif &#xff0c;最新发布版本为0.6.24&#xff0c;…

topsis算法

TOPSIS &#xff08;Technique for Order Preference by Similarity to an Ideal Solution &#xff09;模型中文叫做“逼近理想解排序方法”&#xff0c;是根据评价对象与理想化目标的接近程度进行排序的方法&#xff0c;是一种距离综合评价方法。基本思路是通过假定正、负理想…

C#,数值计算,基础函数——任意位数π的数值算法源程序与数据可视化

对于数学常数 PI 后面位数的计算与追求&#xff0c;是数学家与计算机科学家们乐此不疲的游戏。 一、圆周率PI简史 圆周率&#xff08;Pi&#xff09;是圆的周长与直径的比值&#xff0c;一般用希腊字母π表示&#xff0c;是一个在数学及物理学中普遍存在的数学常数。π也等于圆…

关于图像分割任务中按照比例将数据集随机划分成训练集和测试集

1. 前言 之前写了分类和检测任务划分数据集的脚本&#xff0c;三大任务实现了俩&#xff0c;基于强迫症&#xff0c;也实现一下图像分割的划分脚本 分类划分数据&#xff1a;关于图像分类任务中划分数据集&#xff0c;并且生成分类类别的josn字典文件 检测划分数据&#xff…

如何计算ThreadLocal对象的hash值?【ThreadLocal技术】(含AtomicInteger的介绍)

如何计算ThreadLocal对象的hash值&#xff1f; 一、前置知识二、问题三、剖析源码&#xff1a;如何计算ThreadLocal对象的hash值&#xff1f;1、源码1.1 咱先得知道nextHashCode的起始值1.1.1 那就要先了解AtomicInteger创建AtomicInteger原子的增减操作原子的加法操作原子的获…

对Tor的去匿名化攻击的调查

文章信息 论文题目&#xff1a;De-Anonymisation Attacks on Tor: A Survey 期刊&#xff08;会议&#xff09;&#xff1a; IEEE Communications Surveys & Tutorials 时间&#xff1a;2021 级别&#xff1a;中科院1区&#xff08;IF&#xff1a;35.6&#xff09; 文章链…

Python 面向对象之反射

Python 面向对象之反射 【一】概念 反射是指通过对象的属性名或者方法名来获取对象的属性或调用方法的能力反射还指的是在程序额运行过程中可以动态获取对象的信息(属性和方法) 【二】四个内置函数 又叫做反射函数 万物皆对象&#xff08;整数、字符串、函数、模块、类等等…

黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目——第三部分

黑马程序员Java项目实战《瑞吉外卖》&#xff0c;轻松掌握springboot mybatis plus开发核心技术的真java实战项目——第三部分 1. 菜品管理的业务功能1.1 文件的上传和下载&#x1f647;‍♂️1.2 新增菜品1.3 接收页面提交的数据&#x1f647;‍♂️&#xff08;涉及两张表&a…