commit 0ded0150a4d9cec14b52f642344bcaaa4785ca71 Author: murmur Date: Sun Sep 7 11:10:19 2025 +0800 初始版本 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d78140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +win.app/.build/ +win.app/.update-files/ +win.app/dist/ +uploaded_firmware/ diff --git a/firmware_upgrade.html b/firmware_upgrade.html new file mode 100644 index 0000000..388f70f --- /dev/null +++ b/firmware_upgrade.html @@ -0,0 +1,203 @@ + + + + + 设备固件更新 + + + + +
+

设备固件更新

+
+ + +
+
+ + +
+ +
+
+
+
+
+ + + diff --git a/firmware_upload_server.py b/firmware_upload_server.py new file mode 100644 index 0000000..ec58ad3 --- /dev/null +++ b/firmware_upload_server.py @@ -0,0 +1,55 @@ + +from flask import Flask, request, jsonify +import os +from flask import send_from_directory + +app = Flask(__name__) +UPLOAD_FOLDER = 'uploaded_firmware' +os.makedirs(UPLOAD_FOLDER, exist_ok=True) + +# 临时保存每个上传会话的分包 +chunk_cache = {} + +@app.route('/api/upload_firmware', methods=['POST']) +def upload_firmware(): + chunk = request.files.get('chunk') + index = int(request.form.get('index', -1)) + total = int(request.form.get('total', -1)) + session_id = request.remote_addr # 简单用IP区分会话,实际可用token等 + if chunk is None or index < 0 or total < 1: + return '参数错误', 400 + + # 缓存分包 + if session_id not in chunk_cache: + chunk_cache[session_id] = [None] * total + chunk_cache[session_id][index] = chunk.read() + + # 如果全部收到,合并保存 + if all(part is not None for part in chunk_cache[session_id]): + firmware_data = b''.join(chunk_cache[session_id]) + save_path = os.path.join(UPLOAD_FOLDER, f'firmware_{session_id}.bin') + with open(save_path, 'wb') as f: + f.write(firmware_data) + del chunk_cache[session_id] + return jsonify({'status': 'ok', 'msg': '全部分包已接收并保存'}) + return jsonify({'status': 'ok', 'msg': f'分包{index+1}/{total}已接收'}) + +# 版本信息接口 +@app.route('/api/version_info') +def version_info(): + # 实际可从设备、数据库或文件读取,这里演示写死 + verstr = 'Bootloader版本:V1.0\n固件版本:V1.3\n编译日期:2025.09.06\n固件日志:修复若干bug,提升稳定性。' + return verstr, 200, {'Content-Type': 'text/plain; charset=utf-8'} + +# 静态页面路由 +@app.route('/') +def index(): + return send_from_directory('.', 'firmware_upgrade.html') + +@app.route('/') +def static_files(filename): + # 允许访问同目录下的静态资源(如js/css等) + return send_from_directory('.', filename) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=True) diff --git a/verInfo.md b/verInfo.md new file mode 100644 index 0000000..1e34568 --- /dev/null +++ b/verInfo.md @@ -0,0 +1,3 @@ +版本:V1.0 +时间:23:54:15 2025年9月5日 +日志:https://kangax.github.io/html-minifier/ \ No newline at end of file diff --git a/win.app/default.aproj b/win.app/default.aproj new file mode 100644 index 0000000..d9ffda2 --- /dev/null +++ b/win.app/default.aproj @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/win.app/main.aardio b/win.app/main.aardio new file mode 100644 index 0000000..021bcb7 --- /dev/null +++ b/win.app/main.aardio @@ -0,0 +1,59 @@ +import win.ui; +/*DSG{{*/ +mainForm = win.form(text="aardio 工程";right=759;bottom=531;max=false) +mainForm.add() +/*}}*/ + +import web.view.7; +var wb = web.view(mainForm); + + + +import wsock.tcp.asynHttpServer; +var httpServer = wsock.tcp.asynHttpServer(); + +//这里可以指定 IP 和端口,不指定则自动分配空闲端口 +httpServer.start("127.0.0.1"); + +//服务端 aardio 支持模板语法: doc://language-reference/templating/syntax.md +var url = httpServer.getUrl("/web/firmware_upgrade.html"); //参数支持 aardio 工程嵌入资源目录路径 + +/* +import web.view; +var wb = web.view(winform); +*/ + +//用浏览器组件打开网页试试 +wb.go(url); + + +import fsys.update.simpleMain; +if( fsys.update.simpleMain( + "aardio 工程", + "https://list.020824.xyz/d/Pics/FW/demo/v1/.update-files/version.txt?sign=SVvWq8CBYyAObIvQ9yC2yNC4XMik-QX2zMFs8UvCeGs=:0", /*网址也可以改用目录名,并使用服务端代码动态返回version.txt*/ + "/download/update-files", /*绿色软件建议改为 io.appData("/软件厂商名/软件名字/update-files") */ + function(version,description,status){ + import console + console.log(version,description,status) + /* + version参数包含最新版本号, + description包含最新版本更新说明, + status参数值见下面的列表: + "ready": 下载已完成并准备更新, + "updated": 已更新到新版本并准备启动新版 + "complete": 当前已更新并已启动新版本主程序,所有操作已完成 + "latest": 已经是最新版不需要更新 + "failed": 出错了,description参数为错误信息 + + 这个回调函数不是必须的, + 在此检测更新代码之前或之后都可以在界面线程调用 + fsys.update.simpleMain.onStatusChanged 订阅更新状态变更信息。 + 该认阅回调函数的参数与上面的回调参数相同。 + */ + } )){ + return 0; //必须退出 main.aardio 以启动更新 +} + + +mainForm.show(); +win.loopMessage(); \ No newline at end of file diff --git a/win.app/web/firmware_upgrade.html b/win.app/web/firmware_upgrade.html new file mode 100644 index 0000000..388f70f --- /dev/null +++ b/win.app/web/firmware_upgrade.html @@ -0,0 +1,203 @@ + + + + + 设备固件更新 + + + + +
+

设备固件更新

+
+ + +
+
+ + +
+ +
+
+
+
+
+ + + diff --git a/说明.md b/说明.md new file mode 100644 index 0000000..0b7f17f --- /dev/null +++ b/说明.md @@ -0,0 +1,11 @@ +# 升级逻辑 +MCU端有bootloader和APP分区 +开机后默认进入bootloader,倒计时3s后跳转APP区。3s内请求页面则中断倒计时。 +bootloader有静态页面,通过页面更新固件。 +上传固件文件直接写入app区。 +固件文件前256字节为固件信息。 +固件信息包含版本信息、编译日期、主要更新日志等 + +# 静态页面 +html压缩 +https://kangax.github.io/html-minifier/ \ No newline at end of file