概述
QuecPython具备文件备份还原功能,当用户的代码误删除或意外被修改,可以从备份区还原丢失或错误的文件。
QuecPython数据安全区功能,为用户提供一块专门用于重要信息的区域。
先了解QuecPython的文件系统组成
为了保障产品在市场上稳定运作,我们推出双文件系统备份机制,分别称为“用户文件系统”和“备份文件系统”。
备份还原功能指的是“用户文件系统分区”需要备份的文件(包括脚本文件及其它任何格式的文件),在开机阶段检测到被损坏时,从“备份文件系统分区”将出厂烧录的文件还原至“用户文件系统分区"的功能。
“用户文件系统分区”的文件是可以被正常读写操作的,
“备份文件系统分区”的文件是只读的以确保该分区文件的安全性
为何需要备份还原功能
当应用或系统的关键参数或脚本不允许丢失或出现异常时,往往需要备份和还原功能。
哪些文件需要备份还原
用户可能需要备份还原的文件依据应用场景而定。
例如:要备份音量值、原始密码、服务器IP地址、阿里云、腾讯云产品及设备信息等。
备份还原实现机制
开始之前,先了解下备份还原功能的基本原理,以帮助理解下文。
- 用户通过使用QPYcom工具合并生产固件时,勾选【备份】,文件将自动导入“备份文件系统分区”,会在“备份文件系统分区”生成两个名称分别为checksum.json和backup_restore.json的文件。checksum.json记录了备份区文件的hash表。backup_restore.json表明是否开启备份还原功能。
- checksum.json:开机过程检测到开启了备份还原功能,系统会检测“用户文件系统分区”是否存在checksum.json。若不存在,则将”备份文件系统分区“的checksum.json拷贝到“用户文件系统分区”。
- 开机检测"用户文件系统分区"的checksum.json中的hash值,校验“用户文件系统分区”的用户文件。如果文件不存在或者校验不通过,则将“备份文件系统分区”对应的文件拷贝到“用户文件系统分区”相应的位置,并重新计算hash值,更新在“用户文件系统分区”的checksum.json中。
- 当参与备份还原的用户文件需要FOTA升级时,在升级过程的最后一步,会将更新后的用户文件的hash值写入“用户文件系统分区”的checksum.json。
注意:
- 本文所指的备份功能,是备份出厂烧录的文件;同样,还原也是出厂烧录的文件。
- 备份文件系统分区为只读属性,用户不可配置其读写属性。
触发条件
了解到QuecPython的备份还原的原理以后,可以知道,触发备份还原功能有以下几种可能:
- 用户文件系统分区的checksum.json文件被用户意外删除。
- 当设备短路断电等导致文件系统发生意外错误,致使被标记为备份的用户文件系统分区中文件的数据发生变化,或者文件丢失。
- 用户在应用过程中,手动改写了标记为备份的用户文件系统分区的文件数据,却没有更新checksum.json。
防止误触发
为了稳定运行,我们可以有针对性的防止备份还原的误触发:
用户应用程序上做好把关,避免误删除用户文件系统分区的checksum.json文件。
在访问文件系统时尽量避免暴力开关机,或者必要时,在硬件设计上增加掉电检测和后备电源功能,给文件系统足够的时间更新物理数据。
手动改写了标记为备份的用户文件系统分区的文件数据后,通过以下代码段来更新用户文件系统分区的checksum.sjon文件。更新成功后,会返回当前文件的hash值。
import file_crc32
file_crc32.calc('/usr/1.txt')
执行输出结果如图1所示:
更新到参与备份文件的hash值。
开启备份还原功能
开启QuecPython的备份还原功能,在QPYcom工具上操作即可。
- 登录官方网站“资源下载”,在一级分类“资源”,二级分类“工具”栏中找到【QPYcom 图形化工具】,具体位置如下图:
- 打开QPYcom工具后,在“下载”选项卡勾选【备份】,合并即可生成带备份的生产固件。
数据安全区的使用
数据安全区的功能用于给用户提供一块可存储重要信息的空间,模组提供一块裸flash区域及专门的读写接口供客户存贮重要信息,且信息在烧录固件后不丢失
- 烧录不包含此功能的固件无法保证不丢失
- 提供一个存储和读取接口,不提供删除接口
import SecureData
# 即将存储的数据buf
databuf = '\x31\x32\x33\x34\x35\x36\x37\x38'
# 在index为1的存储区域中存储长度为8的数据databuf
SecureData.Store(1, databuf, 8)
# 定义一个长度为20的数组用于读取存储的数据
buf = bytearray(20)
# 读取index为1的存储区域中的数据至buf中,将读取到数据的长度存储在变量length中
length = SecureData.Read(1, buf, 20)
# 输出读到的数据
print(buf[:length])
具体使用API参考 securedata - 安全数据区相关功能