×

灵活的ESP8266和ESP32初始设备配置

消耗积分:2 | 格式:zip | 大小:0.00 MB | 2023-06-19

王飞云

分享资料个

描述

背景

当您将数百个设备部署为 IoT 项目的一部分时,问题是如何将它们接入客户的网络并为设备提供最新的特定固件。

问题是您不知道设备将在何时何地首次启动。

设备不知道 WiFi 参数,其固件可能已过时。

这就是ColdBoot提供帮助的地方。

所有信息都可以在:https ://github.com/arkhipenko/EspColdBoot

什么是冷启动?

ColdBoot 是 ESP8266 或 ESP32 微控制器的预编译固件,能够快速收集:

  • WiFi参数(SSID和密码)
  • 最新配置文件的 URL
  • OTA更新服务器的URL

通过简单的网络表单从最终用户那里获得。

ColdBoot 的主要目标是尽可能快速轻松地访问 Wifi 并为特定设备提供最新固件。

ColdBoot 通过连接到 USB 或串行端口的终端窗口提供逐步说明(115200 bps 设置)

如何使用:

选项 1:将预编译的二进制文件直接上传到芯片

选项 2:编译并上传提供的草图。

可选:编辑data/config.json文件并使用上传工具上传到 SPIFFS

工艺流程

第 1 步:从 SPIFFS 中读取配置

ColdBoot 尝试从设备的 SPIFFS 文件系统中读取配置文件。

配置文件应命名为“ config.json ”,并应位于根文件夹中。

配置文件是一个简单的 JSON 数组,可以定义以下参数:

  • “标题” - 用于收集用户参数的 Web 表单的标题
  • "SSID" - WiFi 网络 SSID
  • “密码” - WiFi密码
  • “Config” - 如果参数来自网络,则配置文件的 URL
  • “OTA” - OTA 固件配置 HTTP 服务器的 URL
  • “fields” - 要在网络表单上显示的字段数

可以定义所有字段或字段的子集。后续流程可能会受到此文件的影响。

一个示例用例:

配置文件提供 Web 表单的标题、最新配置的 URL,并将 Web 表单字段的数量限制为 2(SSID 和密码)

{
  "Title"    : "My Amazing IoT device",
  "Config"   : "http://ota.home.lan/esp/config/",
  "fields"   : "2"
}

注意:要使用 SPIFFS 配置功能 - 根据需要编辑提供的data/config.json文件,并使用 Arduino IDE 中的 ESP8266 SPIFFS 上传工具将 SPIFFS 图像上传到设备。

第 2 步:根据 SPIFFS 配置连接到 WIFI

如果从 SPIFFS 读取配置成功,则可能会在此处提供 SSID 和密码,因此 ColdBoot 会尝试连接到 WiFi。

如果 SPIFFS 不可用config.json文件不可用,则跳过第 2 步。

第 3 步:用户提供配置

如果设备在步骤 2 中能够连接到 WiFi 网络,则跳过此步骤。

此时,设备会创建一个 WiFi AP 点并创建一个简单的 Web 表单,以便从用户那里收集配置参数。AP SSID 为ESP8266-ESP32-(例如:ESP8266-dac26e)

最终用户需要连接到 AP 并导航到http://10.1.1.1

 

poYBAGOYAQaAB8VSAABSOF9y4ds735.png
 

完整的网络表单如下所示:

 

pYYBAGOYAQmAIncRAABDqbRGJ8o930.png
 

基于步骤 1 示例config.json文件的简化 Web 表单如下所示:

poYBAGOYAQyAK0KVAAA2X63sWRs011.png
 

 

一旦用户点击提交按钮,设备就会一次又一次地尝试连接到 WiFi,直到成功。

设备将在 10 分钟不活动后重新启动。

第 4 步:从 HTTP 服务器读取配置

如果提供了配置 URL,设备将尝试从 HTTP 服务器读取和解析配置参数。

这里有两个选择:

  • 您可以提供到服务器的路径,其中每个设备都存储了特定的配置文件,或者
  • 您可以直接提供配置文件的路径(在这种情况下,多个设备可以读取同一个文件)

如果仅提供文件夹路径,ColdBoot将添加设备 ID 和版本,因此假定请求的配置是唯一的。例如,对于设备 ID ESP8266-dac26e,URL 将如下所示:

​http ://ota.home.lan/esp/config/coldboot-dac26e-1.0.0.json

