Wiznet以太网模块实现在线动态安装库和自动依赖安装-使用uPyPI包管理平台

0 阅读7分钟

引言

做 MicroPython 嵌入式开发的你,是不是每天都在被这些问题折磨? 写好的代码一运行就报错,翻遍半天发现​少装了一个依赖文件​;更崩溃的是,一个库要带好几个附属文件,漏一个就全盘报废。 这里,我们需要先引出依赖库的概念,在 MicroPython 开发中,依赖库的官方定义非常清晰:

你的主功能代码 / 主库,无法独立正常运行,必须调用其他独立的 .py 代码文件提供的​函数、类、硬件接口、算法逻辑​,这些被调用的外部代码文件,就是​依赖库​。

举一个嵌入式真实案例:用单片机驱动 MAX30102 传感器,做心率血氧检测

  • 主功能文件:heart_rate.py(负责:心率计算、数据显示、异常报警)
  • 依赖库文件 1:max30102.py(负责:传感器底层硬件读写、寄存器配置)
  • 依赖库文件 2:filter_lib.py(负责:波形滤波、噪声消除算法)

心率主程序 → 必须调用 传感器驱动 + 滤波算法 才能运行没有这两个依赖库,你的心率代码直接报错,完全跑不起来。

再延伸一个真实开发场景:用 Wiznet EVB-PICO 开发板,通过 Wiznet 网络模块实现​TCP 客户端通信​(最常用的网络功能,适配开发板核心特性):

  • 主功能文件:\tcp\_client.py\(负责:TCP 连接建立、数据发送/接收、连接状态监控)
  • 依赖库文件 1:\wiznet5k.py\(负责:Wiznet 网络模块底层硬件读写、SPI 接口配置、网络芯片初始化)
  • 依赖库文件 2:\socket\_utils.py\(负责:socket 通信工具函数、数据格式化、异常处理)

\TCP 客户端主程序\ → 必须调用 \Wiznet 网络驱动\ + \socket 工具库\ 才能运行,没有这两个依赖库,你的网络通信代码直接报错,Wiznet 模块无法初始化,完全跑不起来。

再延伸一个真实开发场景:

  • 你安装的某个 \Wiznet 网络透传库\,可能依赖 \wiznet5k.py\(底层驱动);
  • \wiznet5k.py\ 驱动,又依赖 \spi\_utils.py\(SPI 通信底层工具)。 这就是​多层嵌套依赖​,也是 Wiznet EVB-PICO 开发中最常见的依赖场景,和你平时开发网络功能时的实际情况完全一致。

疑问

小白灵魂拷问:我为什么不能把所有代码复制粘贴,揉进一个 .py 文件里?

这是 99% 的新手都会踩的坑,我结合​嵌入式开发实际工作​,告诉你绝对不能这么做的 4 个核心原因:

  1. 依赖库会​版本升级​,合并后彻底无法更新
  • max30102.py 驱动:作者会修复 bug、优化读取精度、升级硬件适配
  • filter_lib.py 算法:作者会优化滤波效果,降低误差
  • 如果你把所有代码合并成一个文件: 每次依赖库升级,你都要把整个大文件重写一遍,极易改错、删错代码;而​分离成独立依赖库​,只需要升级单个文件,主代码完全不用动。
  1. 依赖库是​通用工具​,可以复用到无数项目
  • max30102 驱动:不仅能做心率,还能做血氧、手势检测
  • 滤波算法库:不仅能给心率用,还能给温湿度、气压传感器用
  • 合并成一个文件后,代码彻底「锁死」在心率项目里,无法复用; 独立依赖库,所有项目直接调用,一次编写,无数次使用。
  1. 嵌套依赖会让代码彻底失控

一个心率功能,可能依赖 2 个库;这 2 个库,又各自依赖 2 个底层库;最终依赖关系会变成:主代码 → 4 个依赖库。如果全部合并成一个文件,代码会达到​几千行、几万行​,报错了根本找不到问题在哪。

  1. 开发维护成本爆炸

嵌入式开发大多是多人协作:A 工程师写传感器驱动,B 工程师写算法,C 工程师写主功能。代码分开(依赖库模式),大家互不干扰;合并成一个文件,所有人改同一个文件,直接冲突、代码报废。

这就是为什么,我们必须借助Wiznet以太网模块实现: 类 Python pip 的 在线自动安装 + 依赖自动加载:一行代码,自动装主库 + 所有依赖库 + 嵌套依赖,自动处理版本升级!

核心方案:uPyPi + mip

bc5c92f09a89e010152f6e8cd16e34e7.png

我们做的 uPyPi,就是 MicroPython 生态的​**PyPI(Python 官方包仓库)**​,配合 MicroPython 官方内置的 mipmip installs packages)工具,实现:

  • ✅ ​包托管​:驱动包、工具包一键上传到 uPyPi,全球开发者可访问
  • ✅ ​一键安装​:开发板连网,一行代码安装主包 + 所有依赖
  • ✅ ​依赖自动管理​:mip 自动递归安装声明的依赖包,无需手动操作
  • ✅ ​全芯片兼容​:纯软件包设计,支持所有 MicroPython 开发板,无硬件耦合
  • ✅ ​版本管理​:语义化版本控制,彻底避免版本冲突

从零实操:3 步实现借助Wiznet以太网实现动态安装依赖

关于如何下载上传驱动包可看wiki: freakstudio.cn/node/019c99… image.png

第一步:制作第三方依赖包 math_utils

这是一个纯软件工具包,无任何硬件代码,作为主包的依赖。

