From 7255411b07cca0e5945156141b680ad07f46bc85 Mon Sep 17 00:00:00 2001 From: Grey Date: Mon, 27 Feb 2023 10:36:10 +0800 Subject: [PATCH] =?UTF-8?q?feat=20(FOTA):=20=E6=96=B0=E5=A2=9EOTA=E5=8F=8A?= =?UTF-8?q?APP=5FFOTA=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改点记录: 1. 新增OTA的README.py文档, 介绍OTA基础功能. 2. 新增OTA升级-文件.py文档, 介绍客户文件升级. 固件版本: N/A 是否需要文案翻译: 否 --- ...7\347\272\247-\346\226\207\344\273\266.md" | 64 ++++++++++++++++++ .../zh/OTA\345\215\207\347\272\247/README.md" | 8 +++ .../media/APP_FOTA_1.jpg" | Bin 0 -> 5486 bytes .../media/APP_FOTA_2.jpg" | Bin 0 -> 7369 bytes .../media/APP_FOTA_DEMO.py" | 22 ++++++ 5 files changed, 94 insertions(+) create mode 100644 "docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_1.jpg" create mode 100644 "docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_2.jpg" create mode 100644 "docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_DEMO.py" diff --git "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/OTA\345\215\207\347\272\247-\346\226\207\344\273\266.md" "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/OTA\345\215\207\347\272\247-\346\226\207\344\273\266.md" index e69de29b..bbd24906 100644 --- "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/OTA\345\215\207\347\272\247-\346\226\207\344\273\266.md" +++ "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/OTA\345\215\207\347\272\247-\346\226\207\344\273\266.md" @@ -0,0 +1,64 @@ +# OTA升级-文件 + +## 什么是OTA升级-文件 + +OTA:Over-the-Air Technology空中下载技术,是通过移动通信的空中接口实现对移动终端设备进行远程管理的技术。 + +OTA升级-文件就是利用这项技术对模块进行文件升级。在QuecPython中该功能接口为[APP_FOTA](../../API_reference/zh/QuecPython类库/app_fota.html)。为阅读体验以下均命名为APP_FOTA。 + +## 怎么使用APP_FOTA + +### 升级准备 + +在之前的引言中已经说到OTA升级需要使用到HTTP服务器作为升级内容的存放点。对于APP_FOTA而言,服务器需要存储客户需要升级文件内容。此部分工作由客户自主完成。目的就是得到一个可以访问下载到该文件的URL地址即可。 + +### 硬件设计 + +APP_FOTA升级主要为网络侧与模块内部交互,除前提条件模块需要组网成功外无需其他外围硬件支持。 + +### 软件应用 + +QuecPython中APP_FOTA功能支持单文件下载与批量文件下载。API接口分别为:**fota.download(url, file_name)**与**fota.bulk_download(info=[])**,有关API的详细介绍请参考[APP_FOTA](../../API_reference/zh/QuecPython类库/app_fota.html)。 + +需要注意是:调用APP_FOTA接口后文件不是直接下载到**usr**分区(模块存放用户文件的分区),而是下载到一个临时的**.updater**文件夹中。该文件夹可能存在与**usr.updater**文件夹下,也可能存在于**./fota/usr/.updater**。但对于实际使用不需要关注这些。只需了解APP_FOTA后文件并非直接存在**usr**目录,需要**fota.set_update_flag()**设置升级标志位后重启模组才会自动将对应文件搬运至**usr**目录。 + +示例代码如下: + +```python +import app_fota +from misc import Power +import utime as time + + +files = ["000_Grey_Test.py"] +download_list = [] +url = r'%s' % "http://112.31.84.164:8300/upload/Grey/" + +for file in files: + download_list.append({'url': (url + file), 'file_name': '/usr/%s' % file}) + +if download_list: + print("downlist: %d\r\n" % len(download_list), download_list) + fota = app_fota.new() + result = fota.bulk_download(download_list) + fota.set_update_flag() + + print("update ....", result) + time.sleep(1) + Power.powerRestart() # 重启模块 +``` + +## APP_FOTA文件下载测试 + +使用QPYcom工具和模组进行交互,下载示例代码至模组进行运行。 + +下载DEMO代码 + +APP_FOTA_DEMO运行前: + +![APP_FOTA_1](media/APP_FOTA_1.jpg) + +APP_FOTA_DEMO运行后: + +![APP_FOTA_2](media/APP_FOTA_2.jpg) + diff --git "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/README.md" "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/README.md" index e69de29b..3eb80003 100644 --- "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/README.md" +++ "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/README.md" @@ -0,0 +1,8 @@ +# OTA升级 + +OTA:Over-the-Air Technology空中下载技术,是通过移动通信的空中接口实现对移动终端设备进行远程管理的技术。QuecPython的OTA升级包含两部分:[OTA升级-固件](OTA升级-固件.md)及[OTA升级-文件](OTA升级-文件.md)。由于此部分功能测试需用到HTTP服务器作为升级内容的存放点,该部分内容先介绍基本概念和理论,实际操作以操作演示为主进行讲解。 + +# OTA升级文档目录 + +- [OTA升级-固件](OTA升级-固件.md) +- [OTA升级-文件](OTA升级-文件.md) \ No newline at end of file diff --git "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_1.jpg" "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_1.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..067326f9d71975013cd7ccf17d392ad384ce459a GIT binary patch literal 5486 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 aA{cVGMCzNIhrriJ3DlIeL5Me&VgCb6nwVJt literal 0 HcmV?d00001 diff --git "a/docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_2.jpg" "b/docs/development_guide/zh/OTA\345\215\207\347\272\247/media/APP_FOTA_2.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..ce6d54bf961a433073ff7748e657323ec476b0ec GIT binary patch literal 7369 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 b`cJ-Zxw