(前提是http://ota.home.lan/esp/config/是你的配置服务器)

或者,您可以指定直接文件 URL,例如:

​http ://ota.home.lan/esp/config/iotdevice.json

如果ColdBoot确定未提供有效的 URL,则此步骤作为可选跳过

第 5 步:从 OTA 服务器更新固件

此时,ColdBoot 假定存在一个指向可用的 OTA 更新服务器的有效 URL。

设备将尝试根据提供的 URL 执行 OTA 固件更新。

这里有两个选择:

  • 您可以为每个设备提供存储特定二进制文件的服务器的路径,或者
  • 您可以直接提供二进制文件的路径(在这种情况下,多个设备可以基于同一个文件进行更新)

如果仅提供文件夹路径,ColdBoot将添加设备 ID 和版本,因此假定 OTA 请求是唯一的。例如,对于设备 ID ESP8266-dac26e,URL 将如下所示:

​http ://ota.home.lan/esp/bin/coldboot-dac26e-1.0.0.bin

(前提是http://ota.home.lan/esp/bin/是您的 OTA 服务器 URL)

或者,您可以指定直接文件 URL,例如:

​http ://ota.home.lan/esp/bin/iotdevice.bin

第 6 步:重新启动

如果一切顺利,则不应执行第 6 步,因为设备将在第 5 步成功 OTA 更新结束时重新启动。

但是,如果 OTA 更新失败,设备将等待 10 秒并重新启动。

文件夹:

数据- 如果需要通过 SPIFFS 进行配置,则将 SPIFFS 图像上传到设备。必须在根文件夹中包含一个名为config.json的 JSON 文件。

二进制- 预编译的 esp8266 二进制(假设 4Mb 闪存大小、2Mb SPIFFS 大小、1Mb OTA 大小),可以作为制造过程的一部分直接闪存到芯片中

例子:

下面是通过 ColdBoot 配置的真实设备的终端输出。

请注意,在 OTA 完成后,应用程序 ID 会更改为success-...。

ESP8266 ColdBoot v1.0.0

ESP8266 ID: ESP8266-dac26e

Full Application Version: coldboot-dac26e-1.0.0
---------------------------------------------

STEP 1:

 > Reading configuration file from SPIFFS if present
 > SUCCESS.

STEP 2:

 > Configuration read from SPIFFS:
 > Title	:	ColdBoot Initial Config
 > SSID	:	
 > Password	:	
 > Config	:	http://ota.home.lan/esp/config/
 > OTA	:	
 > fields	:	2
 > Current count = 6
 > Current size  = 157

 > Attempting WiFi connection ............................................................ WiFi connection timeout
 > WiFi connection unsuccessful.


STEP 3:

 > Provisioning configuration from the user

	Navigate to  http://10.1.1.1  and fill out the form
	Provide WiFi SSID and password
	as well as URLs for Configuration and/or OTA

 > Bootstrapping SUCCESS.
 > Configuration after Bootstrap:
 > Title	:	ColdBoot Initial Config
 > SSID	:	devices
 > Password	:	********
 > Config	:	http://ota.home.lan/esp/config/
 > OTA	:	
 > fields	:	2
 > Current count = 6
 > Current size  = 142

 > Attempting WiFi connection .............	WiFi connected
 > IP address: 192.168.122.65
 > SSID: devices
 > mac: 98:F4:AB:DA:C2:6E

STEP 4:

 > Checking if configuration should be read from an HTTP server
 > Attempting to read config from this URL:
   http://ota.home.lan/esp/config/coldboot-dac26e-1.0.0.json
 > SUCCESS.
 > Dictionary after HTTP config:
 > Title	:	ColdBoot Initial Config
 > SSID	:	devices
 > Password	:	********
 > Config	:	http://ota.home.lan/esp/config/
 > OTA	:	http://ota.home.lan/esp/bin/
 > fields	:	2
 > Current count = 6
 > Current size  = 148


STEP 5:

 > Checking for the OTA provisioning URL
 > Attempting OTA Update from this URL:
   http://ota.home.lan/esp/bin/coldboot-dac26e-1.0.0.bin

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 3456, room 16 
tail 0
chksum 0x84
csum 0x84
va5432625
@cp:0
ld
ColdBoot v1.0.0

ESP8266 ID: ESP8266-dac26e
AppVersion: success-dac26e-1.0.0

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'灵活的ESP8266和ESP32初始设备配置',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);