文件夹结构如下: 2102d3f9c193c7d7ce423978b6dd56fb.png

code/math_utils.py 代码如下:

image.png

package.json 完整配置为:

{
  "name": "math_utils",
  "version": "1.0.1",
  "description": "纯第三方软件依赖包(无硬件,测试用)",
  "author": "test",
  "license": "MIT",
  "chips": "all",
  "fw": "all",
  "_comments": {
    "chips": "该包支持运行的芯片型号,all表示无芯片限制",
    "fw": "该包依赖的特定固件如ulab、lvgl,all表示无固件依赖"
  },
  "urls": [
    [
      "math_utils.py",
      "code/math_utils.py"
    ]
  ]
}

打包文件夹,上传到 uPyPi 平台,获取包地址: image.png

第二步:制作主测试包 test_core

主包依赖上面的 math_utils,用户只需要安装主包,mip 自动安装依赖。 文件夹结构: image.png

code/test_core.py 代码如下: image.png

package.json 完整配置为:

"name": "test_core",
  "version": "1.0.4",
  "description": "纯软件测试主包(无硬件,依赖第三方包)",
  "author": "test",
  "license": "MIT",
  "chips": "all",
  "fw": "all",
  "_comments": {
    "chips": "该包支持运行的芯片型号,all表示无芯片限制",
    "fw": "该包依赖的特定固件如ulab、lvgl,all表示无固件依赖"
  },
  "urls": [
    [
      "test_core.py",
      "code/test_core.py"
    ]
  ],
  "deps": [
    ["https://upypi.net/pkgs/math_utils/1.0.1", "latest"]
  ]
}

这里,我们在deps字段声明主包依赖 math_utils 的 uPyPi 地址,mip 安装主包时,​自动递归安装依赖包​,用户完全不用管;`支持多个依赖,可嵌套依赖,mip自动处理所有依赖链。

打包文件夹,上传到 uPyPi 平台,获取主包地址:

image.png

第三步:Wiznet EVB-PICO 一键安装 + 测试

完整代码如下:

# ==================== Wiznet EVB-PICO 以太网纯软件测试(无硬件耦合) ====================
# Python env   : MicroPython v1.23.0 on Wiznet W5500
# -*- coding: utf-8 -*-        
# @Time    : 2024/8/7 下午9:12   
# @Author  : 李清水            
# @File    : main.py       
# @Description : Wiznet以太网 + uPyPi自动安装依赖 纯测试代码

import time
import network
import mip
from machine import Pin, SPI

# ==================== 配置 ====================
# 以太网静态IP配置(Wiznet EVB-PICO)
ETH_IP = '192.168.1.20'
ETH_SUBNET = '255.255.255.0'
ETH_GATEWAY = '192.168.1.1'
ETH_DNS = '8.8.8.8'
# uPyPi 主测试包地址(替换成upypi的地址)
MAIN_PACKAGE = "https://upypi.net/pkgs/test_core/1.0.4"

# ==================== 以太网连接(仅修改这部分!) ====================
def connect():
    try:
        print("初始化 Wiznet 以太网...")
        # W5500 SPI 初始化(EVB-PICO 标准引脚)
        spi = SPI(0, 2000000, mosi=Pin(19), miso=Pin(16), sck=Pin(18))
        nic = network.WIZNET5K(spi, Pin(17), Pin(20))
        nic.active(True)
        # 配置静态IP
        nic.ifconfig((ETH_IP, ETH_SUBNET, ETH_GATEWAY, ETH_DNS))
        
        # 等待以太网连接
        timeout = 10
        while not nic.isconnected() and timeout > 0:
            timeout -= 1
            time.sleep(1)
        
        if nic.isconnected():
            print("以太网连接成功!IP:", nic.ifconfig()[0])
            return True
        else:
            print("以太网连接失败!")
            return False
    except Exception as e:
        print("以太网初始化失败:", e)
        return False

# ==================== 远程安装(自动装第三方软件依赖)【完全不变】 ====================
def install():
    print("开始安装:主包 + 第三方纯软件依赖...")
    mip.install(MAIN_PACKAGE)
    print("✅ 安装完成!无任何硬件依赖")

# ==================== 纯软件测试(无硬件)【完全不变】 ====================
def test():
    # 导入安装好的纯软件包
    from test_core import TestCore
    test = TestCore()
    
    # 运行测试
    print("\n===== 纯软件测试结果 =====")
    print(test.test_add(10, 20))
    print(test.test_multiply(10, 20))
    print("=========================\n")
    print("🎉 测试成功!依赖安装正常")

# ==================== 主程序【完全不变】 ====================
if __name__ == "__main__":
    if connect():
        install()
        test()

运行结果如下: image.png

我们也可以使用本地安装方式: 425c8df75b87b45e580666af2ec8e522.png

可以看到:Wiznet成功通过 MicroPython 的 mip 工具实现了类 Python pip 的在线动态安装能力,设备连接 WiFi 后自动拉取并部署了主测试包 test_core.py 及其第三方依赖包 math_utils.py/lib 目录。 后续纯软件测试验证了主包对依赖库的正常调用,加法、乘法运算结果完全正确,完整实现了嵌入式设备端的在线库安装、依赖自动管理与功能验证,彻底解决了传统手动拷贝文件、漏装依赖的开发痛点,实现了与 PC 端 Python 开发一致的标准化包管理体验。

bc5c92f09a89e010152f6e8cd16e34e7.png

51e33f7e0189f70fb697e4c961bb767e.png