Mind+ MicroPython 积木模式扩展开发手册¶
本文档将指导开发者创建适用于 Mind+ MicroPython 积木模式的扩展。
1. 扩展包文件结构¶
Mind+ V2 扩展库基于模板仓库 mindplus-ext2-builder 开发,克隆或下载该仓库得到的目录既是开发工程,也是最终提交收录的仓库,结构如下:
ext2-mpy-name/ # 仓库名称可参考,以ext2-mpy-为前缀
├── extension/ # 扩展库源码目录
│ ├── func.js # 生成代码
│ ├── index.js # 图形块定义主文件
│ ├── public/ # 静态资源目录
│ │ ├── cover.png # 封面图
│ │ ├── config.json # 配置文件
│ │ └── libraries/ # MicroPython 扩展库文件目录 (可选)
│ │ └── df_xxx_lib.py # MicroPython 库文件
│ ├── icon/ # 图标资源目录
│ │ ├── blockIcon.svg # 积木图标 (建议使用白色)
│ │ └── menuIcon.svg # 分类菜单图标 (建议使用积木颜色)
│ └── locales/ # 国际化语言包
│ ├── zh-cn.json # 简体中文翻译
│ ├── en.json # 英文翻译
│ └── index.js # 翻译入口文件 (构建时自动生成)
├── scripts/
├── utils/
├── ...
└── README.md
extension/及README.md需要自己编写,其余部分是固定的构建环境,无需修改
2. 配置文件 (public/config.json)¶
config.json 是扩展的核心配置文件,定义了扩展的基本信息、支持的设备以及依赖库。
示例配置¶
{
"id": "DFR0024",
"author": "yourUserId",
"version": "0.0.1",
"name": {
"zh-cn": "DS18B20温度传感器",
"en": "DS18B20 Temperature Sensor"
},
"description": {
"zh-cn": "测量温度,范围-55~+125℃",
"en": "Detect ambient temperature with large range of -55~+125℃"
},
"cover": "cover.png",
"isDevice": false,
"mode": "micropython-block",
"main": "main.js",
"supportDevices": {
"dev-DFRobot-handpyEsp32": "^0.0.1",
"dev-DFRobot-unihikerK10": "^0.0.1"
},
"meta": {
"runtimeVersion": "0.0.1"
},
"sku": "DFR0024",
"compatibilityId": ""
}
关键字段说明¶
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
id | 必填 | string | 扩展唯一标识符,建议仅包含字母和数字 |
author | 必填 | string | 作者 ID |
version | 必填 | string | 扩展版本号 |
name | 必填 | object | 多语言名称 |
description | 必填 | object | 多语言描述 |
cover | 必填 | string | 封面图片文件名,需位于 public 目录下 |
isDevice | 必填 | boolean | 模块扩展固定为 false |
mode | 必填 | string | 模式,此处应为 micropython-block |
main | 必填 | string | 入口文件路径,一般为编译后的 main.js |
supportDevices | 必填 | object | 支持的主控板及版本要求 |
meta.runtimeVersion | 必填 | string | 扩展 runtime 接口版本(用于控制 API 兼容性) |
sku | 可选 | string | 硬件产品型号,多个型号用|隔开;没有则留空 |
compatibilityId | 可选 | string | Mind+V1.x用户库兼容字段;没有则留空 |
不需要使用可选字段时,
sku、compatibilityId写空字符串:
meta.runtimeVersion¶
runtimeVersion 表示开发扩展时依赖的 runtime API 最低版本,以 通用参考-Runtime接口参考 为准
不可随意设置一个很大的版本号,否则扩展只能在高版本中加载,兼容性会变差
compatibilityId(仅需兼容V1.x库时使用)¶
如果当前开发的库由Mind+V1.x库转换而来,或者需要在Mind+V2.x中打开Mind+V1.x包含同样用户库的项目文件,则可以使用此字段指定V1.x用户库的id。
注意:如需兼容V1.x版本扩展,需要保证V2扩展库index.js中积木的opcode与V1.x版本扩展库main.ts中对应积木的函数名称一致,并保证积木类型、数量、输入框数量和类型、兼容主板等信息保持一致,并在Mind+V1版本中加载旧扩展的所有积木保存项目,然后在Mind+V2中需要保证可以正常打开。
参考示例:
- V1用户库:https://gitee.com/liliang9693/ext-ds1302
- V2用户库:https://gitee.com/mind-plus/ext2-ds1302
格式:"compatibilityId": "[author]-[id]-thirdex"
例如:
- 在V1的扩展库中config.json中,
"id": "oled12864","author": "DFRobot",则在V2的扩展库中的config.json中设置"compatibilityId": "dfrobot-oled12864-thirdex" - 另外也可以直接查看V1导出的.mpext文件名,例如
dfrobot-oled12864-thirdex-V0.0.3.mpext,不带版本号和后缀即为compatibilityId的值;或者也可以在Mind+V2中打开包含这个库的V1的项目文件,会提示“项目中存在尚未兼容的扩展: dfrobot-oled12864-thirdex”,提示语中的字段即为compatibilityId的值。
3. 图形块描述文件 (index.js)¶
index.js 是扩展的入口文件,负责定义图形块(Block)的外观、参数以及与 Mind+ 运行时的交互。
类结构定义¶
模块扩展通过 runtime.getCurrentDeviceId() 获取当前主控标识,可按当前主控动态调整积木菜单。
import ArgumentType from '../utils/argument-type';
import BlockType from '../utils/block-type';
import blockIconURI from './icon/blockIcon.svg';
import menuIconURI from './icon/menuIcon.svg';
import Func from './func'; // 引入生成代码类
import { setLocaleData, formatMessage, setLocale } from '../utils/translation';
import LocaleData from "./locales";
setLocaleData(LocaleData);
class Extension {
constructor(runtime, extensionId) {
this.runtime = runtime;
// 初始化生成代码的实例
this.funcs = new Func(runtime, extensionId);
}
// 必须实现:切换语言的钩子
setLocale(locale) {
setLocale(locale);
}
// 必须实现:返回生成代码的实例
getCodePrimitives() {
return this.funcs;
}
// 必须实现:返回扩展的详细信息
getInfo() {
return {
name: 'SEN0001',
blockIconURI: blockIconURI,
menuIconURI: menuIconURI,
color1: '#FF9F06',
color2: '#DD8A04',
color3: '#BE7705',
blocks: [
{
opcode: 'readUltrasound',
blockType: BlockType.REPORTER,
text: formatMessage({
id: 'gui.blocklyText.sen0001.readUltrasound',
description: 'Label for the blocklyText of init',
default: 'ulrasonic sensor unit init'
}),
arguments: {}
}
],
menus: {},
};
}
}
export default Extension;
关键方法说明¶
| 方法 | 作用 | 是否必须 |
|---|---|---|
getCodePrimitives() | 返回积木代码生成方法对象(Func 实例) | 必须 |
getInfo() | 返回扩展积木元信息(名称、图标、颜色、blocks、menus) | 必须 |
setLocale(locale) | 响应 IDE 语言切换 | 必须 |
4. 代码生成文件 (func.js)¶
func.js 负责将图形块转换为 MicroPython 代码。函数名必须与 index.js 中积木的 opcode 一一对应。
核心结构¶
class Func {
constructor(runtime, extensionId) {
this.runtime = runtime;
}
readUltrasound(generator, block, parameter) {
// generator: 代码生成器,提供 addImport / addInit 等 API
// block: 积木实例
// parameter: 积木参数,通过 parameter.XXX.code 取值
generator.addImport('import time');
}
}
export default Func;
5. 翻译资源文件 (locales)¶
locales/zh-cn.json:
6. MicroPython 生成代码 API¶
在 func.js 的 opcode 方法中,通过 generator 调用以下 API。
1. 导入库模块 addImport¶
addImport(code: string)
- 功能:导入 MicroPython 库模块
- 参数:
code— 实际生成代码(去掉空格后作为 id) - 覆盖规则:相同 id 时覆盖旧代码
- 示例:
- 生成效果:
2. 添加全局变量 addVariable¶
addVariable(id: string, code: string, coverage: boolean = false)
- 功能:定义全局变量
- 参数:
id— 变量标识符code— 实际生成代码coverage— 是否覆盖同 id 变量(默认false)- 示例:
- 生成效果:
3. 添加初始化区域代码 addInit¶
addInit(id: string, code: string, priority: number = 0, isCover: boolean = false)
- 功能:添加初始化代码(位于
while True:之前) - 参数:
id— 标识符code— 实际生成代码priority— 优先级(0–9,9 最靠前,默认 0)isCover— 是否覆盖同 id 代码(默认false)- 示例:
- 生成效果:
4. 添加全局函数 addFunction¶
addFunction(code: string, isCover: boolean = false)
- 功能:添加全局函数(函数名作为 id)
- 参数:
code— 完整函数代码isCover— 是否覆盖同名函数(默认false)- 示例:
- 生成效果:
5. 添加 while True 头部代码 addWhile¶
Mind+V2.0.8及以上版本可用
addWhile(id: string, code: string, isCover: boolean = false)
- 功能:在
while True:循环头部插入代码 - 参数:
id— 标识符code— 实际生成代码isCover— 是否覆盖同 id 代码(默认false)- 示例:
- 生成效果:
6. 创建事件回调函数¶
- 返回以
def开头的函数定义字符串,作为事件积木回调: - 生成效果:
7. 在积木位置生成 code¶
- 位置:
while True:或积木当前位置 - 规则:
- 返回字符串直接插入代码
- 返回数组
[code, priority]处理运算符优先级 - 示例:
- 生成效果:
8. 获取已生成的初始化代码 getSetup¶
getSetup(id: string)
- 功能:获取指定 id 的初始化区域代码,常用于合并中断触发条件等场景
const lastInitCode = generator.getSetup(`button_${button}.irq`);
if (lastInitCode && lastInitCode.indexOf(mode) === -1) {
// 已有另一沿的中断配置,合并为双边沿
}
9. 获取已生成的静态函数 getStaticFunction¶
getStaticFunction(funcName: string)
- 功能:获取已生成的同名函数代码,便于在多个积木间复用 / 合并定时器回调等逻辑
const lastFuncCode = generator.getStaticFunction('timer13_tick');
if (lastFuncCode && lastFuncCode.indexOf('dht11') === -1) {
// 扩展已有定时器回调
}
10. 进阶用法¶
- 添加注释
addComment(id: string, comment: any, position: number, isCover: boolean) - 添加错误提示
addErrorPrompt(message: string) - 获取资源路径
get_asset_path_by_name(生成代码中可用的全局函数)